1
ARM queue, various patches accumulated over the Christmas break.
1
target-arm queue: this clears out a bunch of patches I'd sent over
2
the last coupled of weeks that have now got reviewed. Mostly
3
this is MPS2 device support improvements, put there is also
4
more of the incremental work towards supporting AArch32 Hyp mode,
5
a floating point bugfix, and the raspi framebuffer viewport support.
2
6
7
thanks
3
-- PMM
8
-- PMM
4
9
5
The following changes since commit 612061b277915fadd80631eb7a6926f48a110c44:
10
The following changes since commit 5ccac548faf041ff5229a8e8342e3be14a34c8af:
6
11
7
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-10' into staging (2018-01-11 11:52:40 +0000)
12
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging (2018-08-23 17:35:48 +0100)
8
13
9
are available in the git repository at:
14
are available in the Git repository at:
10
15
11
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180111
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180824
12
17
13
for you to fetch changes up to 0cf09852015e47a5fbb974ff7ac320366afd21ee:
18
for you to fetch changes up to 30a719e3cb5c5367f3651eba8fa935634bfee286:
14
19
15
hw/intc/arm_gic: reserved register addresses are RAZ/WI (2018-01-11 13:25:40 +0000)
20
hw/arm/mps2: Fix ID register errors on AN511 and AN385 (2018-08-24 10:22:44 +0100)
16
21
17
----------------------------------------------------------------
22
----------------------------------------------------------------
18
target-arm queue:
23
target-arm queue:
19
* add aarch64_be linux-user target
24
* Fix rounding errors in scaling float-to-int and int-to-float operations
20
* Virt: ACPI: fix qemu assert due to re-assigned table data address
25
* Connect virtualization-related IRQs and memory regions of GICv2
21
* imx_fec: various bug fixes and cleanups
26
in boards that use Cortex-A7 or Cortex-A15
22
* hw/timer/pxa2xx_timer: replace hw_error() -> qemu_log_mask()
27
* Support taking exceptions to AArch32 Hyp mode
23
* hw/sd/pxa2xx_mmci: add read/write() trace events
28
* Clear CPSR.IL and CPSR.J on 32-bit exception entry
24
* linux-user/arm/nwfpe: Check coprocessor number for FPA emulation
29
(a minor bug fix that won't affect non-buggy guest code)
25
* target/arm: Make disas_thumb2_insn() generate its own UNDEF exceptions
30
* mps2-an505: Implement various missing devices:
26
* hw/intc/arm_gicv3: Make reserved register addresses RAZ/WI
31
dual timer, watchdogs, counters in the FPGAIO registers,
27
* hw/intc/arm_gic: reserved register addresses are RAZ/WI
32
some missing ID/control registers, TrustZone Master Security
33
Controllers, PL081 DMA controllers, PL022 SPI controllers
34
* correct ID register values for mps2-an385, -an511, -an505
35
* fix some hardcoded tabs in untouched backwaters of the
36
target/arm codebase
37
* raspi: Refactor framebuffer property handling code and implement
38
support for the virtual framebuffer/viewport
28
39
29
----------------------------------------------------------------
40
----------------------------------------------------------------
30
Andrey Smirnov (11):
41
Peter Maydell (48):
31
imx_fec: Do not link to netdev
42
hw/intc/arm_gic: Make per-cpu GICH memory regions 0x200 bytes large
32
imx_fec: Refactor imx_eth_enable_rx()
43
hw/arm/vexpress: Connect VIRQ and VFIQ
33
imx_fec: Change queue flushing heuristics
44
hw/arm/highbank: Connect VIRQ and VFIQ
34
imx_fec: Move Tx frame buffer away from the stack
45
hw/arm/fsl-imx6ul: Connect VIRQ and VFIQ
35
imx_fec: Use ENET_FTRL to determine truncation length
46
hw/arm/fsl-imx6ul: Connect VIRQ and VFIQ
36
imx_fec: Use MIN instead of explicit ternary operator
47
hw/cpu/a15mpcore: If CPU has EL2, enable it on the GIC and wire it up
37
imx_fec: Emulate SHIFT16 in ENETx_RACC
48
hw/arm/vexpress: Don't set info->secure_boot if CPU doesn't have EL3
38
imx_fec: Add support for multiple Tx DMA rings
49
hw/arm/vexpress: Add "virtualization" property controlling presence of EL2
39
imx_fec: Use correct length for packet size
50
target/arm: Implement RAZ/WI HACTLR2
40
imx_fec: Fix a typo in imx_enet_receive()
51
target/arm: Implement AArch32 HCR and HCR2
41
imx_fec: Reserve full FSL_IMX25_FEC_SIZE page for the register file
52
target/arm: Factor out code for taking an AArch32 exception
53
target/arm: Implement support for taking exceptions to Hyp mode
54
target/arm: Clear CPSR.IL and CPSR.J on 32-bit exception entry
55
hw/arm/boot: AArch32 kernels should be started in Hyp mode if available
56
hw/misc/mps2-fpgaio: Implement 1Hz and 100Hz counters
57
hw/misc/mps2-fpgaio: Implement PSCNTR and COUNTER
58
hw/timer/cmsdk-apb-dualtimer: Implement CMSDK dual timer module
59
hw/arm/iotkit: Wire up the dualtimer
60
hw/arm/mps2: Wire up dual-timer in mps2-an385 and mps2-an511
61
hw/arm/iotkit: Wire up the watchdogs
62
hw/arm/iotkit: Wire up the S32KTIMER
63
hw/misc/iotkit-sysctl: Implement IoTKit system control element
64
hw/misc/iotkit-sysinfo: Implement IoTKit system information block
65
hw/misc/iotkit: Wire up the sysctl and sysinfo register blocks
66
hw/misc/tz-msc: Model TrustZone Master Security Controller
67
hw/misc/iotkit-secctl: Wire up registers for controlling MSCs
68
hw/arm/iotkit: Wire up the lines for MSCs
69
hw/arm/mps2-tz: Create PL081s and MSCs
70
hw/ssi/pl022: Allow use as embedded-struct device
71
hw/ssi/pl022: Set up reset function in class init
72
hw/ssi/pl022: Don't directly call vmstate_register()
73
hw/ssi/pl022: Use DeviceState::realize rather than SysBusDevice::init
74
hw/ssi/pl022: Correct wrong value for PL022_INT_RT
75
hw/ssi/pl022: Correct wrong DMACR and ICR handling
76
hw/arm/mps2-tz: Instantiate SPI controllers
77
hw/arm/mps2-tz: Fix MPS2 SCC config register values
78
target/arm: Untabify translate.c
79
target/arm: Untabify iwmmxt_helper.c
80
target/arm: Remove a handful of stray tabs
81
hw/misc/bcm2835_fb: Move config fields to their own struct
82
hw/misc/bcm2835_property: Track fb settings using BCM2835FBConfig
83
hw/display/bcm2835_fb: Drop unused size and pitch fields
84
hw/display/bcm2835_fb: Reset resolution, etc correctly
85
hw/display/bcm2835_fb: Abstract out calculation of pitch, size
86
hw/display/bcm2835_fb: Fix handling of virtual framebuffer
87
hw/display/bcm2835_fb: Validate config settings
88
hw/display/bcm2835_fb: Validate bcm2835_fb_mbox_push() config
89
hw/arm/mps2: Fix ID register errors on AN511 and AN385
42
90
43
Michael Weiser (8):
91
Richard Henderson (4):
44
linux-user: Add support for big-endian aarch64
92
softfloat: Add scaling int-to-float routines
45
linux-user: Add separate aarch64_be uname
93
softfloat: Add scaling float-to-int routines
46
linux-user: Fix endianess of aarch64 signal trampoline
94
target/arm: Use the int-to-float-scale softfloat routines
47
configure: Add aarch64_be-linux-user target
95
target/arm: Use the float-to-int-scale softfloat routines
48
linux-user: Add aarch64_be magic numbers to qemu-binfmt-conf.sh
49
linux-user: Separate binfmt arm CPU families
50
linux-user: Activate armeb handler registration
51
target/arm: Fix stlxp for aarch64_be
52
96
53
Peter Maydell (4):
97
hw/misc/Makefile.objs | 3 +
54
linux-user/arm/nwfpe: Check coprocessor number for FPA emulation
98
hw/timer/Makefile.objs | 1 +
55
target/arm: Make disas_thumb2_insn() generate its own UNDEF exceptions
99
include/fpu/softfloat.h | 169 +++++++---
56
hw/intc/arm_gicv3: Make reserved register addresses RAZ/WI
100
include/hw/arm/iotkit.h | 25 +-
57
hw/intc/arm_gic: reserved register addresses are RAZ/WI
101
include/hw/display/bcm2835_fb.h | 59 +++-
102
include/hw/misc/iotkit-secctl.h | 14 +
103
include/hw/misc/iotkit-sysctl.h | 49 +++
104
include/hw/misc/iotkit-sysinfo.h | 37 +++
105
include/hw/misc/mps2-fpgaio.h | 10 +
106
include/hw/misc/tz-msc.h | 79 +++++
107
include/hw/ssi/pl022.h | 51 +++
108
include/hw/timer/cmsdk-apb-dualtimer.h | 72 ++++
109
target/arm/cpu.h | 16 +-
110
fpu/softfloat.c | 579 ++++++++++++++++++++++++++-------
111
hw/arm/boot.c | 11 +
112
hw/arm/fsl-imx6ul.c | 4 +
113
hw/arm/fsl-imx7.c | 4 +
114
hw/arm/highbank.c | 6 +
115
hw/arm/iotkit.c | 114 ++++++-
116
hw/arm/mps2-tz.c | 142 +++++++-
117
hw/arm/mps2.c | 17 +-
118
hw/arm/vexpress.c | 64 +++-
119
hw/cpu/a15mpcore.c | 31 +-
120
hw/display/bcm2835_fb.c | 218 ++++++++-----
121
hw/intc/arm_gic.c | 2 +-
122
hw/misc/bcm2835_property.c | 123 ++++---
123
hw/misc/iotkit-secctl.c | 73 ++++-
124
hw/misc/iotkit-sysctl.c | 261 +++++++++++++++
125
hw/misc/iotkit-sysinfo.c | 128 ++++++++
126
hw/misc/mps2-fpgaio.c | 146 ++++++++-
127
hw/misc/tz-msc.c | 308 ++++++++++++++++++
128
hw/ssi/pl022.c | 57 ++--
129
hw/timer/cmsdk-apb-dualtimer.c | 515 +++++++++++++++++++++++++++++
130
target/arm/arm-semi.c | 2 +-
131
target/arm/helper.c | 342 +++++++++++++------
132
target/arm/iwmmxt_helper.c | 234 ++++++-------
133
target/arm/translate.c | 122 +++----
134
MAINTAINERS | 10 +
135
default-configs/arm-softmmu.mak | 4 +
136
hw/misc/trace-events | 16 +
137
hw/timer/trace-events | 5 +
138
41 files changed, 3405 insertions(+), 718 deletions(-)
139
create mode 100644 include/hw/misc/iotkit-sysctl.h
140
create mode 100644 include/hw/misc/iotkit-sysinfo.h
141
create mode 100644 include/hw/misc/tz-msc.h
142
create mode 100644 include/hw/ssi/pl022.h
143
create mode 100644 include/hw/timer/cmsdk-apb-dualtimer.h
144
create mode 100644 hw/misc/iotkit-sysctl.c
145
create mode 100644 hw/misc/iotkit-sysinfo.c
146
create mode 100644 hw/misc/tz-msc.c
147
create mode 100644 hw/timer/cmsdk-apb-dualtimer.c
58
148
59
Philippe Mathieu-Daudé (2):
60
hw/timer/pxa2xx_timer: replace hw_error() -> qemu_log_mask()
61
hw/sd/pxa2xx_mmci: add read/write() trace events
62
63
Zhaoshenglong (1):
64
Virt: ACPI: fix qemu assert due to re-assigned table data address
65
66
configure | 5 +-
67
include/hw/arm/fsl-imx25.h | 1 -
68
include/hw/net/imx_fec.h | 27 +++-
69
linux-user/aarch64/target_syscall.h | 4 +
70
hw/arm/fsl-imx6.c | 1 +
71
hw/arm/virt-acpi-build.c | 18 ++-
72
hw/intc/arm_gic.c | 5 +-
73
hw/intc/arm_gicv3_dist.c | 13 ++
74
hw/intc/arm_gicv3_its_common.c | 8 +-
75
hw/intc/arm_gicv3_redist.c | 13 ++
76
hw/net/imx_fec.c | 210 +++++++++++++++++++++++-------
77
hw/sd/pxa2xx_mmci.c | 78 +++++++----
78
hw/timer/pxa2xx_timer.c | 17 ++-
79
linux-user/arm/nwfpe/fpa11.c | 9 ++
80
linux-user/main.c | 6 +
81
linux-user/signal.c | 10 +-
82
target/arm/helper-a64.c | 7 +-
83
target/arm/translate.c | 23 ++--
84
default-configs/aarch64_be-linux-user.mak | 1 +
85
hw/sd/trace-events | 4 +
86
scripts/qemu-binfmt-conf.sh | 15 ++-
87
21 files changed, 356 insertions(+), 119 deletions(-)
88
create mode 100644 default-configs/aarch64_be-linux-user.mak
89
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Frame truncation length, TRUNC_FL, is determined by the contents of
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
ENET_FTRL register, so convert the code to use it instead of a
4
Message-id: 20180814002653.12828-2-richard.henderson@linaro.org
5
hardcoded constant.
6
7
To avoid the case where TRUNC_FL is greater that ENET_MAX_FRAME_SIZE,
8
increase the value of the latter to its theoretical maximum of 16K.
9
10
Cc: Peter Maydell <peter.maydell@linaro.org>
11
Cc: Jason Wang <jasowang@redhat.com>
12
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Cc: qemu-devel@nongnu.org
14
Cc: qemu-arm@nongnu.org
15
Cc: yurovsky@gmail.com
16
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
7
---
20
include/hw/net/imx_fec.h | 3 ++-
8
include/fpu/softfloat.h | 56 ++++++++----
21
hw/net/imx_fec.c | 4 ++--
9
fpu/softfloat.c | 188 +++++++++++++++++++++++++++++-----------
22
2 files changed, 4 insertions(+), 3 deletions(-)
10
2 files changed, 179 insertions(+), 65 deletions(-)
23
11
24
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
12
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
25
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/net/imx_fec.h
14
--- a/include/fpu/softfloat.h
27
+++ b/include/hw/net/imx_fec.h
15
+++ b/include/fpu/softfloat.h
28
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ enum {
29
#define ENET_TCCR3 393
17
/*----------------------------------------------------------------------------
30
#define ENET_MAX 400
18
| Software IEC/IEEE integer-to-floating-point conversion routines.
31
19
*----------------------------------------------------------------------------*/
32
-#define ENET_MAX_FRAME_SIZE 2032
20
+
33
21
+float16 int16_to_float16_scalbn(int16_t a, int, float_status *status);
34
/* EIR and EIMR */
22
+float16 int32_to_float16_scalbn(int32_t a, int, float_status *status);
35
#define ENET_INT_HB (1 << 31)
23
+float16 int64_to_float16_scalbn(int64_t a, int, float_status *status);
36
@@ -XXX,XX +XXX,XX @@
24
+float16 uint16_to_float16_scalbn(uint16_t a, int, float_status *status);
37
#define ENET_RCR_NLC (1 << 30)
25
+float16 uint32_to_float16_scalbn(uint32_t a, int, float_status *status);
38
#define ENET_RCR_GRS (1 << 31)
26
+float16 uint64_to_float16_scalbn(uint64_t a, int, float_status *status);
39
27
+
40
+#define ENET_MAX_FRAME_SIZE (1 << ENET_RCR_MAX_FL_LENGTH)
28
+float16 int16_to_float16(int16_t a, float_status *status);
41
+
29
+float16 int32_to_float16(int32_t a, float_status *status);
42
/* TCR */
30
+float16 int64_to_float16(int64_t a, float_status *status);
43
#define ENET_TCR_GTS (1 << 0)
31
+float16 uint16_to_float16(uint16_t a, float_status *status);
44
#define ENET_TCR_FDEN (1 << 2)
32
+float16 uint32_to_float16(uint32_t a, float_status *status);
45
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
33
+float16 uint64_to_float16(uint64_t a, float_status *status);
34
+
35
+float32 int16_to_float32_scalbn(int16_t, int, float_status *status);
36
+float32 int32_to_float32_scalbn(int32_t, int, float_status *status);
37
+float32 int64_to_float32_scalbn(int64_t, int, float_status *status);
38
+float32 uint16_to_float32_scalbn(uint16_t, int, float_status *status);
39
+float32 uint32_to_float32_scalbn(uint32_t, int, float_status *status);
40
+float32 uint64_to_float32_scalbn(uint64_t, int, float_status *status);
41
+
42
float32 int16_to_float32(int16_t, float_status *status);
43
float32 int32_to_float32(int32_t, float_status *status);
44
-float64 int16_to_float64(int16_t, float_status *status);
45
-float64 int32_to_float64(int32_t, float_status *status);
46
+float32 int64_to_float32(int64_t, float_status *status);
47
float32 uint16_to_float32(uint16_t, float_status *status);
48
float32 uint32_to_float32(uint32_t, float_status *status);
49
+float32 uint64_to_float32(uint64_t, float_status *status);
50
+
51
+float64 int16_to_float64_scalbn(int16_t, int, float_status *status);
52
+float64 int32_to_float64_scalbn(int32_t, int, float_status *status);
53
+float64 int64_to_float64_scalbn(int64_t, int, float_status *status);
54
+float64 uint16_to_float64_scalbn(uint16_t, int, float_status *status);
55
+float64 uint32_to_float64_scalbn(uint32_t, int, float_status *status);
56
+float64 uint64_to_float64_scalbn(uint64_t, int, float_status *status);
57
+
58
+float64 int16_to_float64(int16_t, float_status *status);
59
+float64 int32_to_float64(int32_t, float_status *status);
60
+float64 int64_to_float64(int64_t, float_status *status);
61
float64 uint16_to_float64(uint16_t, float_status *status);
62
float64 uint32_to_float64(uint32_t, float_status *status);
63
-floatx80 int32_to_floatx80(int32_t, float_status *status);
64
-float128 int32_to_float128(int32_t, float_status *status);
65
-float32 int64_to_float32(int64_t, float_status *status);
66
-float64 int64_to_float64(int64_t, float_status *status);
67
-floatx80 int64_to_floatx80(int64_t, float_status *status);
68
-float128 int64_to_float128(int64_t, float_status *status);
69
-float32 uint64_to_float32(uint64_t, float_status *status);
70
float64 uint64_to_float64(uint64_t, float_status *status);
71
+
72
+floatx80 int32_to_floatx80(int32_t, float_status *status);
73
+floatx80 int64_to_floatx80(int64_t, float_status *status);
74
+
75
+float128 int32_to_float128(int32_t, float_status *status);
76
+float128 int64_to_float128(int64_t, float_status *status);
77
float128 uint64_to_float128(uint64_t, float_status *status);
78
79
/*----------------------------------------------------------------------------
80
@@ -XXX,XX +XXX,XX @@ int64_t float16_to_int64(float16, float_status *status);
81
uint64_t float16_to_uint64(float16 a, float_status *status);
82
int64_t float16_to_int64_round_to_zero(float16, float_status *status);
83
uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *status);
84
-float16 int16_to_float16(int16_t a, float_status *status);
85
-float16 int32_to_float16(int32_t a, float_status *status);
86
-float16 int64_to_float16(int64_t a, float_status *status);
87
-float16 uint16_to_float16(uint16_t a, float_status *status);
88
-float16 uint32_to_float16(uint32_t a, float_status *status);
89
-float16 uint64_to_float16(uint64_t a, float_status *status);
90
91
/*----------------------------------------------------------------------------
92
| Software half-precision operations.
93
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
46
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/net/imx_fec.c
95
--- a/fpu/softfloat.c
48
+++ b/hw/net/imx_fec.c
96
+++ b/fpu/softfloat.c
49
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
97
@@ -XXX,XX +XXX,XX @@ FLOAT_TO_UINT(64, 64)
50
crc_ptr = (uint8_t *) &crc;
98
* to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
51
99
*/
52
/* Huge frames are truncted. */
100
53
- if (size > ENET_MAX_FRAME_SIZE) {
101
-static FloatParts int_to_float(int64_t a, float_status *status)
54
- size = ENET_MAX_FRAME_SIZE;
102
+static FloatParts int_to_float(int64_t a, int scale, float_status *status)
55
+ if (size > s->regs[ENET_FTRL]) {
103
{
56
+ size = s->regs[ENET_FTRL];
104
- FloatParts r = {};
57
flags |= ENET_BD_TR | ENET_BD_LG;
105
+ FloatParts r = { .sign = false };
106
+
107
if (a == 0) {
108
r.cls = float_class_zero;
109
- r.sign = false;
110
- } else if (a == (1ULL << 63)) {
111
- r.cls = float_class_normal;
112
- r.sign = true;
113
- r.frac = DECOMPOSED_IMPLICIT_BIT;
114
- r.exp = 63;
115
} else {
116
- uint64_t f;
117
- if (a < 0) {
118
- f = -a;
119
- r.sign = true;
120
- } else {
121
- f = a;
122
- r.sign = false;
123
- }
124
- int shift = clz64(f) - 1;
125
+ uint64_t f = a;
126
+ int shift;
127
+
128
r.cls = float_class_normal;
129
- r.exp = (DECOMPOSED_BINARY_POINT - shift);
130
- r.frac = f << shift;
131
+ if (a < 0) {
132
+ f = -f;
133
+ r.sign = true;
134
+ }
135
+ shift = clz64(f) - 1;
136
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
137
+
138
+ r.exp = DECOMPOSED_BINARY_POINT - shift + scale;
139
+ r.frac = (shift < 0 ? DECOMPOSED_IMPLICIT_BIT : f << shift);
58
}
140
}
59
141
142
return r;
143
}
144
145
+float16 int64_to_float16_scalbn(int64_t a, int scale, float_status *status)
146
+{
147
+ FloatParts pa = int_to_float(a, scale, status);
148
+ return float16_round_pack_canonical(pa, status);
149
+}
150
+
151
+float16 int32_to_float16_scalbn(int32_t a, int scale, float_status *status)
152
+{
153
+ return int64_to_float16_scalbn(a, scale, status);
154
+}
155
+
156
+float16 int16_to_float16_scalbn(int16_t a, int scale, float_status *status)
157
+{
158
+ return int64_to_float16_scalbn(a, scale, status);
159
+}
160
+
161
float16 int64_to_float16(int64_t a, float_status *status)
162
{
163
- FloatParts pa = int_to_float(a, status);
164
- return float16_round_pack_canonical(pa, status);
165
+ return int64_to_float16_scalbn(a, 0, status);
166
}
167
168
float16 int32_to_float16(int32_t a, float_status *status)
169
{
170
- return int64_to_float16(a, status);
171
+ return int64_to_float16_scalbn(a, 0, status);
172
}
173
174
float16 int16_to_float16(int16_t a, float_status *status)
175
{
176
- return int64_to_float16(a, status);
177
+ return int64_to_float16_scalbn(a, 0, status);
178
+}
179
+
180
+float32 int64_to_float32_scalbn(int64_t a, int scale, float_status *status)
181
+{
182
+ FloatParts pa = int_to_float(a, scale, status);
183
+ return float32_round_pack_canonical(pa, status);
184
+}
185
+
186
+float32 int32_to_float32_scalbn(int32_t a, int scale, float_status *status)
187
+{
188
+ return int64_to_float32_scalbn(a, scale, status);
189
+}
190
+
191
+float32 int16_to_float32_scalbn(int16_t a, int scale, float_status *status)
192
+{
193
+ return int64_to_float32_scalbn(a, scale, status);
194
}
195
196
float32 int64_to_float32(int64_t a, float_status *status)
197
{
198
- FloatParts pa = int_to_float(a, status);
199
- return float32_round_pack_canonical(pa, status);
200
+ return int64_to_float32_scalbn(a, 0, status);
201
}
202
203
float32 int32_to_float32(int32_t a, float_status *status)
204
{
205
- return int64_to_float32(a, status);
206
+ return int64_to_float32_scalbn(a, 0, status);
207
}
208
209
float32 int16_to_float32(int16_t a, float_status *status)
210
{
211
- return int64_to_float32(a, status);
212
+ return int64_to_float32_scalbn(a, 0, status);
213
+}
214
+
215
+float64 int64_to_float64_scalbn(int64_t a, int scale, float_status *status)
216
+{
217
+ FloatParts pa = int_to_float(a, scale, status);
218
+ return float64_round_pack_canonical(pa, status);
219
+}
220
+
221
+float64 int32_to_float64_scalbn(int32_t a, int scale, float_status *status)
222
+{
223
+ return int64_to_float64_scalbn(a, scale, status);
224
+}
225
+
226
+float64 int16_to_float64_scalbn(int16_t a, int scale, float_status *status)
227
+{
228
+ return int64_to_float64_scalbn(a, scale, status);
229
}
230
231
float64 int64_to_float64(int64_t a, float_status *status)
232
{
233
- FloatParts pa = int_to_float(a, status);
234
- return float64_round_pack_canonical(pa, status);
235
+ return int64_to_float64_scalbn(a, 0, status);
236
}
237
238
float64 int32_to_float64(int32_t a, float_status *status)
239
{
240
- return int64_to_float64(a, status);
241
+ return int64_to_float64_scalbn(a, 0, status);
242
}
243
244
float64 int16_to_float64(int16_t a, float_status *status)
245
{
246
- return int64_to_float64(a, status);
247
+ return int64_to_float64_scalbn(a, 0, status);
248
}
249
250
251
@@ -XXX,XX +XXX,XX @@ float64 int16_to_float64(int16_t a, float_status *status)
252
* IEC/IEEE Standard for Binary Floating-Point Arithmetic.
253
*/
254
255
-static FloatParts uint_to_float(uint64_t a, float_status *status)
256
+static FloatParts uint_to_float(uint64_t a, int scale, float_status *status)
257
{
258
- FloatParts r = { .sign = false};
259
+ FloatParts r = { .sign = false };
260
261
if (a == 0) {
262
r.cls = float_class_zero;
263
} else {
264
- int spare_bits = clz64(a) - 1;
265
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
266
r.cls = float_class_normal;
267
- r.exp = DECOMPOSED_BINARY_POINT - spare_bits;
268
- if (spare_bits < 0) {
269
- shift64RightJamming(a, -spare_bits, &a);
270
+ if ((int64_t)a < 0) {
271
+ r.exp = DECOMPOSED_BINARY_POINT + 1 + scale;
272
+ shift64RightJamming(a, 1, &a);
273
r.frac = a;
274
} else {
275
- r.frac = a << spare_bits;
276
+ int shift = clz64(a) - 1;
277
+ r.exp = DECOMPOSED_BINARY_POINT - shift + scale;
278
+ r.frac = a << shift;
279
}
280
}
281
282
return r;
283
}
284
285
+float16 uint64_to_float16_scalbn(uint64_t a, int scale, float_status *status)
286
+{
287
+ FloatParts pa = uint_to_float(a, scale, status);
288
+ return float16_round_pack_canonical(pa, status);
289
+}
290
+
291
+float16 uint32_to_float16_scalbn(uint32_t a, int scale, float_status *status)
292
+{
293
+ return uint64_to_float16_scalbn(a, scale, status);
294
+}
295
+
296
+float16 uint16_to_float16_scalbn(uint16_t a, int scale, float_status *status)
297
+{
298
+ return uint64_to_float16_scalbn(a, scale, status);
299
+}
300
+
301
float16 uint64_to_float16(uint64_t a, float_status *status)
302
{
303
- FloatParts pa = uint_to_float(a, status);
304
- return float16_round_pack_canonical(pa, status);
305
+ return uint64_to_float16_scalbn(a, 0, status);
306
}
307
308
float16 uint32_to_float16(uint32_t a, float_status *status)
309
{
310
- return uint64_to_float16(a, status);
311
+ return uint64_to_float16_scalbn(a, 0, status);
312
}
313
314
float16 uint16_to_float16(uint16_t a, float_status *status)
315
{
316
- return uint64_to_float16(a, status);
317
+ return uint64_to_float16_scalbn(a, 0, status);
318
+}
319
+
320
+float32 uint64_to_float32_scalbn(uint64_t a, int scale, float_status *status)
321
+{
322
+ FloatParts pa = uint_to_float(a, scale, status);
323
+ return float32_round_pack_canonical(pa, status);
324
+}
325
+
326
+float32 uint32_to_float32_scalbn(uint32_t a, int scale, float_status *status)
327
+{
328
+ return uint64_to_float32_scalbn(a, scale, status);
329
+}
330
+
331
+float32 uint16_to_float32_scalbn(uint16_t a, int scale, float_status *status)
332
+{
333
+ return uint64_to_float32_scalbn(a, scale, status);
334
}
335
336
float32 uint64_to_float32(uint64_t a, float_status *status)
337
{
338
- FloatParts pa = uint_to_float(a, status);
339
- return float32_round_pack_canonical(pa, status);
340
+ return uint64_to_float32_scalbn(a, 0, status);
341
}
342
343
float32 uint32_to_float32(uint32_t a, float_status *status)
344
{
345
- return uint64_to_float32(a, status);
346
+ return uint64_to_float32_scalbn(a, 0, status);
347
}
348
349
float32 uint16_to_float32(uint16_t a, float_status *status)
350
{
351
- return uint64_to_float32(a, status);
352
+ return uint64_to_float32_scalbn(a, 0, status);
353
+}
354
+
355
+float64 uint64_to_float64_scalbn(uint64_t a, int scale, float_status *status)
356
+{
357
+ FloatParts pa = uint_to_float(a, scale, status);
358
+ return float64_round_pack_canonical(pa, status);
359
+}
360
+
361
+float64 uint32_to_float64_scalbn(uint32_t a, int scale, float_status *status)
362
+{
363
+ return uint64_to_float64_scalbn(a, scale, status);
364
+}
365
+
366
+float64 uint16_to_float64_scalbn(uint16_t a, int scale, float_status *status)
367
+{
368
+ return uint64_to_float64_scalbn(a, scale, status);
369
}
370
371
float64 uint64_to_float64(uint64_t a, float_status *status)
372
{
373
- FloatParts pa = uint_to_float(a, status);
374
- return float64_round_pack_canonical(pa, status);
375
+ return uint64_to_float64_scalbn(a, 0, status);
376
}
377
378
float64 uint32_to_float64(uint32_t a, float_status *status)
379
{
380
- return uint64_to_float64(a, status);
381
+ return uint64_to_float64_scalbn(a, 0, status);
382
}
383
384
float64 uint16_to_float64(uint16_t a, float_status *status)
385
{
386
- return uint64_to_float64(a, status);
387
+ return uint64_to_float64_scalbn(a, 0, status);
388
}
389
390
/* Float Min/Max */
60
--
391
--
61
2.7.4
392
2.18.0
62
393
63
394
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Make Tx frame assembly buffer to be a paort of IMXFECState structure
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
to avoid a concern about having large data buffer on the stack.
4
Message-id: 20180814002653.12828-3-richard.henderson@linaro.org
5
6
Cc: Peter Maydell <peter.maydell@linaro.org>
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: yurovsky@gmail.com
12
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
7
---
16
include/hw/net/imx_fec.h | 3 +++
8
include/fpu/softfloat.h | 85 ++++++---
17
hw/net/imx_fec.c | 22 +++++++++++-----------
9
fpu/softfloat.c | 391 ++++++++++++++++++++++++++++++++--------
18
2 files changed, 14 insertions(+), 11 deletions(-)
10
2 files changed, 379 insertions(+), 97 deletions(-)
19
11
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
12
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
14
--- a/include/fpu/softfloat.h
23
+++ b/include/hw/net/imx_fec.h
15
+++ b/include/fpu/softfloat.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct IMXFECState {
16
@@ -XXX,XX +XXX,XX @@ float128 uint64_to_float128(uint64_t, float_status *status);
25
uint32_t phy_int_mask;
17
/*----------------------------------------------------------------------------
26
18
| Software half-precision conversion routines.
27
bool is_fec;
19
*----------------------------------------------------------------------------*/
28
+
20
+
29
+ /* Buffer used to assemble a Tx frame */
21
float16 float32_to_float16(float32, bool ieee, float_status *status);
30
+ uint8_t frame[ENET_MAX_FRAME_SIZE];
22
float32 float16_to_float32(float16, bool ieee, float_status *status);
31
} IMXFECState;
23
float16 float64_to_float16(float64 a, bool ieee, float_status *status);
32
24
float64 float16_to_float64(float16 a, bool ieee, float_status *status);
33
#endif
25
+
34
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
26
+int16_t float16_to_int16_scalbn(float16, int, int, float_status *status);
27
+int32_t float16_to_int32_scalbn(float16, int, int, float_status *status);
28
+int64_t float16_to_int64_scalbn(float16, int, int, float_status *status);
29
+
30
int16_t float16_to_int16(float16, float_status *status);
31
-uint16_t float16_to_uint16(float16 a, float_status *status);
32
-int16_t float16_to_int16_round_to_zero(float16, float_status *status);
33
-uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *status);
34
int32_t float16_to_int32(float16, float_status *status);
35
-uint32_t float16_to_uint32(float16 a, float_status *status);
36
-int32_t float16_to_int32_round_to_zero(float16, float_status *status);
37
-uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *status);
38
int64_t float16_to_int64(float16, float_status *status);
39
-uint64_t float16_to_uint64(float16 a, float_status *status);
40
+
41
+int16_t float16_to_int16_round_to_zero(float16, float_status *status);
42
+int32_t float16_to_int32_round_to_zero(float16, float_status *status);
43
int64_t float16_to_int64_round_to_zero(float16, float_status *status);
44
+
45
+uint16_t float16_to_uint16_scalbn(float16 a, int, int, float_status *status);
46
+uint32_t float16_to_uint32_scalbn(float16 a, int, int, float_status *status);
47
+uint64_t float16_to_uint64_scalbn(float16 a, int, int, float_status *status);
48
+
49
+uint16_t float16_to_uint16(float16 a, float_status *status);
50
+uint32_t float16_to_uint32(float16 a, float_status *status);
51
+uint64_t float16_to_uint64(float16 a, float_status *status);
52
+
53
+uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *status);
54
+uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *status);
55
uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *status);
56
57
/*----------------------------------------------------------------------------
58
@@ -XXX,XX +XXX,XX @@ float16 float16_default_nan(float_status *status);
59
/*----------------------------------------------------------------------------
60
| Software IEC/IEEE single-precision conversion routines.
61
*----------------------------------------------------------------------------*/
62
+
63
+int16_t float32_to_int16_scalbn(float32, int, int, float_status *status);
64
+int32_t float32_to_int32_scalbn(float32, int, int, float_status *status);
65
+int64_t float32_to_int64_scalbn(float32, int, int, float_status *status);
66
+
67
int16_t float32_to_int16(float32, float_status *status);
68
-uint16_t float32_to_uint16(float32, float_status *status);
69
-int16_t float32_to_int16_round_to_zero(float32, float_status *status);
70
-uint16_t float32_to_uint16_round_to_zero(float32, float_status *status);
71
int32_t float32_to_int32(float32, float_status *status);
72
-int32_t float32_to_int32_round_to_zero(float32, float_status *status);
73
-uint32_t float32_to_uint32(float32, float_status *status);
74
-uint32_t float32_to_uint32_round_to_zero(float32, float_status *status);
75
int64_t float32_to_int64(float32, float_status *status);
76
-uint64_t float32_to_uint64(float32, float_status *status);
77
-uint64_t float32_to_uint64_round_to_zero(float32, float_status *status);
78
+
79
+int16_t float32_to_int16_round_to_zero(float32, float_status *status);
80
+int32_t float32_to_int32_round_to_zero(float32, float_status *status);
81
int64_t float32_to_int64_round_to_zero(float32, float_status *status);
82
+
83
+uint16_t float32_to_uint16_scalbn(float32, int, int, float_status *status);
84
+uint32_t float32_to_uint32_scalbn(float32, int, int, float_status *status);
85
+uint64_t float32_to_uint64_scalbn(float32, int, int, float_status *status);
86
+
87
+uint16_t float32_to_uint16(float32, float_status *status);
88
+uint32_t float32_to_uint32(float32, float_status *status);
89
+uint64_t float32_to_uint64(float32, float_status *status);
90
+
91
+uint16_t float32_to_uint16_round_to_zero(float32, float_status *status);
92
+uint32_t float32_to_uint32_round_to_zero(float32, float_status *status);
93
+uint64_t float32_to_uint64_round_to_zero(float32, float_status *status);
94
+
95
float64 float32_to_float64(float32, float_status *status);
96
floatx80 float32_to_floatx80(float32, float_status *status);
97
float128 float32_to_float128(float32, float_status *status);
98
@@ -XXX,XX +XXX,XX @@ float32 float32_default_nan(float_status *status);
99
/*----------------------------------------------------------------------------
100
| Software IEC/IEEE double-precision conversion routines.
101
*----------------------------------------------------------------------------*/
102
+
103
+int16_t float64_to_int16_scalbn(float64, int, int, float_status *status);
104
+int32_t float64_to_int32_scalbn(float64, int, int, float_status *status);
105
+int64_t float64_to_int64_scalbn(float64, int, int, float_status *status);
106
+
107
int16_t float64_to_int16(float64, float_status *status);
108
-uint16_t float64_to_uint16(float64, float_status *status);
109
-int16_t float64_to_int16_round_to_zero(float64, float_status *status);
110
-uint16_t float64_to_uint16_round_to_zero(float64, float_status *status);
111
int32_t float64_to_int32(float64, float_status *status);
112
-int32_t float64_to_int32_round_to_zero(float64, float_status *status);
113
-uint32_t float64_to_uint32(float64, float_status *status);
114
-uint32_t float64_to_uint32_round_to_zero(float64, float_status *status);
115
int64_t float64_to_int64(float64, float_status *status);
116
+
117
+int16_t float64_to_int16_round_to_zero(float64, float_status *status);
118
+int32_t float64_to_int32_round_to_zero(float64, float_status *status);
119
int64_t float64_to_int64_round_to_zero(float64, float_status *status);
120
-uint64_t float64_to_uint64(float64 a, float_status *status);
121
-uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *status);
122
+
123
+uint16_t float64_to_uint16_scalbn(float64, int, int, float_status *status);
124
+uint32_t float64_to_uint32_scalbn(float64, int, int, float_status *status);
125
+uint64_t float64_to_uint64_scalbn(float64, int, int, float_status *status);
126
+
127
+uint16_t float64_to_uint16(float64, float_status *status);
128
+uint32_t float64_to_uint32(float64, float_status *status);
129
+uint64_t float64_to_uint64(float64, float_status *status);
130
+
131
+uint16_t float64_to_uint16_round_to_zero(float64, float_status *status);
132
+uint32_t float64_to_uint32_round_to_zero(float64, float_status *status);
133
+uint64_t float64_to_uint64_round_to_zero(float64, float_status *status);
134
+
135
float32 float64_to_float32(float64, float_status *status);
136
floatx80 float64_to_floatx80(float64, float_status *status);
137
float128 float64_to_float128(float64, float_status *status);
138
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
35
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/net/imx_fec.c
140
--- a/fpu/softfloat.c
37
+++ b/hw/net/imx_fec.c
141
+++ b/fpu/softfloat.c
38
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s)
142
@@ -XXX,XX +XXX,XX @@ float32 float64_to_float32(float64 a, float_status *s)
39
static void imx_fec_do_tx(IMXFECState *s)
143
* Arithmetic.
144
*/
145
146
-static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
147
+static FloatParts round_to_int(FloatParts a, int rmode,
148
+ int scale, float_status *s)
40
{
149
{
41
int frame_size = 0, descnt = 0;
150
- if (is_nan(a.cls)) {
42
- uint8_t frame[ENET_MAX_FRAME_SIZE];
151
- return return_nan(a, s);
43
- uint8_t *ptr = frame;
152
- }
44
+ uint8_t *ptr = s->frame;
153
-
45
uint32_t addr = s->tx_descriptor;
154
switch (a.cls) {
46
155
+ case float_class_qnan:
47
while (descnt++ < IMX_MAX_DESC) {
156
+ case float_class_snan:
48
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
157
+ return return_nan(a, s);
49
frame_size += len;
158
+
50
if (bd.flags & ENET_BD_L) {
159
case float_class_zero:
51
/* Last buffer in frame. */
160
case float_class_inf:
52
- qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size);
161
- case float_class_qnan:
53
- ptr = frame;
162
/* already "integral" */
54
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
163
break;
55
+ ptr = s->frame;
164
+
56
frame_size = 0;
165
case float_class_normal:
57
s->regs[ENET_EIR] |= ENET_INT_TXF;
166
+ scale = MIN(MAX(scale, -0x10000), 0x10000);
167
+ a.exp += scale;
168
+
169
if (a.exp >= DECOMPOSED_BINARY_POINT) {
170
/* already integral */
171
break;
172
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
173
bool one;
174
/* all fractional */
175
s->float_exception_flags |= float_flag_inexact;
176
- switch (rounding_mode) {
177
+ switch (rmode) {
178
case float_round_nearest_even:
179
one = a.exp == -1 && a.frac > DECOMPOSED_IMPLICIT_BIT;
180
break;
181
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
182
uint64_t rnd_mask = rnd_even_mask >> 1;
183
uint64_t inc;
184
185
- switch (rounding_mode) {
186
+ switch (rmode) {
187
case float_round_nearest_even:
188
inc = ((a.frac & rnd_even_mask) != frac_lsbm1 ? frac_lsbm1 : 0);
189
break;
190
@@ -XXX,XX +XXX,XX @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
191
float16 float16_round_to_int(float16 a, float_status *s)
192
{
193
FloatParts pa = float16_unpack_canonical(a, s);
194
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
195
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
196
return float16_round_pack_canonical(pr, s);
197
}
198
199
float32 float32_round_to_int(float32 a, float_status *s)
200
{
201
FloatParts pa = float32_unpack_canonical(a, s);
202
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
203
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
204
return float32_round_pack_canonical(pr, s);
205
}
206
207
float64 float64_round_to_int(float64 a, float_status *s)
208
{
209
FloatParts pa = float64_unpack_canonical(a, s);
210
- FloatParts pr = round_to_int(pa, s->float_rounding_mode, s);
211
+ FloatParts pr = round_to_int(pa, s->float_rounding_mode, 0, s);
212
return float64_round_pack_canonical(pr, s);
213
}
214
215
float64 float64_trunc_to_int(float64 a, float_status *s)
216
{
217
FloatParts pa = float64_unpack_canonical(a, s);
218
- FloatParts pr = round_to_int(pa, float_round_to_zero, s);
219
+ FloatParts pr = round_to_int(pa, float_round_to_zero, 0, s);
220
return float64_round_pack_canonical(pr, s);
221
}
222
223
@@ -XXX,XX +XXX,XX @@ float64 float64_trunc_to_int(float64 a, float_status *s)
224
* is returned.
225
*/
226
227
-static int64_t round_to_int_and_pack(FloatParts in, int rmode,
228
+static int64_t round_to_int_and_pack(FloatParts in, int rmode, int scale,
229
int64_t min, int64_t max,
230
float_status *s)
231
{
232
uint64_t r;
233
int orig_flags = get_float_exception_flags(s);
234
- FloatParts p = round_to_int(in, rmode, s);
235
+ FloatParts p = round_to_int(in, rmode, scale, s);
236
237
switch (p.cls) {
238
case float_class_snan:
239
@@ -XXX,XX +XXX,XX @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode,
240
}
241
}
242
243
-#define FLOAT_TO_INT(fsz, isz) \
244
-int ## isz ## _t float ## fsz ## _to_int ## isz(float ## fsz a, \
245
- float_status *s) \
246
-{ \
247
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
248
- return round_to_int_and_pack(p, s->float_rounding_mode, \
249
- INT ## isz ## _MIN, INT ## isz ## _MAX,\
250
- s); \
251
-} \
252
- \
253
-int ## isz ## _t float ## fsz ## _to_int ## isz ## _round_to_zero \
254
- (float ## fsz a, float_status *s) \
255
-{ \
256
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
257
- return round_to_int_and_pack(p, float_round_to_zero, \
258
- INT ## isz ## _MIN, INT ## isz ## _MAX,\
259
- s); \
260
+int16_t float16_to_int16_scalbn(float16 a, int rmode, int scale,
261
+ float_status *s)
262
+{
263
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
264
+ rmode, scale, INT16_MIN, INT16_MAX, s);
265
}
266
267
-FLOAT_TO_INT(16, 16)
268
-FLOAT_TO_INT(16, 32)
269
-FLOAT_TO_INT(16, 64)
270
+int32_t float16_to_int32_scalbn(float16 a, int rmode, int scale,
271
+ float_status *s)
272
+{
273
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
274
+ rmode, scale, INT32_MIN, INT32_MAX, s);
275
+}
276
277
-FLOAT_TO_INT(32, 16)
278
-FLOAT_TO_INT(32, 32)
279
-FLOAT_TO_INT(32, 64)
280
+int64_t float16_to_int64_scalbn(float16 a, int rmode, int scale,
281
+ float_status *s)
282
+{
283
+ return round_to_int_and_pack(float16_unpack_canonical(a, s),
284
+ rmode, scale, INT64_MIN, INT64_MAX, s);
285
+}
286
287
-FLOAT_TO_INT(64, 16)
288
-FLOAT_TO_INT(64, 32)
289
-FLOAT_TO_INT(64, 64)
290
+int16_t float32_to_int16_scalbn(float32 a, int rmode, int scale,
291
+ float_status *s)
292
+{
293
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
294
+ rmode, scale, INT16_MIN, INT16_MAX, s);
295
+}
296
297
-#undef FLOAT_TO_INT
298
+int32_t float32_to_int32_scalbn(float32 a, int rmode, int scale,
299
+ float_status *s)
300
+{
301
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
302
+ rmode, scale, INT32_MIN, INT32_MAX, s);
303
+}
304
+
305
+int64_t float32_to_int64_scalbn(float32 a, int rmode, int scale,
306
+ float_status *s)
307
+{
308
+ return round_to_int_and_pack(float32_unpack_canonical(a, s),
309
+ rmode, scale, INT64_MIN, INT64_MAX, s);
310
+}
311
+
312
+int16_t float64_to_int16_scalbn(float64 a, int rmode, int scale,
313
+ float_status *s)
314
+{
315
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
316
+ rmode, scale, INT16_MIN, INT16_MAX, s);
317
+}
318
+
319
+int32_t float64_to_int32_scalbn(float64 a, int rmode, int scale,
320
+ float_status *s)
321
+{
322
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
323
+ rmode, scale, INT32_MIN, INT32_MAX, s);
324
+}
325
+
326
+int64_t float64_to_int64_scalbn(float64 a, int rmode, int scale,
327
+ float_status *s)
328
+{
329
+ return round_to_int_and_pack(float64_unpack_canonical(a, s),
330
+ rmode, scale, INT64_MIN, INT64_MAX, s);
331
+}
332
+
333
+int16_t float16_to_int16(float16 a, float_status *s)
334
+{
335
+ return float16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
336
+}
337
+
338
+int32_t float16_to_int32(float16 a, float_status *s)
339
+{
340
+ return float16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
341
+}
342
+
343
+int64_t float16_to_int64(float16 a, float_status *s)
344
+{
345
+ return float16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
346
+}
347
+
348
+int16_t float32_to_int16(float32 a, float_status *s)
349
+{
350
+ return float32_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
351
+}
352
+
353
+int32_t float32_to_int32(float32 a, float_status *s)
354
+{
355
+ return float32_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
356
+}
357
+
358
+int64_t float32_to_int64(float32 a, float_status *s)
359
+{
360
+ return float32_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
361
+}
362
+
363
+int16_t float64_to_int16(float64 a, float_status *s)
364
+{
365
+ return float64_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
366
+}
367
+
368
+int32_t float64_to_int32(float64 a, float_status *s)
369
+{
370
+ return float64_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
371
+}
372
+
373
+int64_t float64_to_int64(float64 a, float_status *s)
374
+{
375
+ return float64_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
376
+}
377
+
378
+int16_t float16_to_int16_round_to_zero(float16 a, float_status *s)
379
+{
380
+ return float16_to_int16_scalbn(a, float_round_to_zero, 0, s);
381
+}
382
+
383
+int32_t float16_to_int32_round_to_zero(float16 a, float_status *s)
384
+{
385
+ return float16_to_int32_scalbn(a, float_round_to_zero, 0, s);
386
+}
387
+
388
+int64_t float16_to_int64_round_to_zero(float16 a, float_status *s)
389
+{
390
+ return float16_to_int64_scalbn(a, float_round_to_zero, 0, s);
391
+}
392
+
393
+int16_t float32_to_int16_round_to_zero(float32 a, float_status *s)
394
+{
395
+ return float32_to_int16_scalbn(a, float_round_to_zero, 0, s);
396
+}
397
+
398
+int32_t float32_to_int32_round_to_zero(float32 a, float_status *s)
399
+{
400
+ return float32_to_int32_scalbn(a, float_round_to_zero, 0, s);
401
+}
402
+
403
+int64_t float32_to_int64_round_to_zero(float32 a, float_status *s)
404
+{
405
+ return float32_to_int64_scalbn(a, float_round_to_zero, 0, s);
406
+}
407
+
408
+int16_t float64_to_int16_round_to_zero(float64 a, float_status *s)
409
+{
410
+ return float64_to_int16_scalbn(a, float_round_to_zero, 0, s);
411
+}
412
+
413
+int32_t float64_to_int32_round_to_zero(float64 a, float_status *s)
414
+{
415
+ return float64_to_int32_scalbn(a, float_round_to_zero, 0, s);
416
+}
417
+
418
+int64_t float64_to_int64_round_to_zero(float64 a, float_status *s)
419
+{
420
+ return float64_to_int64_scalbn(a, float_round_to_zero, 0, s);
421
+}
422
423
/*
424
* Returns the result of converting the floating-point value `a' to
425
@@ -XXX,XX +XXX,XX @@ FLOAT_TO_INT(64, 64)
426
* flag.
427
*/
428
429
-static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
430
- float_status *s)
431
+static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, int scale,
432
+ uint64_t max, float_status *s)
433
{
434
int orig_flags = get_float_exception_flags(s);
435
- FloatParts p = round_to_int(in, rmode, s);
436
+ FloatParts p = round_to_int(in, rmode, scale, s);
437
+ uint64_t r;
438
439
switch (p.cls) {
440
case float_class_snan:
441
@@ -XXX,XX +XXX,XX @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
442
case float_class_zero:
443
return 0;
444
case float_class_normal:
445
- {
446
- uint64_t r;
447
if (p.sign) {
448
s->float_exception_flags = orig_flags | float_flag_invalid;
449
return 0;
450
@@ -XXX,XX +XXX,XX @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
451
if (r > max) {
452
s->float_exception_flags = orig_flags | float_flag_invalid;
453
return max;
454
- } else {
455
- return r;
58
}
456
}
59
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
457
- }
60
static void imx_enet_do_tx(IMXFECState *s)
458
+ return r;
61
{
459
default:
62
int frame_size = 0, descnt = 0;
460
g_assert_not_reached();
63
- uint8_t frame[ENET_MAX_FRAME_SIZE];
461
}
64
- uint8_t *ptr = frame;
462
}
65
+ uint8_t *ptr = s->frame;
463
66
uint32_t addr = s->tx_descriptor;
464
-#define FLOAT_TO_UINT(fsz, isz) \
67
465
-uint ## isz ## _t float ## fsz ## _to_uint ## isz(float ## fsz a, \
68
while (descnt++ < IMX_MAX_DESC) {
466
- float_status *s) \
69
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
467
-{ \
70
frame_size += len;
468
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
71
if (bd.flags & ENET_BD_L) {
469
- return round_to_uint_and_pack(p, s->float_rounding_mode, \
72
if (bd.option & ENET_BD_PINS) {
470
- UINT ## isz ## _MAX, s); \
73
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
471
-} \
74
+ struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
472
- \
75
if (IP_HEADER_VERSION(ip_hd) == 4) {
473
-uint ## isz ## _t float ## fsz ## _to_uint ## isz ## _round_to_zero \
76
- net_checksum_calculate(frame, frame_size);
474
- (float ## fsz a, float_status *s) \
77
+ net_checksum_calculate(s->frame, frame_size);
475
-{ \
78
}
476
- FloatParts p = float ## fsz ## _unpack_canonical(a, s); \
79
}
477
- return round_to_uint_and_pack(p, float_round_to_zero, \
80
if (bd.option & ENET_BD_IINS) {
478
- UINT ## isz ## _MAX, s); \
81
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
479
+uint16_t float16_to_uint16_scalbn(float16 a, int rmode, int scale,
82
+ struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
480
+ float_status *s)
83
/* We compute checksum only for IPv4 frames */
481
+{
84
if (IP_HEADER_VERSION(ip_hd) == 4) {
482
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
85
uint16_t csum;
483
+ rmode, scale, UINT16_MAX, s);
86
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
484
}
87
}
485
88
}
486
-FLOAT_TO_UINT(16, 16)
89
/* Last buffer in frame. */
487
-FLOAT_TO_UINT(16, 32)
90
- qemu_send_packet(qemu_get_queue(s->nic), frame, len);
488
-FLOAT_TO_UINT(16, 64)
91
- ptr = frame;
489
+uint32_t float16_to_uint32_scalbn(float16 a, int rmode, int scale,
92
+
490
+ float_status *s)
93
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, len);
491
+{
94
+ ptr = s->frame;
492
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
95
+
493
+ rmode, scale, UINT32_MAX, s);
96
frame_size = 0;
494
+}
97
if (bd.option & ENET_BD_TX_INT) {
495
98
s->regs[ENET_EIR] |= ENET_INT_TXF;
496
-FLOAT_TO_UINT(32, 16)
497
-FLOAT_TO_UINT(32, 32)
498
-FLOAT_TO_UINT(32, 64)
499
+uint64_t float16_to_uint64_scalbn(float16 a, int rmode, int scale,
500
+ float_status *s)
501
+{
502
+ return round_to_uint_and_pack(float16_unpack_canonical(a, s),
503
+ rmode, scale, UINT64_MAX, s);
504
+}
505
506
-FLOAT_TO_UINT(64, 16)
507
-FLOAT_TO_UINT(64, 32)
508
-FLOAT_TO_UINT(64, 64)
509
+uint16_t float32_to_uint16_scalbn(float32 a, int rmode, int scale,
510
+ float_status *s)
511
+{
512
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
513
+ rmode, scale, UINT16_MAX, s);
514
+}
515
516
-#undef FLOAT_TO_UINT
517
+uint32_t float32_to_uint32_scalbn(float32 a, int rmode, int scale,
518
+ float_status *s)
519
+{
520
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
521
+ rmode, scale, UINT32_MAX, s);
522
+}
523
+
524
+uint64_t float32_to_uint64_scalbn(float32 a, int rmode, int scale,
525
+ float_status *s)
526
+{
527
+ return round_to_uint_and_pack(float32_unpack_canonical(a, s),
528
+ rmode, scale, UINT64_MAX, s);
529
+}
530
+
531
+uint16_t float64_to_uint16_scalbn(float64 a, int rmode, int scale,
532
+ float_status *s)
533
+{
534
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
535
+ rmode, scale, UINT16_MAX, s);
536
+}
537
+
538
+uint32_t float64_to_uint32_scalbn(float64 a, int rmode, int scale,
539
+ float_status *s)
540
+{
541
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
542
+ rmode, scale, UINT32_MAX, s);
543
+}
544
+
545
+uint64_t float64_to_uint64_scalbn(float64 a, int rmode, int scale,
546
+ float_status *s)
547
+{
548
+ return round_to_uint_and_pack(float64_unpack_canonical(a, s),
549
+ rmode, scale, UINT64_MAX, s);
550
+}
551
+
552
+uint16_t float16_to_uint16(float16 a, float_status *s)
553
+{
554
+ return float16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
555
+}
556
+
557
+uint32_t float16_to_uint32(float16 a, float_status *s)
558
+{
559
+ return float16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
560
+}
561
+
562
+uint64_t float16_to_uint64(float16 a, float_status *s)
563
+{
564
+ return float16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
565
+}
566
+
567
+uint16_t float32_to_uint16(float32 a, float_status *s)
568
+{
569
+ return float32_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
570
+}
571
+
572
+uint32_t float32_to_uint32(float32 a, float_status *s)
573
+{
574
+ return float32_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
575
+}
576
+
577
+uint64_t float32_to_uint64(float32 a, float_status *s)
578
+{
579
+ return float32_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
580
+}
581
+
582
+uint16_t float64_to_uint16(float64 a, float_status *s)
583
+{
584
+ return float64_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
585
+}
586
+
587
+uint32_t float64_to_uint32(float64 a, float_status *s)
588
+{
589
+ return float64_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
590
+}
591
+
592
+uint64_t float64_to_uint64(float64 a, float_status *s)
593
+{
594
+ return float64_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
595
+}
596
+
597
+uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *s)
598
+{
599
+ return float16_to_uint16_scalbn(a, float_round_to_zero, 0, s);
600
+}
601
+
602
+uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *s)
603
+{
604
+ return float16_to_uint32_scalbn(a, float_round_to_zero, 0, s);
605
+}
606
+
607
+uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *s)
608
+{
609
+ return float16_to_uint64_scalbn(a, float_round_to_zero, 0, s);
610
+}
611
+
612
+uint16_t float32_to_uint16_round_to_zero(float32 a, float_status *s)
613
+{
614
+ return float32_to_uint16_scalbn(a, float_round_to_zero, 0, s);
615
+}
616
+
617
+uint32_t float32_to_uint32_round_to_zero(float32 a, float_status *s)
618
+{
619
+ return float32_to_uint32_scalbn(a, float_round_to_zero, 0, s);
620
+}
621
+
622
+uint64_t float32_to_uint64_round_to_zero(float32 a, float_status *s)
623
+{
624
+ return float32_to_uint64_scalbn(a, float_round_to_zero, 0, s);
625
+}
626
+
627
+uint16_t float64_to_uint16_round_to_zero(float64 a, float_status *s)
628
+{
629
+ return float64_to_uint16_scalbn(a, float_round_to_zero, 0, s);
630
+}
631
+
632
+uint32_t float64_to_uint32_round_to_zero(float64 a, float_status *s)
633
+{
634
+ return float64_to_uint32_scalbn(a, float_round_to_zero, 0, s);
635
+}
636
+
637
+uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *s)
638
+{
639
+ return float64_to_uint64_scalbn(a, float_round_to_zero, 0, s);
640
+}
641
642
/*
643
* Integer to float conversions
99
--
644
--
100
2.7.4
645
2.18.0
101
646
102
647
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
4
Message-id: 20180814002653.12828-4-richard.henderson@linaro.org
5
Message-id: 20180104000156.30932-1-f4bug@amsat.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: add missing include]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
hw/sd/pxa2xx_mmci.c | 78 ++++++++++++++++++++++++++++++++++-------------------
8
target/arm/helper.c | 29 +++++------------------------
10
hw/sd/trace-events | 4 +++
9
1 file changed, 5 insertions(+), 24 deletions(-)
11
2 files changed, 54 insertions(+), 28 deletions(-)
12
10
13
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/sd/pxa2xx_mmci.c
13
--- a/target/arm/helper.c
16
+++ b/hw/sd/pxa2xx_mmci.c
14
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
18
#include "hw/qdev.h"
16
#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
19
#include "hw/qdev-properties.h"
17
float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
20
#include "qemu/error-report.h"
18
void *fpstp) \
21
+#include "qemu/log.h"
19
-{ \
22
+#include "trace.h"
20
- float_status *fpst = fpstp; \
23
21
- float##fsz tmp; \
24
#define TYPE_PXA2XX_MMCI "pxa2xx-mmci"
22
- tmp = itype##_to_##float##fsz(x, fpst); \
25
#define PXA2XX_MMCI(obj) OBJECT_CHECK(PXA2xxMMCIState, (obj), TYPE_PXA2XX_MMCI)
23
- return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
26
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s)
24
-}
27
static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
25
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
26
27
/* Notice that we want only input-denormal exception flags from the
28
* scalbn operation: the other possible flags (overflow+inexact if
29
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
30
#undef VFP_CONV_FLOAT_FIX_ROUND
31
#undef VFP_CONV_FIX_A64
32
33
-/* Conversion to/from f16 can overflow to infinity before/after scaling.
34
- * Therefore we convert to f64, scale, and then convert f64 to f16; or
35
- * vice versa for conversion to integer.
36
- *
37
- * For 16- and 32-bit integers, the conversion to f64 never rounds.
38
- * For 64-bit integers, any integer that would cause rounding will also
39
- * overflow to f16 infinity, so there is no double rounding problem.
40
- */
41
-
42
-static float16 do_postscale_fp16(float64 f, int shift, float_status *fpst)
43
-{
44
- return float64_to_float16(float64_scalbn(f, -shift, fpst), true, fpst);
45
-}
46
-
47
uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
28
{
48
{
29
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
49
- return do_postscale_fp16(int32_to_float64(x, fpst), shift, fpst);
30
- uint32_t ret;
50
+ return int32_to_float16_scalbn(x, -shift, fpst);
31
+ uint32_t ret = 0;
32
33
switch (offset) {
34
case MMC_STRPCL:
35
- return 0;
36
+ break;
37
case MMC_STAT:
38
- return s->status;
39
+ ret = s->status;
40
+ break;
41
case MMC_CLKRT:
42
- return s->clkrt;
43
+ ret = s->clkrt;
44
+ break;
45
case MMC_SPI:
46
- return s->spi;
47
+ ret = s->spi;
48
+ break;
49
case MMC_CMDAT:
50
- return s->cmdat;
51
+ ret = s->cmdat;
52
+ break;
53
case MMC_RESTO:
54
- return s->resp_tout;
55
+ ret = s->resp_tout;
56
+ break;
57
case MMC_RDTO:
58
- return s->read_tout;
59
+ ret = s->read_tout;
60
+ break;
61
case MMC_BLKLEN:
62
- return s->blklen;
63
+ ret = s->blklen;
64
+ break;
65
case MMC_NUMBLK:
66
- return s->numblk;
67
+ ret = s->numblk;
68
+ break;
69
case MMC_PRTBUF:
70
- return 0;
71
+ break;
72
case MMC_I_MASK:
73
- return s->intmask;
74
+ ret = s->intmask;
75
+ break;
76
case MMC_I_REG:
77
- return s->intreq;
78
+ ret = s->intreq;
79
+ break;
80
case MMC_CMD:
81
- return s->cmd | 0x40;
82
+ ret = s->cmd | 0x40;
83
+ break;
84
case MMC_ARGH:
85
- return s->arg >> 16;
86
+ ret = s->arg >> 16;
87
+ break;
88
case MMC_ARGL:
89
- return s->arg & 0xffff;
90
+ ret = s->arg & 0xffff;
91
+ break;
92
case MMC_RES:
93
- if (s->resp_len < 9)
94
- return s->resp_fifo[s->resp_len ++];
95
- return 0;
96
+ ret = (s->resp_len < 9) ? s->resp_fifo[s->resp_len++] : 0;
97
+ break;
98
case MMC_RXFIFO:
99
- ret = 0;
100
while (size-- && s->rx_len) {
101
ret |= s->rx_fifo[s->rx_start++] << (size << 3);
102
s->rx_start &= 0x1f;
103
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
104
}
105
s->intreq &= ~INT_RXFIFO_REQ;
106
pxa2xx_mmci_fifo_update(s);
107
- return ret;
108
+ break;
109
case MMC_RDWAIT:
110
- return 0;
111
+ break;
112
case MMC_BLKS_REM:
113
- return s->numblk;
114
+ ret = s->numblk;
115
+ break;
116
default:
117
- hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
118
+ qemu_log_mask(LOG_GUEST_ERROR,
119
+ "%s: incorrect register 0x%02" HWADDR_PRIx "\n",
120
+ __func__, offset);
121
}
122
+ trace_pxa2xx_mmci_read(size, offset, ret);
123
124
- return 0;
125
+ return ret;
126
}
51
}
127
52
128
static void pxa2xx_mmci_write(void *opaque,
53
uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
129
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
130
{
54
{
131
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
55
- return do_postscale_fp16(uint32_to_float64(x, fpst), shift, fpst);
132
56
+ return uint32_to_float16_scalbn(x, -shift, fpst);
133
+ trace_pxa2xx_mmci_write(size, offset, value);
134
switch (offset) {
135
case MMC_STRPCL:
136
if (value & STRPCL_STRT_CLK) {
137
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
138
139
case MMC_SPI:
140
s->spi = value & 0xf;
141
- if (value & SPI_SPI_MODE)
142
- printf("%s: attempted to use card in SPI mode\n", __FUNCTION__);
143
+ if (value & SPI_SPI_MODE) {
144
+ qemu_log_mask(LOG_GUEST_ERROR,
145
+ "%s: attempted to use card in SPI mode\n", __func__);
146
+ }
147
break;
148
149
case MMC_CMDAT:
150
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
151
break;
152
153
default:
154
- hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
155
+ qemu_log_mask(LOG_GUEST_ERROR,
156
+ "%s: incorrect reg 0x%02" HWADDR_PRIx " "
157
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
158
}
159
}
57
}
160
58
161
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
59
uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
162
index XXXXXXX..XXXXXXX 100644
60
{
163
--- a/hw/sd/trace-events
61
- return do_postscale_fp16(int64_to_float64(x, fpst), shift, fpst);
164
+++ b/hw/sd/trace-events
62
+ return int64_to_float16_scalbn(x, -shift, fpst);
165
@@ -XXX,XX +XXX,XX @@
63
}
166
# hw/sd/milkymist-memcard.c
64
167
milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
65
uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
168
milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
66
{
169
+
67
- return do_postscale_fp16(uint64_to_float64(x, fpst), shift, fpst);
170
+# hw/sd/pxa2xx_mmci.c
68
+ return uint64_to_float16_scalbn(x, -shift, fpst);
171
+pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
69
}
172
+pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
70
71
static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
173
--
72
--
174
2.7.4
73
2.18.0
175
74
176
75
diff view generated by jsdifflib
1
From: Zhaoshenglong <zhaoshenglong@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
acpi_data_push uses g_array_set_size to resize the memory size. If there
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
is no enough contiguous memory, the address will be changed. If we use
4
Message-id: 20180814002653.12828-5-richard.henderson@linaro.org
5
the old value, it will assert.
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
qemu-kvm: hw/acpi/bios-linker-loader.c:214: bios_linker_loader_add_checksum:
7
Assertion `start_offset < file->blob->len' failed.`
8
9
This issue only happens in building SRAT table now but here we unify the
10
pattern for other tables as well to avoid possible issues in the future.
11
12
Signed-off-by: Zhaoshenglong <zhaoshenglong@huawei.com>
13
Reviewed-by: Andrew Jones <drjones@redhat.com>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
7
---
16
hw/arm/virt-acpi-build.c | 18 +++++++++++-------
8
target/arm/helper.c | 101 ++++++++++++++++++++++----------------------
17
1 file changed, 11 insertions(+), 7 deletions(-)
9
1 file changed, 51 insertions(+), 50 deletions(-)
18
10
19
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/virt-acpi-build.c
13
--- a/target/arm/helper.c
22
+++ b/hw/arm/virt-acpi-build.c
14
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
15
@@ -XXX,XX +XXX,XX @@ float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
24
AcpiSerialPortConsoleRedirection *spcr;
16
void *fpstp) \
25
const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
17
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
26
int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
18
27
+ int spcr_start = table_data->len;
19
-/* Notice that we want only input-denormal exception flags from the
28
20
- * scalbn operation: the other possible flags (overflow+inexact if
29
spcr = acpi_data_push(table_data, sizeof(*spcr));
21
- * we overflow to infinity, output-denormal) aren't correct for the
30
22
- * complete scale-and-convert operation.
31
@@ -XXX,XX +XXX,XX @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
23
- */
32
spcr->pci_device_id = 0xffff; /* PCI Device ID: not a PCI device */
24
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
33
spcr->pci_vendor_id = 0xffff; /* PCI Vendor ID: not a PCI device */
25
-uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
34
26
- uint32_t shift, \
35
- build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2,
27
- void *fpstp) \
36
- NULL, NULL);
28
-{ \
37
+ build_header(linker, table_data, (void *)(table_data->data + spcr_start),
29
- float_status *fpst = fpstp; \
38
+ "SPCR", table_data->len - spcr_start, 2, NULL, NULL);
30
- int old_exc_flags = get_float_exception_flags(fpst); \
31
- float##fsz tmp; \
32
- if (float##fsz##_is_any_nan(x)) { \
33
- float_raise(float_flag_invalid, fpst); \
34
- return 0; \
35
- } \
36
- tmp = float##fsz##_scalbn(x, shift, fpst); \
37
- old_exc_flags |= get_float_exception_flags(fpst) \
38
- & float_flag_input_denormal; \
39
- set_float_exception_flags(old_exc_flags, fpst); \
40
- return float##fsz##_to_##itype##round(tmp, fpst); \
41
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
42
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
43
+ void *fpst) \
44
+{ \
45
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
46
+ float_raise(float_flag_invalid, fpst); \
47
+ return 0; \
48
+ } \
49
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
39
}
50
}
40
51
41
static void
52
#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
42
@@ -XXX,XX +XXX,XX @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
53
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
43
mem_base += numa_info[i].node_mem;
54
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero) \
44
}
55
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
45
56
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
46
- build_header(linker, table_data, (void *)srat, "SRAT",
57
+ float_round_to_zero, _round_to_zero) \
47
- table_data->len - srat_start, 3, NULL, NULL);
58
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
48
+ build_header(linker, table_data, (void *)(table_data->data + srat_start),
59
+ get_float_rounding_mode(fpst), )
49
+ "SRAT", table_data->len - srat_start, 3, NULL, NULL);
60
61
#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
62
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
63
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
64
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
65
+ get_float_rounding_mode(fpst), )
66
67
VFP_CONV_FIX(sh, d, 64, 64, int16)
68
VFP_CONV_FIX(sl, d, 64, 64, int32)
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
70
return uint64_to_float16_scalbn(x, -shift, fpst);
50
}
71
}
51
72
52
static void
73
-static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
53
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
74
-{
54
AcpiTableMcfg *mcfg;
75
- if (unlikely(float16_is_any_nan(f))) {
55
const MemMapEntry *memmap = vms->memmap;
76
- float_raise(float_flag_invalid, fpst);
56
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
77
- return 0;
57
+ int mcfg_start = table_data->len;
78
- } else {
58
79
- int old_exc_flags = get_float_exception_flags(fpst);
59
mcfg = acpi_data_push(table_data, len);
80
- float64 ret;
60
mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base);
81
-
61
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
82
- ret = float16_to_float64(f, true, fpst);
62
mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
83
- ret = float64_scalbn(ret, shift, fpst);
63
/ PCIE_MMCFG_SIZE_MIN) - 1;
84
- old_exc_flags |= get_float_exception_flags(fpst)
64
85
- & float_flag_input_denormal;
65
- build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
86
- set_float_exception_flags(old_exc_flags, fpst);
66
+ build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
87
-
67
+ "MCFG", table_data->len - mcfg_start, 1, NULL, NULL);
88
- return ret;
89
- }
90
-}
91
-
92
uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
93
{
94
- return float64_to_int16(do_prescale_fp16(x, shift, fpst), fpst);
95
+ if (unlikely(float16_is_any_nan(x))) {
96
+ float_raise(float_flag_invalid, fpst);
97
+ return 0;
98
+ }
99
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
100
+ shift, fpst);
68
}
101
}
69
102
70
/* GTDT */
103
uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
71
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
72
static void build_fadt(GArray *table_data, BIOSLinker *linker,
73
VirtMachineState *vms, unsigned dsdt_tbl_offset)
74
{
104
{
75
+ int fadt_start = table_data->len;
105
- return float64_to_uint16(do_prescale_fp16(x, shift, fpst), fpst);
76
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
106
+ if (unlikely(float16_is_any_nan(x))) {
77
unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data;
107
+ float_raise(float_flag_invalid, fpst);
78
uint16_t bootflags;
108
+ return 0;
79
@@ -XXX,XX +XXX,XX @@ static void build_fadt(GArray *table_data, BIOSLinker *linker,
109
+ }
80
ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt),
110
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
81
ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
111
+ shift, fpst);
82
83
- build_header(linker, table_data,
84
- (void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
85
+ build_header(linker, table_data, (void *)(table_data->data + fadt_start),
86
+ "FACP", table_data->len - fadt_start, 5, NULL, NULL);
87
}
112
}
88
113
89
/* DSDT */
114
uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
115
{
116
- return float64_to_int32(do_prescale_fp16(x, shift, fpst), fpst);
117
+ if (unlikely(float16_is_any_nan(x))) {
118
+ float_raise(float_flag_invalid, fpst);
119
+ return 0;
120
+ }
121
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
122
+ shift, fpst);
123
}
124
125
uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
126
{
127
- return float64_to_uint32(do_prescale_fp16(x, shift, fpst), fpst);
128
+ if (unlikely(float16_is_any_nan(x))) {
129
+ float_raise(float_flag_invalid, fpst);
130
+ return 0;
131
+ }
132
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
133
+ shift, fpst);
134
}
135
136
uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
137
{
138
- return float64_to_int64(do_prescale_fp16(x, shift, fpst), fpst);
139
+ if (unlikely(float16_is_any_nan(x))) {
140
+ float_raise(float_flag_invalid, fpst);
141
+ return 0;
142
+ }
143
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
144
+ shift, fpst);
145
}
146
147
uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
148
{
149
- return float64_to_uint64(do_prescale_fp16(x, shift, fpst), fpst);
150
+ if (unlikely(float16_is_any_nan(x))) {
151
+ float_raise(float_flag_invalid, fpst);
152
+ return 0;
153
+ }
154
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
155
+ shift, fpst);
156
}
157
158
/* Set the current fp rounding mode and return the old one.
90
--
159
--
91
2.7.4
160
2.18.0
92
161
93
162
diff view generated by jsdifflib
1
The GICv2 specification says that reserved register addresses
1
Reduce the size of the per-cpu GICH memory regions from 0x1000
2
must RAZ/WI; now that we implement external abort handling
2
to 0x200. The registers only cover 0x200 bytes, and the Cortex-A15
3
for Arm CPUs this means we must return MEMTX_OK rather than
3
wants to map them at a spacing of 0x200 bytes apart. Having the
4
MEMTX_ERROR, to avoid generating a spurious guest data abort.
4
region be too large interferes with mapping them like that, so
5
reduce it.
5
6
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1513183941-24300-3-git-send-email-peter.maydell@linaro.org
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
9
Message-id: 20180821132811.17675-3-peter.maydell@linaro.org
10
---
10
---
11
hw/intc/arm_gic.c | 5 +++--
11
hw/intc/arm_gic.c | 2 +-
12
1 file changed, 3 insertions(+), 2 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
13
14
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
14
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gic.c
16
--- a/hw/intc/arm_gic.c
17
+++ b/hw/intc/arm_gic.c
17
+++ b/hw/intc/arm_gic.c
18
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
18
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
19
default:
19
for (i = 0; i < s->num_cpu; i++) {
20
qemu_log_mask(LOG_GUEST_ERROR,
20
memory_region_init_io(&s->vifaceiomem[i + 1], OBJECT(s),
21
"gic_cpu_read: Bad offset %x\n", (int)offset);
21
&gic_viface_ops, &s->backref[i],
22
- return MEMTX_ERROR;
22
- "gic_viface", 0x1000);
23
+ *data = 0;
23
+ "gic_viface", 0x200);
24
+ break;
24
sysbus_init_mmio(sbd, &s->vifaceiomem[i + 1]);
25
}
25
}
26
}
26
return MEMTX_OK;
27
}
28
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
29
default:
30
qemu_log_mask(LOG_GUEST_ERROR,
31
"gic_cpu_write: Bad offset %x\n", (int)offset);
32
- return MEMTX_ERROR;
33
+ return MEMTX_OK;
34
}
35
gic_update(s);
36
return MEMTX_OK;
37
--
27
--
38
2.7.4
28
2.18.0
39
29
40
30
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
2
5
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
5
Message-id: 20180103224208.30291-2-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-4-peter.maydell@linaro.org
7
---
9
---
8
hw/timer/pxa2xx_timer.c | 17 +++++++++++++++--
10
hw/arm/vexpress.c | 4 ++++
9
1 file changed, 15 insertions(+), 2 deletions(-)
11
1 file changed, 4 insertions(+)
10
12
11
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
13
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/timer/pxa2xx_timer.c
15
--- a/hw/arm/vexpress.c
14
+++ b/hw/timer/pxa2xx_timer.c
16
+++ b/hw/arm/vexpress.c
15
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void init_cpus(const char *cpu_type, const char *privdev,
16
#include "sysemu/sysemu.h"
18
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
17
#include "hw/arm/pxa.h"
19
sysbus_connect_irq(busdev, n + smp_cpus,
18
#include "hw/sysbus.h"
20
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
19
+#include "qemu/log.h"
21
+ sysbus_connect_irq(busdev, n + 2 * smp_cpus,
20
22
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
21
#define OSMR0    0x00
23
+ sysbus_connect_irq(busdev, n + 3 * smp_cpus,
22
#define OSMR1    0x04
24
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
23
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
24
case OSNR:
25
return s->snapshot;
26
default:
27
+ qemu_log_mask(LOG_UNIMP,
28
+ "%s: unknown register 0x%02" HWADDR_PRIx "\n",
29
+ __func__, offset);
30
+ break;
31
badreg:
32
- hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
33
+ qemu_log_mask(LOG_GUEST_ERROR,
34
+ "%s: incorrect register 0x%02" HWADDR_PRIx "\n",
35
+ __func__, offset);
36
}
37
38
return 0;
39
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset,
40
}
41
break;
42
default:
43
+ qemu_log_mask(LOG_UNIMP,
44
+ "%s: unknown register 0x%02" HWADDR_PRIx " "
45
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
46
+ break;
47
badreg:
48
- hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
49
+ qemu_log_mask(LOG_GUEST_ERROR,
50
+ "%s: incorrect register 0x%02" HWADDR_PRIx " "
51
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
52
}
25
}
53
}
26
}
54
27
55
--
28
--
56
2.7.4
29
2.18.0
57
30
58
31
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
2
5
3
Enable big-endian mode for data accesses on aarch64 for big-endian linux
4
user mode. Activate it for all exception levels as documented by ARM:
5
Set the SCTLR EE bit for ELs 1 through 3. Additionally set bit E0E in
6
EL1 to enable it in EL0 as well.
7
8
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20171220212308.12614-2-michael.weiser@gmx.de
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-5-peter.maydell@linaro.org
12
---
9
---
13
linux-user/main.c | 6 ++++++
10
hw/arm/highbank.c | 6 ++++++
14
1 file changed, 6 insertions(+)
11
1 file changed, 6 insertions(+)
15
12
16
diff --git a/linux-user/main.c b/linux-user/main.c
13
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/linux-user/main.c
15
--- a/hw/arm/highbank.c
19
+++ b/linux-user/main.c
16
+++ b/hw/arm/highbank.c
20
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
17
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
21
}
18
int n;
22
env->pc = regs->pc;
19
qemu_irq cpu_irq[4];
23
env->xregs[31] = regs->sp;
20
qemu_irq cpu_fiq[4];
24
+#ifdef TARGET_WORDS_BIGENDIAN
21
+ qemu_irq cpu_virq[4];
25
+ env->cp15.sctlr_el[1] |= SCTLR_E0E;
22
+ qemu_irq cpu_vfiq[4];
26
+ for (i = 1; i < 4; ++i) {
23
MemoryRegion *sysram;
27
+ env->cp15.sctlr_el[i] |= SCTLR_EE;
24
MemoryRegion *dram;
28
+ }
25
MemoryRegion *sysmem;
29
+#endif
26
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
27
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
28
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
29
cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ);
30
+ cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ);
31
+ cpu_vfiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VFIQ);
30
}
32
}
31
#elif defined(TARGET_ARM)
33
32
{
34
sysmem = get_system_memory();
35
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
36
for (n = 0; n < smp_cpus; n++) {
37
sysbus_connect_irq(busdev, n, cpu_irq[n]);
38
sysbus_connect_irq(busdev, n + smp_cpus, cpu_fiq[n]);
39
+ sysbus_connect_irq(busdev, n + 2 * smp_cpus, cpu_virq[n]);
40
+ sysbus_connect_irq(busdev, n + 3 * smp_cpus, cpu_vfiq[n]);
41
}
42
43
for (n = 0; n < 128; n++) {
33
--
44
--
34
2.7.4
45
2.18.0
35
46
36
47
diff view generated by jsdifflib
New patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-6-peter.maydell@linaro.org
9
---
10
hw/arm/fsl-imx6ul.c | 4 ++++
11
1 file changed, 4 insertions(+)
12
13
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/fsl-imx6ul.c
16
+++ b/hw/arm/fsl-imx6ul.c
17
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
18
irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
19
sysbus_connect_irq(sbd, i, irq);
20
sysbus_connect_irq(sbd, i + smp_cpus, qdev_get_gpio_in(d, ARM_CPU_FIQ));
21
+ sysbus_connect_irq(sbd, i + 2 * smp_cpus,
22
+ qdev_get_gpio_in(d, ARM_CPU_VIRQ));
23
+ sysbus_connect_irq(sbd, i + 3 * smp_cpus,
24
+ qdev_get_gpio_in(d, ARM_CPU_VFIQ));
25
}
26
27
/*
28
--
29
2.18.0
30
31
diff view generated by jsdifflib
New patch
1
Connect the VIRQ and VFIQ lines from the GIC to the CPU;
2
these exist always for both CPU and GIC whether the
3
virtualization extensions are enabled or not, so we
4
can just unconditionally connect them.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-7-peter.maydell@linaro.org
9
---
10
hw/arm/fsl-imx7.c | 4 ++++
11
1 file changed, 4 insertions(+)
12
13
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/fsl-imx7.c
16
+++ b/hw/arm/fsl-imx7.c
17
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
18
sysbus_connect_irq(sbd, i, irq);
19
irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
20
sysbus_connect_irq(sbd, i + smp_cpus, irq);
21
+ irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ);
22
+ sysbus_connect_irq(sbd, i + 2 * smp_cpus, irq);
23
+ irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ);
24
+ sysbus_connect_irq(sbd, i + 3 * smp_cpus, irq);
25
}
26
27
/*
28
--
29
2.18.0
30
31
diff view generated by jsdifflib
New patch
1
For the A15MPCore internal peripheral object, we handle GIC
2
security extensions support by checking whether the CPUs
3
have EL3 enabled; if so then we enable it also on the GIC.
4
Handle the virtualization extensions in the same way: if the
5
CPU has EL2 then enable it on the GIC and wire up the
6
virtualization-specific memory regions and the maintenance
7
interrupt.
1
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
11
Message-id: 20180821132811.17675-8-peter.maydell@linaro.org
12
---
13
hw/cpu/a15mpcore.c | 31 ++++++++++++++++++++++++++++---
14
1 file changed, 28 insertions(+), 3 deletions(-)
15
16
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/cpu/a15mpcore.c
19
+++ b/hw/cpu/a15mpcore.c
20
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
21
int i;
22
Error *err = NULL;
23
bool has_el3;
24
+ bool has_el2;
25
Object *cpuobj;
26
27
gicdev = DEVICE(&s->gic);
28
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
29
has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
30
object_property_get_bool(cpuobj, "has_el3", &error_abort);
31
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
32
+ /* Similarly for virtualization support */
33
+ has_el2 = object_property_find(cpuobj, "has_el2", NULL) &&
34
+ object_property_get_bool(cpuobj, "has_el2", &error_abort);
35
+ qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2);
36
}
37
38
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
39
@@ -XXX,XX +XXX,XX @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
40
qdev_get_gpio_in(gicdev,
41
ppibase + timer_irq[irq]));
42
}
43
+ if (has_el2) {
44
+ /* Connect the GIC maintenance interrupt to PPI ID 25 */
45
+ sysbus_connect_irq(SYS_BUS_DEVICE(gicdev), i + 4 * s->num_cpu,
46
+ qdev_get_gpio_in(gicdev, ppibase + 25));
47
+ }
48
}
49
50
/* Memory map (addresses are offsets from PERIPHBASE):
51
* 0x0000-0x0fff -- reserved
52
* 0x1000-0x1fff -- GIC Distributor
53
* 0x2000-0x3fff -- GIC CPU interface
54
- * 0x4000-0x4fff -- GIC virtual interface control (not modelled)
55
- * 0x5000-0x5fff -- GIC virtual interface control (not modelled)
56
- * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
57
+ * 0x4000-0x4fff -- GIC virtual interface control for this CPU
58
+ * 0x5000-0x51ff -- GIC virtual interface control for CPU 0
59
+ * 0x5200-0x53ff -- GIC virtual interface control for CPU 1
60
+ * 0x5400-0x55ff -- GIC virtual interface control for CPU 2
61
+ * 0x5600-0x57ff -- GIC virtual interface control for CPU 3
62
+ * 0x6000-0x7fff -- GIC virtual CPU interface
63
*/
64
memory_region_add_subregion(&s->container, 0x1000,
65
sysbus_mmio_get_region(busdev, 0));
66
memory_region_add_subregion(&s->container, 0x2000,
67
sysbus_mmio_get_region(busdev, 1));
68
+ if (has_el2) {
69
+ memory_region_add_subregion(&s->container, 0x4000,
70
+ sysbus_mmio_get_region(busdev, 2));
71
+ memory_region_add_subregion(&s->container, 0x6000,
72
+ sysbus_mmio_get_region(busdev, 3));
73
+ for (i = 0; i < s->num_cpu; i++) {
74
+ hwaddr base = 0x5000 + i * 0x200;
75
+ MemoryRegion *mr = sysbus_mmio_get_region(busdev,
76
+ 4 + s->num_cpu + i);
77
+ memory_region_add_subregion(&s->container, base, mr);
78
+ }
79
+ }
80
}
81
82
static Property a15mp_priv_properties[] = {
83
--
84
2.18.0
85
86
diff view generated by jsdifflib
New patch
1
Don't request that the arm_load_kernel() code should boot in secure
2
state if the CPU doesn't have a secure state. Currently this
3
doesn't make a difference because the boot.c code only examines
4
the secure_boot flag in code guarded by an ARM_FEATURE_EL3 check,
5
but upcoming changes for supporting booting into Hyp mode will
6
change that.
1
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180821132811.17675-9-peter.maydell@linaro.org
11
---
12
hw/arm/vexpress.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/vexpress.c
18
+++ b/hw/arm/vexpress.c
19
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
20
daughterboard->bootinfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
21
daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
22
daughterboard->bootinfo.modify_dtb = vexpress_modify_dtb;
23
- /* Indicate that when booting Linux we should be in secure state */
24
- daughterboard->bootinfo.secure_boot = true;
25
+ /* When booting Linux we should be in secure state if the CPU has one. */
26
+ daughterboard->bootinfo.secure_boot = vms->secure;
27
arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);
28
}
29
30
--
31
2.18.0
32
33
diff view generated by jsdifflib
New patch
1
Add a "virtualization" property to the vexpress-a15 board,
2
controlling presence of EL2. As with EL3, we default to
3
enabling it, but the user can disable it if they have an
4
older guest which can't cope with it being present.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180821132811.17675-10-peter.maydell@linaro.org
9
---
10
hw/arm/vexpress.c | 56 ++++++++++++++++++++++++++++++++++++++++++++---
11
1 file changed, 53 insertions(+), 3 deletions(-)
12
13
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/vexpress.c
16
+++ b/hw/arm/vexpress.c
17
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
typedef struct {
19
MachineState parent;
20
bool secure;
21
+ bool virt;
22
} VexpressMachineState;
23
24
#define TYPE_VEXPRESS_MACHINE "vexpress"
25
@@ -XXX,XX +XXX,XX @@ struct VEDBoardInfo {
26
};
27
28
static void init_cpus(const char *cpu_type, const char *privdev,
29
- hwaddr periphbase, qemu_irq *pic, bool secure)
30
+ hwaddr periphbase, qemu_irq *pic, bool secure, bool virt)
31
{
32
DeviceState *dev;
33
SysBusDevice *busdev;
34
@@ -XXX,XX +XXX,XX @@ static void init_cpus(const char *cpu_type, const char *privdev,
35
if (!secure) {
36
object_property_set_bool(cpuobj, false, "has_el3", NULL);
37
}
38
+ if (!virt) {
39
+ if (object_property_find(cpuobj, "has_el2", NULL)) {
40
+ object_property_set_bool(cpuobj, false, "has_el2", NULL);
41
+ }
42
+ }
43
44
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
45
object_property_set_int(cpuobj, periphbase,
46
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
47
memory_region_add_subregion(sysmem, 0x60000000, ram);
48
49
/* 0x1e000000 A9MPCore (SCU) private memory region */
50
- init_cpus(cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic, vms->secure);
51
+ init_cpus(cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic,
52
+ vms->secure, vms->virt);
53
54
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
55
56
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
57
memory_region_add_subregion(sysmem, 0x80000000, ram);
58
59
/* 0x2c000000 A15MPCore private memory region (GIC) */
60
- init_cpus(cpu_type, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure);
61
+ init_cpus(cpu_type, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure,
62
+ vms->virt);
63
64
/* A15 daughterboard peripherals: */
65
66
@@ -XXX,XX +XXX,XX @@ static void vexpress_set_secure(Object *obj, bool value, Error **errp)
67
vms->secure = value;
68
}
69
70
+static bool vexpress_get_virt(Object *obj, Error **errp)
71
+{
72
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
73
+
74
+ return vms->virt;
75
+}
76
+
77
+static void vexpress_set_virt(Object *obj, bool value, Error **errp)
78
+{
79
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
80
+
81
+ vms->virt = value;
82
+}
83
+
84
static void vexpress_instance_init(Object *obj)
85
{
86
VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
87
@@ -XXX,XX +XXX,XX @@ static void vexpress_instance_init(Object *obj)
88
NULL);
89
}
90
91
+static void vexpress_a15_instance_init(Object *obj)
92
+{
93
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
94
+
95
+ /*
96
+ * For the vexpress-a15, EL2 is by default enabled if EL3 is,
97
+ * but can also be specifically set to on or off.
98
+ */
99
+ vms->virt = true;
100
+ object_property_add_bool(obj, "virtualization", vexpress_get_virt,
101
+ vexpress_set_virt, NULL);
102
+ object_property_set_description(obj, "virtualization",
103
+ "Set on/off to enable/disable the ARM "
104
+ "Virtualization Extensions "
105
+ "(defaults to same as 'secure')",
106
+ NULL);
107
+}
108
+
109
+static void vexpress_a9_instance_init(Object *obj)
110
+{
111
+ VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
112
+
113
+ /* The A9 doesn't have the virt extensions */
114
+ vms->virt = false;
115
+}
116
+
117
static void vexpress_class_init(ObjectClass *oc, void *data)
118
{
119
MachineClass *mc = MACHINE_CLASS(oc);
120
@@ -XXX,XX +XXX,XX @@ static const TypeInfo vexpress_a9_info = {
121
.name = TYPE_VEXPRESS_A9_MACHINE,
122
.parent = TYPE_VEXPRESS_MACHINE,
123
.class_init = vexpress_a9_class_init,
124
+ .instance_init = vexpress_a9_instance_init,
125
};
126
127
static const TypeInfo vexpress_a15_info = {
128
.name = TYPE_VEXPRESS_A15_MACHINE,
129
.parent = TYPE_VEXPRESS_MACHINE,
130
.class_init = vexpress_a15_class_init,
131
+ .instance_init = vexpress_a15_instance_init,
132
};
133
134
static void vexpress_machine_init(void)
135
--
136
2.18.0
137
138
diff view generated by jsdifflib
New patch
1
The v8 AArch32 HACTLR2 register maps to bits [63:32] of ACTLR_EL2.
2
We implement ACTLR_EL2 as RAZ/WI, so make HACTLR2 also RAZ/WI.
3
(We put the regdef next to ACTLR_EL2 as a reminder in case we
4
ever make ACTLR_EL2 something other than RAZ/WI).
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180820153020.21478-2-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 10 ++++++++++
13
1 file changed, 10 insertions(+)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
20
REGINFO_SENTINEL
21
};
22
define_arm_cp_regs(cpu, auxcr_reginfo);
23
+ if (arm_feature(env, ARM_FEATURE_V8)) {
24
+ /* HACTLR2 maps to ACTLR_EL2[63:32] and is not in ARMv7 */
25
+ ARMCPRegInfo hactlr2_reginfo = {
26
+ .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
27
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
28
+ .access = PL2_RW, .type = ARM_CP_CONST,
29
+ .resetvalue = 0
30
+ };
31
+ define_one_arm_cp_reg(cpu, &hactlr2_reginfo);
32
+ }
33
}
34
35
if (arm_feature(env, ARM_FEATURE_CBAR)) {
36
--
37
2.18.0
38
39
diff view generated by jsdifflib
New patch
1
The AArch32 HCR and HCR2 registers alias HCR_EL2
2
bits [31:0] and [63:32]; implement them.
1
3
4
Since HCR2 exists in ARMv8 but not ARMv7, we need new
5
regdef arrays for "we have EL3, not EL2, we're ARMv8"
6
and "we have EL2, we're ARMv8" to hold the definitions.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Message-id: 20180820153020.21478-3-peter.maydell@linaro.org
13
---
14
target/arm/helper.c | 54 +++++++++++++++++++++++++++++++++++++++++----
15
1 file changed, 50 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
22
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
23
.access = PL2_RW,
24
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
25
- { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
26
+ { .name = "HCR_EL2", .state = ARM_CP_STATE_BOTH,
27
.type = ARM_CP_NO_RAW,
28
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
29
.access = PL2_RW,
30
- .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
31
+ .type = ARM_CP_CONST, .resetvalue = 0 },
32
{ .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
33
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
34
.access = PL2_RW,
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
36
REGINFO_SENTINEL
37
};
38
39
+/* Ditto, but for registers which exist in ARMv8 but not v7 */
40
+static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
41
+ { .name = "HCR2", .state = ARM_CP_STATE_AA32,
42
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
43
+ .access = PL2_RW,
44
+ .type = ARM_CP_CONST, .resetvalue = 0 },
45
+ REGINFO_SENTINEL
46
+};
47
+
48
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
49
{
50
ARMCPU *cpu = arm_env_get_cpu(env);
51
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
* HCR_PTW forbids certain page-table setups
53
* HCR_DC Disables stage1 and enables stage2 translation
54
*/
55
- if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
56
+ if ((env->cp15.hcr_el2 ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
57
tlb_flush(CPU(cpu));
58
}
59
- raw_write(env, ri, value);
60
+ env->cp15.hcr_el2 = value;
61
+}
62
+
63
+static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri,
64
+ uint64_t value)
65
+{
66
+ /* Handle HCR2 write, i.e. write to high half of HCR_EL2 */
67
+ value = deposit64(env->cp15.hcr_el2, 32, 32, value);
68
+ hcr_write(env, NULL, value);
69
+}
70
+
71
+static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
72
+ uint64_t value)
73
+{
74
+ /* Handle HCR write, i.e. write to low half of HCR_EL2 */
75
+ value = deposit64(env->cp15.hcr_el2, 0, 32, value);
76
+ hcr_write(env, NULL, value);
77
}
78
79
static const ARMCPRegInfo el2_cp_reginfo[] = {
80
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
81
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
82
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
83
.writefn = hcr_write },
84
+ { .name = "HCR", .state = ARM_CP_STATE_AA32,
85
+ .type = ARM_CP_ALIAS,
86
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
87
+ .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
88
+ .writefn = hcr_writelow },
89
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
90
.type = ARM_CP_ALIAS,
91
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
92
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
93
REGINFO_SENTINEL
94
};
95
96
+static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
97
+ { .name = "HCR2", .state = ARM_CP_STATE_AA32,
98
+ .type = ARM_CP_ALIAS,
99
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
100
+ .access = PL2_RW,
101
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
102
+ .writefn = hcr_writehigh },
103
+ REGINFO_SENTINEL
104
+};
105
+
106
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
107
bool isread)
108
{
109
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
110
};
111
define_arm_cp_regs(cpu, vpidr_regs);
112
define_arm_cp_regs(cpu, el2_cp_reginfo);
113
+ if (arm_feature(env, ARM_FEATURE_V8)) {
114
+ define_arm_cp_regs(cpu, el2_v8_cp_reginfo);
115
+ }
116
/* RVBAR_EL2 is only implemented if EL2 is the highest EL */
117
if (!arm_feature(env, ARM_FEATURE_EL3)) {
118
ARMCPRegInfo rvbar = {
119
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
120
};
121
define_arm_cp_regs(cpu, vpidr_regs);
122
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
123
+ if (arm_feature(env, ARM_FEATURE_V8)) {
124
+ define_arm_cp_regs(cpu, el3_no_el2_v8_cp_reginfo);
125
+ }
126
}
127
}
128
if (arm_feature(env, ARM_FEATURE_EL3)) {
129
--
130
2.18.0
131
132
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Factor out the code which changes the CPU state so as to
2
actually take an exception to AArch32. We're going to want
3
to use this for handling exception entry to Hyp mode.
2
4
3
Refactor imx_eth_enable_rx() to have more meaningfull variable name
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
than 'tmp' and to reduce number of logical negations done.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20180820153020.21478-4-peter.maydell@linaro.org
10
---
11
target/arm/helper.c | 64 +++++++++++++++++++++++++++++----------------
12
1 file changed, 41 insertions(+), 23 deletions(-)
5
13
6
Cc: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: yurovsky@gmail.com
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/net/imx_fec.c | 8 ++++----
18
1 file changed, 4 insertions(+), 4 deletions(-)
19
20
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/imx_fec.c
16
--- a/target/arm/helper.c
23
+++ b/hw/net/imx_fec.c
17
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s)
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sync_64_to_32(CPUARMState *env)
25
static void imx_eth_enable_rx(IMXFECState *s)
19
env->regs[15] = env->pc;
20
}
21
22
+static void take_aarch32_exception(CPUARMState *env, int new_mode,
23
+ uint32_t mask, uint32_t offset,
24
+ uint32_t newpc)
25
+{
26
+ /* Change the CPU state so as to actually take the exception. */
27
+ switch_mode(env, new_mode);
28
+ /*
29
+ * For exceptions taken to AArch32 we must clear the SS bit in both
30
+ * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
31
+ */
32
+ env->uncached_cpsr &= ~PSTATE_SS;
33
+ env->spsr = cpsr_read(env);
34
+ /* Clear IT bits. */
35
+ env->condexec_bits = 0;
36
+ /* Switch to the new mode, and to the correct instruction set. */
37
+ env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
38
+ /* Set new mode endianness */
39
+ env->uncached_cpsr &= ~CPSR_E;
40
+ if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
41
+ env->uncached_cpsr |= CPSR_E;
42
+ }
43
+ env->daif |= mask;
44
+
45
+ if (new_mode == ARM_CPU_MODE_HYP) {
46
+ env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
47
+ env->elr_el[2] = env->regs[15];
48
+ } else {
49
+ /*
50
+ * this is a lie, as there was no c1_sys on V4T/V5, but who cares
51
+ * and we should just guard the thumb mode on V4
52
+ */
53
+ if (arm_feature(env, ARM_FEATURE_V4T)) {
54
+ env->thumb =
55
+ (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
56
+ }
57
+ env->regs[14] = env->regs[15] + offset;
58
+ }
59
+ env->regs[15] = newpc;
60
+}
61
+
62
static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
26
{
63
{
27
IMXFECBufDesc bd;
64
ARMCPU *cpu = ARM_CPU(cs);
28
- bool tmp;
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
29
+ bool rx_ring_full;
66
env->cp15.scr_el3 &= ~SCR_NS;
30
31
imx_fec_read_bd(&bd, s->rx_descriptor);
32
33
- tmp = ((bd.flags & ENET_BD_E) != 0);
34
+ rx_ring_full = !(bd.flags & ENET_BD_E);
35
36
- if (!tmp) {
37
+ if (rx_ring_full) {
38
FEC_PRINTF("RX buffer full\n");
39
} else if (!s->regs[ENET_RDAR]) {
40
qemu_flush_queued_packets(qemu_get_queue(s->nic));
41
}
67
}
42
68
43
- s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0;
69
- switch_mode (env, new_mode);
44
+ s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
70
- /* For exceptions taken to AArch32 we must clear the SS bit in both
71
- * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
72
- */
73
- env->uncached_cpsr &= ~PSTATE_SS;
74
- env->spsr = cpsr_read(env);
75
- /* Clear IT bits. */
76
- env->condexec_bits = 0;
77
- /* Switch to the new mode, and to the correct instruction set. */
78
- env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
79
- /* Set new mode endianness */
80
- env->uncached_cpsr &= ~CPSR_E;
81
- if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
82
- env->uncached_cpsr |= CPSR_E;
83
- }
84
- env->daif |= mask;
85
- /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
86
- * and we should just guard the thumb mode on V4 */
87
- if (arm_feature(env, ARM_FEATURE_V4T)) {
88
- env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
89
- }
90
- env->regs[14] = env->regs[15] + offset;
91
- env->regs[15] = addr;
92
+ take_aarch32_exception(env, new_mode, mask, offset, addr);
45
}
93
}
46
94
47
static void imx_eth_reset(DeviceState *d)
95
/* Handle exception entry to a target EL which is using AArch64 */
48
--
96
--
49
2.7.4
97
2.18.0
50
98
51
99
diff view generated by jsdifflib
New patch
1
Implement the necessary support code for taking exceptions
2
to Hyp mode in AArch32.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180820153020.21478-5-peter.maydell@linaro.org
9
---
10
target/arm/helper.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 82 insertions(+)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
18
env->regs[15] = newpc;
19
}
20
21
+static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
22
+{
23
+ /*
24
+ * Handle exception entry to Hyp mode; this is sufficiently
25
+ * different to entry to other AArch32 modes that we handle it
26
+ * separately here.
27
+ *
28
+ * The vector table entry used is always the 0x14 Hyp mode entry point,
29
+ * unless this is an UNDEF/HVC/abort taken from Hyp to Hyp.
30
+ * The offset applied to the preferred return address is always zero
31
+ * (see DDI0487C.a section G1.12.3).
32
+ * PSTATE A/I/F masks are set based only on the SCR.EA/IRQ/FIQ values.
33
+ */
34
+ uint32_t addr, mask;
35
+ ARMCPU *cpu = ARM_CPU(cs);
36
+ CPUARMState *env = &cpu->env;
37
+
38
+ switch (cs->exception_index) {
39
+ case EXCP_UDEF:
40
+ addr = 0x04;
41
+ break;
42
+ case EXCP_SWI:
43
+ addr = 0x14;
44
+ break;
45
+ case EXCP_BKPT:
46
+ /* Fall through to prefetch abort. */
47
+ case EXCP_PREFETCH_ABORT:
48
+ env->cp15.ifar_s = env->exception.vaddress;
49
+ qemu_log_mask(CPU_LOG_INT, "...with HIFAR 0x%x\n",
50
+ (uint32_t)env->exception.vaddress);
51
+ addr = 0x0c;
52
+ break;
53
+ case EXCP_DATA_ABORT:
54
+ env->cp15.dfar_s = env->exception.vaddress;
55
+ qemu_log_mask(CPU_LOG_INT, "...with HDFAR 0x%x\n",
56
+ (uint32_t)env->exception.vaddress);
57
+ addr = 0x10;
58
+ break;
59
+ case EXCP_IRQ:
60
+ addr = 0x18;
61
+ break;
62
+ case EXCP_FIQ:
63
+ addr = 0x1c;
64
+ break;
65
+ case EXCP_HVC:
66
+ addr = 0x08;
67
+ break;
68
+ case EXCP_HYP_TRAP:
69
+ addr = 0x14;
70
+ default:
71
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
72
+ }
73
+
74
+ if (cs->exception_index != EXCP_IRQ && cs->exception_index != EXCP_FIQ) {
75
+ env->cp15.esr_el[2] = env->exception.syndrome;
76
+ }
77
+
78
+ if (arm_current_el(env) != 2 && addr < 0x14) {
79
+ addr = 0x14;
80
+ }
81
+
82
+ mask = 0;
83
+ if (!(env->cp15.scr_el3 & SCR_EA)) {
84
+ mask |= CPSR_A;
85
+ }
86
+ if (!(env->cp15.scr_el3 & SCR_IRQ)) {
87
+ mask |= CPSR_I;
88
+ }
89
+ if (!(env->cp15.scr_el3 & SCR_FIQ)) {
90
+ mask |= CPSR_F;
91
+ }
92
+
93
+ addr += env->cp15.hvbar;
94
+
95
+ take_aarch32_exception(env, ARM_CPU_MODE_HYP, mask, 0, addr);
96
+}
97
+
98
static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
99
{
100
ARMCPU *cpu = ARM_CPU(cs);
101
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
102
env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, 2, 4, moe);
103
}
104
105
+ if (env->exception.target_el == 2) {
106
+ arm_cpu_do_interrupt_aarch32_hyp(cs);
107
+ return;
108
+ }
109
+
110
/* TODO: Vectored interrupt controller. */
111
switch (cs->exception_index) {
112
case EXCP_UDEF:
113
--
114
2.18.0
115
116
diff view generated by jsdifflib
New patch
1
On 32-bit exception entry, CPSR.J must always be set to 0
2
(see v7A Arm ARM DDI0406C.c B1.8.5). CPSR.IL must also
3
be cleared on 32-bit exception entry (see v8A Arm ARM
4
DDI0487C.a G1.10).
1
5
6
Clear these bits. (This fixes a bug which will never be noticed
7
by non-buggy guests.)
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
13
Message-id: 20180820153020.21478-6-peter.maydell@linaro.org
14
---
15
target/arm/helper.c | 2 ++
16
1 file changed, 2 insertions(+)
17
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
23
if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
24
env->uncached_cpsr |= CPSR_E;
25
}
26
+ /* J and IL must always be cleared for exception entry */
27
+ env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
28
env->daif |= mask;
29
30
if (new_mode == ARM_CPU_MODE_HYP) {
31
--
32
2.18.0
33
34
diff view generated by jsdifflib
New patch
1
The kernel booting specification for an AArch32 kernel requires that
2
it is booted in Hyp mode if available; otherwise the kernel can't
3
enable KVM. We were incorrectly leaving the kernel in SVC mode.
4
If we're booting an AArch32 kernel in the Nonsecure state and Hyp
5
mode is available, start in it.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
11
Message-id: 20180820153020.21478-7-peter.maydell@linaro.org
12
---
13
hw/arm/boot.c | 11 +++++++++++
14
1 file changed, 11 insertions(+)
15
16
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/boot.c
19
+++ b/hw/arm/boot.c
20
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
21
}
22
}
23
24
+ if (!env->aarch64 && !info->secure_boot &&
25
+ arm_feature(env, ARM_FEATURE_EL2)) {
26
+ /*
27
+ * This is an AArch32 boot not to Secure state, and
28
+ * we have Hyp mode available, so boot the kernel into
29
+ * Hyp mode. This is not how the CPU comes out of reset,
30
+ * so we need to manually put it there.
31
+ */
32
+ cpsr_write(env, ARM_CPU_MODE_HYP, CPSR_M, CPSRWriteRaw);
33
+ }
34
+
35
if (cs == first_cpu) {
36
AddressSpace *as = arm_boot_address_space(cpu, info);
37
38
--
39
2.18.0
40
41
diff view generated by jsdifflib
New patch
1
The MPS2 FPGAIO block includes some simple free-running counters.
2
Implement these.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180820141116.9118-2-peter.maydell@linaro.org
7
---
8
include/hw/misc/mps2-fpgaio.h | 4 +++
9
hw/misc/mps2-fpgaio.c | 53 ++++++++++++++++++++++++++++++++++-
10
2 files changed, 56 insertions(+), 1 deletion(-)
11
12
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/misc/mps2-fpgaio.h
15
+++ b/include/hw/misc/mps2-fpgaio.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
uint32_t misc;
18
19
uint32_t prescale_clk;
20
+
21
+ /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
22
+ int64_t clk1hz_tick_offset;
23
+ int64_t clk100hz_tick_offset;
24
} MPS2FPGAIO;
25
26
#endif
27
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/misc/mps2-fpgaio.c
30
+++ b/hw/misc/mps2-fpgaio.c
31
@@ -XXX,XX +XXX,XX @@
32
#include "hw/sysbus.h"
33
#include "hw/registerfields.h"
34
#include "hw/misc/mps2-fpgaio.h"
35
+#include "qemu/timer.h"
36
37
REG32(LED0, 0)
38
REG32(BUTTON, 8)
39
@@ -XXX,XX +XXX,XX @@ REG32(PRESCALE, 0x1c)
40
REG32(PSCNTR, 0x20)
41
REG32(MISC, 0x4c)
42
43
+static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
44
+{
45
+ return muldiv64(now - tick_offset, frq, NANOSECONDS_PER_SECOND);
46
+}
47
+
48
+static int64_t tickoff_from_counter(int64_t now, uint32_t count, int frq)
49
+{
50
+ return now - muldiv64(count, NANOSECONDS_PER_SECOND, frq);
51
+}
52
+
53
static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
54
{
55
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
56
uint64_t r;
57
+ int64_t now;
58
59
switch (offset) {
60
case A_LED0:
61
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
62
r = s->misc;
63
break;
64
case A_CLK1HZ:
65
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
66
+ r = counter_from_tickoff(now, s->clk1hz_tick_offset, 1);
67
+ break;
68
case A_CLK100HZ:
69
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
70
+ r = counter_from_tickoff(now, s->clk100hz_tick_offset, 100);
71
+ break;
72
case A_COUNTER:
73
case A_PSCNTR:
74
- /* These are all upcounters of various frequencies. */
75
qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
76
r = 0;
77
break;
78
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
82
+ int64_t now;
83
84
trace_mps2_fpgaio_write(offset, value, size);
85
86
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
87
"MPS2 FPGAIO: MISC control bits unimplemented\n");
88
s->misc = value;
89
break;
90
+ case A_CLK1HZ:
91
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
92
+ s->clk1hz_tick_offset = tickoff_from_counter(now, value, 1);
93
+ break;
94
+ case A_CLK100HZ:
95
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
96
+ s->clk100hz_tick_offset = tickoff_from_counter(now, value, 100);
97
+ break;
98
default:
99
qemu_log_mask(LOG_GUEST_ERROR,
100
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
101
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps mps2_fpgaio_ops = {
102
static void mps2_fpgaio_reset(DeviceState *dev)
103
{
104
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
105
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
106
107
trace_mps2_fpgaio_reset();
108
s->led0 = 0;
109
s->prescale = 0;
110
s->misc = 0;
111
+ s->clk1hz_tick_offset = tickoff_from_counter(now, 0, 1);
112
+ s->clk100hz_tick_offset = tickoff_from_counter(now, 0, 100);
113
}
114
115
static void mps2_fpgaio_init(Object *obj)
116
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
117
sysbus_init_mmio(sbd, &s->iomem);
118
}
119
120
+static bool mps2_fpgaio_counters_needed(void *opaque)
121
+{
122
+ /* Currently vmstate.c insists all subsections have a 'needed' function */
123
+ return true;
124
+}
125
+
126
+static const VMStateDescription mps2_fpgaio_counters_vmstate = {
127
+ .name = "mps2-fpgaio/counters",
128
+ .version_id = 1,
129
+ .minimum_version_id = 1,
130
+ .needed = mps2_fpgaio_counters_needed,
131
+ .fields = (VMStateField[]) {
132
+ VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
133
+ VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
134
+ VMSTATE_END_OF_LIST()
135
+ }
136
+};
137
+
138
static const VMStateDescription mps2_fpgaio_vmstate = {
139
.name = "mps2-fpgaio",
140
.version_id = 1,
141
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
142
VMSTATE_UINT32(prescale, MPS2FPGAIO),
143
VMSTATE_UINT32(misc, MPS2FPGAIO),
144
VMSTATE_END_OF_LIST()
145
+ },
146
+ .subsections = (const VMStateDescription*[]) {
147
+ &mps2_fpgaio_counters_vmstate,
148
+ NULL
149
}
150
};
151
152
--
153
2.18.0
154
155
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
In the MPS2 FPGAIO, PSCNTR is a free-running downcounter with
2
a reload value configured via the PRESCALE register, and
3
COUNTER counts up by 1 every time PSCNTR reaches zero.
4
Implement these counters.
2
5
3
Needed to support latest Linux kernel driver which relies on that
6
We can just increment the counters migration subsection's
4
functionality.
7
version ID because we only added it in the previous commit,
8
so no released QEMU versions will be using it.
5
9
6
Cc: Peter Maydell <peter.maydell@linaro.org>
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: yurovsky@gmail.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20180820141116.9118-3-peter.maydell@linaro.org
15
---
14
---
16
include/hw/net/imx_fec.h | 2 ++
15
include/hw/misc/mps2-fpgaio.h | 6 +++
17
hw/net/imx_fec.c | 23 +++++++++++++++++++++++
16
hw/misc/mps2-fpgaio.c | 97 +++++++++++++++++++++++++++++++++--
18
2 files changed, 25 insertions(+)
17
2 files changed, 99 insertions(+), 4 deletions(-)
19
18
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
19
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
21
--- a/include/hw/misc/mps2-fpgaio.h
23
+++ b/include/hw/net/imx_fec.h
22
+++ b/include/hw/misc/mps2-fpgaio.h
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
#define ENET_TWFR_TFWR_LENGTH (6)
24
uint32_t prescale;
26
#define ENET_TWFR_STRFWD (1 << 8)
25
uint32_t misc;
27
26
28
+#define ENET_RACC_SHIFT16 BIT(7)
27
+ /* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
28
+ int64_t pscntr_sync_ticks;
29
+ /* Values of COUNTER and PSCNTR at time pscntr_sync_ticks */
30
+ uint32_t counter;
31
+ uint32_t pscntr;
29
+
32
+
30
/* Buffer Descriptor. */
33
uint32_t prescale_clk;
31
typedef struct {
34
32
uint16_t length;
35
/* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
33
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
36
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
34
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/net/imx_fec.c
38
--- a/hw/misc/mps2-fpgaio.c
36
+++ b/hw/net/imx_fec.c
39
+++ b/hw/misc/mps2-fpgaio.c
37
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
40
@@ -XXX,XX +XXX,XX @@ static int64_t tickoff_from_counter(int64_t now, uint32_t count, int frq)
38
uint8_t *crc_ptr;
41
return now - muldiv64(count, NANOSECONDS_PER_SECOND, frq);
39
unsigned int buf_len;
42
}
40
size_t size = len;
43
41
+ bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
44
+static void resync_counter(MPS2FPGAIO *s)
42
45
+{
43
FEC_PRINTF("len %d\n", (int)size);
46
+ /*
44
47
+ * Update s->counter and s->pscntr to their true current values
45
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
48
+ * by calculating how many times PSCNTR has ticked since the
46
crc = cpu_to_be32(crc32(~0, buf, size));
49
+ * last time we did a resync.
47
crc_ptr = (uint8_t *) &crc;
50
+ */
48
51
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
49
+ if (shift16) {
52
+ int64_t elapsed = now - s->pscntr_sync_ticks;
50
+ size += 2;
53
+
54
+ /*
55
+ * Round elapsed down to a whole number of PSCNTR ticks, so we don't
56
+ * lose time if we do multiple resyncs in a single tick.
57
+ */
58
+ uint64_t ticks = muldiv64(elapsed, s->prescale_clk, NANOSECONDS_PER_SECOND);
59
+
60
+ /*
61
+ * Work out what PSCNTR and COUNTER have moved to. We assume that
62
+ * PSCNTR reloads from PRESCALE one tick-period after it hits zero,
63
+ * and that COUNTER increments at the same moment.
64
+ */
65
+ if (ticks == 0) {
66
+ /* We haven't ticked since the last time we were asked */
67
+ return;
68
+ } else if (ticks < s->pscntr) {
69
+ /* We haven't yet reached zero, just reduce the PSCNTR */
70
+ s->pscntr -= ticks;
71
+ } else {
72
+ if (s->prescale == 0) {
73
+ /*
74
+ * If the reload value is zero then the PSCNTR will stick
75
+ * at zero once it reaches it, and so we will increment
76
+ * COUNTER every tick after that.
77
+ */
78
+ s->counter += ticks - s->pscntr;
79
+ s->pscntr = 0;
80
+ } else {
81
+ /*
82
+ * This is the complicated bit. This ASCII art diagram gives an
83
+ * example with PRESCALE==5 PSCNTR==7:
84
+ *
85
+ * ticks 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
86
+ * PSCNTR 7 6 5 4 3 2 1 0 5 4 3 2 1 0 5
87
+ * cinc 1 2
88
+ * y 0 1 2 3 4 5 6 7 8 9 10 11 12
89
+ * x 0 1 2 3 4 5 0 1 2 3 4 5 0
90
+ *
91
+ * where x = y % (s->prescale + 1)
92
+ * and so PSCNTR = s->prescale - x
93
+ * and COUNTER is incremented by y / (s->prescale + 1)
94
+ *
95
+ * The case where PSCNTR < PRESCALE works out the same,
96
+ * though we must be careful to calculate y as 64-bit unsigned
97
+ * for all parts of the expression.
98
+ * y < 0 is not possible because that implies ticks < s->pscntr.
99
+ */
100
+ uint64_t y = ticks - s->pscntr + s->prescale;
101
+ s->pscntr = s->prescale - (y % (s->prescale + 1));
102
+ s->counter += y / (s->prescale + 1);
103
+ }
51
+ }
104
+ }
52
+
105
+
53
/* Huge frames are truncted. */
106
+ /*
54
if (size > s->regs[ENET_FTRL]) {
107
+ * Only advance the sync time to the timestamp of the last PSCNTR tick,
55
size = s->regs[ENET_FTRL];
108
+ * not all the way to 'now', so we don't lose time if we do multiple
56
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
109
+ * resyncs in a single tick.
57
buf_len += size - 4;
110
+ */
58
}
111
+ s->pscntr_sync_ticks += muldiv64(ticks, NANOSECONDS_PER_SECOND,
59
buf_addr = bd.data;
112
+ s->prescale_clk);
113
+}
60
+
114
+
61
+ if (shift16) {
115
static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
62
+ /*
116
{
63
+ * If SHIFT16 bit of ENETx_RACC register is set we need to
117
MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
64
+ * align the payload to 4-byte boundary.
118
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
65
+ */
119
r = counter_from_tickoff(now, s->clk100hz_tick_offset, 100);
66
+ const uint8_t zeros[2] = { 0 };
120
break;
67
+
121
case A_COUNTER:
68
+ dma_memory_write(&address_space_memory, buf_addr,
122
+ resync_counter(s);
69
+ zeros, sizeof(zeros));
123
+ r = s->counter;
70
+
124
+ break;
71
+ buf_addr += sizeof(zeros);
125
case A_PSCNTR:
72
+ buf_len -= sizeof(zeros);
126
- qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
73
+
127
- r = 0;
74
+ /* We only do this once per Ethernet frame */
128
+ resync_counter(s);
75
+ shift16 = false;
129
+ r = s->pscntr;
76
+ }
130
break;
77
+
131
default:
78
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
132
qemu_log_mask(LOG_GUEST_ERROR,
79
buf += buf_len;
133
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
80
if (size < 4) {
134
s->led0 = value & 0x3;
135
break;
136
case A_PRESCALE:
137
+ resync_counter(s);
138
s->prescale = value;
139
break;
140
case A_MISC:
141
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
142
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
143
s->clk100hz_tick_offset = tickoff_from_counter(now, value, 100);
144
break;
145
+ case A_COUNTER:
146
+ resync_counter(s);
147
+ s->counter = value;
148
+ break;
149
+ case A_PSCNTR:
150
+ resync_counter(s);
151
+ s->pscntr = value;
152
+ break;
153
default:
154
qemu_log_mask(LOG_GUEST_ERROR,
155
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
156
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
157
s->misc = 0;
158
s->clk1hz_tick_offset = tickoff_from_counter(now, 0, 1);
159
s->clk100hz_tick_offset = tickoff_from_counter(now, 0, 100);
160
+ s->counter = 0;
161
+ s->pscntr = 0;
162
+ s->pscntr_sync_ticks = now;
163
}
164
165
static void mps2_fpgaio_init(Object *obj)
166
@@ -XXX,XX +XXX,XX @@ static bool mps2_fpgaio_counters_needed(void *opaque)
167
168
static const VMStateDescription mps2_fpgaio_counters_vmstate = {
169
.name = "mps2-fpgaio/counters",
170
- .version_id = 1,
171
- .minimum_version_id = 1,
172
+ .version_id = 2,
173
+ .minimum_version_id = 2,
174
.needed = mps2_fpgaio_counters_needed,
175
.fields = (VMStateField[]) {
176
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
177
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
178
+ VMSTATE_UINT32(counter, MPS2FPGAIO),
179
+ VMSTATE_UINT32(pscntr, MPS2FPGAIO),
180
+ VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
181
VMSTATE_END_OF_LIST()
182
}
183
};
81
--
184
--
82
2.7.4
185
2.18.0
83
186
84
187
diff view generated by jsdifflib
New patch
1
The Arm Cortex-M System Design Kit includes a "dual-input timer module"
2
which combines two programmable down-counters. Implement a model
3
of this device.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-4-peter.maydell@linaro.org
8
---
9
hw/timer/Makefile.objs | 1 +
10
include/hw/timer/cmsdk-apb-dualtimer.h | 72 ++++
11
hw/timer/cmsdk-apb-dualtimer.c | 515 +++++++++++++++++++++++++
12
MAINTAINERS | 2 +
13
default-configs/arm-softmmu.mak | 1 +
14
hw/timer/trace-events | 5 +
15
6 files changed, 596 insertions(+)
16
create mode 100644 include/hw/timer/cmsdk-apb-dualtimer.h
17
create mode 100644 hw/timer/cmsdk-apb-dualtimer.c
18
19
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/timer/Makefile.objs
22
+++ b/hw/timer/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
24
25
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
26
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
27
+common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
28
common-obj-$(CONFIG_MSF2) += mss-timer.o
29
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
30
new file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- /dev/null
33
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * ARM CMSDK APB dual-timer emulation
37
+ *
38
+ * Copyright (c) 2018 Linaro Limited
39
+ * Written by Peter Maydell
40
+ *
41
+ * This program is free software; you can redistribute it and/or modify
42
+ * it under the terms of the GNU General Public License version 2 or
43
+ * (at your option) any later version.
44
+ */
45
+
46
+/*
47
+ * This is a model of the "APB dual-input timer" which is part of the Cortex-M
48
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
49
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
50
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
51
+ *
52
+ * QEMU interface:
53
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
54
+ * + sysbus MMIO region 0: the register bank
55
+ * + sysbus IRQ 0: combined timer interrupt TIMINTC
56
+ * + sysbus IRO 1: timer block 1 interrupt TIMINT1
57
+ * + sysbus IRQ 2: timer block 2 interrupt TIMINT2
58
+ */
59
+
60
+#ifndef CMSDK_APB_DUALTIMER_H
61
+#define CMSDK_APB_DUALTIMER_H
62
+
63
+#include "hw/sysbus.h"
64
+#include "hw/ptimer.h"
65
+
66
+#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
67
+#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \
68
+ TYPE_CMSDK_APB_DUALTIMER)
69
+
70
+typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer;
71
+
72
+/* One of the two identical timer modules in the dual-timer module */
73
+typedef struct CMSDKAPBDualTimerModule {
74
+ CMSDKAPBDualTimer *parent;
75
+ struct ptimer_state *timer;
76
+ qemu_irq timerint;
77
+ /*
78
+ * We must track the guest LOAD and VALUE register state by hand
79
+ * rather than leaving this state only in the ptimer limit/count,
80
+ * because if CONTROL.SIZE is 0 then only the low 16 bits of the
81
+ * counter actually counts, but the high half is still guest
82
+ * accessible.
83
+ */
84
+ uint32_t load;
85
+ uint32_t value;
86
+ uint32_t control;
87
+ uint32_t intstatus;
88
+} CMSDKAPBDualTimerModule;
89
+
90
+#define CMSDK_APB_DUALTIMER_NUM_MODULES 2
91
+
92
+struct CMSDKAPBDualTimer {
93
+ /*< private >*/
94
+ SysBusDevice parent_obj;
95
+
96
+ /*< public >*/
97
+ MemoryRegion iomem;
98
+ qemu_irq timerintc;
99
+ uint32_t pclk_frq;
100
+
101
+ CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
102
+ uint32_t timeritcr;
103
+ uint32_t timeritop;
104
+};
105
+
106
+#endif
107
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
108
new file mode 100644
109
index XXXXXXX..XXXXXXX
110
--- /dev/null
111
+++ b/hw/timer/cmsdk-apb-dualtimer.c
112
@@ -XXX,XX +XXX,XX @@
113
+/*
114
+ * ARM CMSDK APB dual-timer emulation
115
+ *
116
+ * Copyright (c) 2018 Linaro Limited
117
+ * Written by Peter Maydell
118
+ *
119
+ * This program is free software; you can redistribute it and/or modify
120
+ * it under the terms of the GNU General Public License version 2 or
121
+ * (at your option) any later version.
122
+ */
123
+
124
+/*
125
+ * This is a model of the "APB dual-input timer" which is part of the Cortex-M
126
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
127
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
128
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
129
+ */
130
+
131
+#include "qemu/osdep.h"
132
+#include "qemu/log.h"
133
+#include "trace.h"
134
+#include "qapi/error.h"
135
+#include "qemu/main-loop.h"
136
+#include "hw/sysbus.h"
137
+#include "hw/registerfields.h"
138
+#include "hw/timer/cmsdk-apb-dualtimer.h"
139
+
140
+REG32(TIMER1LOAD, 0x0)
141
+REG32(TIMER1VALUE, 0x4)
142
+REG32(TIMER1CONTROL, 0x8)
143
+ FIELD(CONTROL, ONESHOT, 0, 1)
144
+ FIELD(CONTROL, SIZE, 1, 1)
145
+ FIELD(CONTROL, PRESCALE, 2, 2)
146
+ FIELD(CONTROL, INTEN, 5, 1)
147
+ FIELD(CONTROL, MODE, 6, 1)
148
+ FIELD(CONTROL, ENABLE, 7, 1)
149
+#define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
150
+ R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
151
+ R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
152
+REG32(TIMER1INTCLR, 0xc)
153
+REG32(TIMER1RIS, 0x10)
154
+REG32(TIMER1MIS, 0x14)
155
+REG32(TIMER1BGLOAD, 0x18)
156
+REG32(TIMER2LOAD, 0x20)
157
+REG32(TIMER2VALUE, 0x24)
158
+REG32(TIMER2CONTROL, 0x28)
159
+REG32(TIMER2INTCLR, 0x2c)
160
+REG32(TIMER2RIS, 0x30)
161
+REG32(TIMER2MIS, 0x34)
162
+REG32(TIMER2BGLOAD, 0x38)
163
+REG32(TIMERITCR, 0xf00)
164
+ FIELD(TIMERITCR, ENABLE, 0, 1)
165
+#define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
166
+REG32(TIMERITOP, 0xf04)
167
+ FIELD(TIMERITOP, TIMINT1, 0, 1)
168
+ FIELD(TIMERITOP, TIMINT2, 1, 1)
169
+#define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
170
+ R_TIMERITOP_TIMINT2_MASK)
171
+REG32(PID4, 0xfd0)
172
+REG32(PID5, 0xfd4)
173
+REG32(PID6, 0xfd8)
174
+REG32(PID7, 0xfdc)
175
+REG32(PID0, 0xfe0)
176
+REG32(PID1, 0xfe4)
177
+REG32(PID2, 0xfe8)
178
+REG32(PID3, 0xfec)
179
+REG32(CID0, 0xff0)
180
+REG32(CID1, 0xff4)
181
+REG32(CID2, 0xff8)
182
+REG32(CID3, 0xffc)
183
+
184
+/* PID/CID values */
185
+static const int timer_id[] = {
186
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
187
+ 0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
188
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
189
+};
190
+
191
+static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
192
+{
193
+ /* Return masked interrupt status for the timer module */
194
+ return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
195
+}
196
+
197
+static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
198
+{
199
+ bool timint1, timint2, timintc;
200
+
201
+ if (s->timeritcr) {
202
+ /* Integration test mode: outputs driven directly from TIMERITOP bits */
203
+ timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK;
204
+ timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK;
205
+ } else {
206
+ timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
207
+ timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
208
+ }
209
+
210
+ timintc = timint1 || timint2;
211
+
212
+ qemu_set_irq(s->timermod[0].timerint, timint1);
213
+ qemu_set_irq(s->timermod[1].timerint, timint2);
214
+ qemu_set_irq(s->timerintc, timintc);
215
+}
216
+
217
+static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
218
+ uint32_t newctrl)
219
+{
220
+ /* Handle a write to the CONTROL register */
221
+ uint32_t changed;
222
+
223
+ newctrl &= R_CONTROL_VALID_MASK;
224
+
225
+ changed = m->control ^ newctrl;
226
+
227
+ if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
228
+ /* ENABLE cleared, stop timer before any further changes */
229
+ ptimer_stop(m->timer);
230
+ }
231
+
232
+ if (changed & R_CONTROL_PRESCALE_MASK) {
233
+ int divisor;
234
+
235
+ switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
236
+ case 0:
237
+ divisor = 1;
238
+ break;
239
+ case 1:
240
+ divisor = 16;
241
+ break;
242
+ case 2:
243
+ divisor = 256;
244
+ break;
245
+ case 3:
246
+ /* UNDEFINED; complain, and arbitrarily treat like 2 */
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
249
+ " is undefined behaviour\n");
250
+ divisor = 256;
251
+ break;
252
+ default:
253
+ g_assert_not_reached();
254
+ }
255
+ ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
256
+ }
257
+
258
+ if (changed & R_CONTROL_MODE_MASK) {
259
+ uint32_t load;
260
+ if (newctrl & R_CONTROL_MODE_MASK) {
261
+ /* Periodic: the limit is the LOAD register value */
262
+ load = m->load;
263
+ } else {
264
+ /* Free-running: counter wraps around */
265
+ load = ptimer_get_limit(m->timer);
266
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
267
+ load = deposit32(m->load, 0, 16, load);
268
+ }
269
+ m->load = load;
270
+ load = 0xffffffff;
271
+ }
272
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
273
+ load &= 0xffff;
274
+ }
275
+ ptimer_set_limit(m->timer, load, 0);
276
+ }
277
+
278
+ if (changed & R_CONTROL_SIZE_MASK) {
279
+ /* Timer switched between 16 and 32 bit count */
280
+ uint32_t value, load;
281
+
282
+ value = ptimer_get_count(m->timer);
283
+ load = ptimer_get_limit(m->timer);
284
+ if (newctrl & R_CONTROL_SIZE_MASK) {
285
+ /* 16 -> 32, top half of VALUE is in struct field */
286
+ value = deposit32(m->value, 0, 16, value);
287
+ } else {
288
+ /* 32 -> 16: save top half to struct field and truncate */
289
+ m->value = value;
290
+ value &= 0xffff;
291
+ }
292
+
293
+ if (newctrl & R_CONTROL_MODE_MASK) {
294
+ /* Periodic, timer limit has LOAD value */
295
+ if (newctrl & R_CONTROL_SIZE_MASK) {
296
+ load = deposit32(m->load, 0, 16, load);
297
+ } else {
298
+ m->load = load;
299
+ load &= 0xffff;
300
+ }
301
+ } else {
302
+ /* Free-running, timer limit is set to give wraparound */
303
+ if (newctrl & R_CONTROL_SIZE_MASK) {
304
+ load = 0xffffffff;
305
+ } else {
306
+ load = 0xffff;
307
+ }
308
+ }
309
+ ptimer_set_count(m->timer, value);
310
+ ptimer_set_limit(m->timer, load, 0);
311
+ }
312
+
313
+ if (newctrl & R_CONTROL_ENABLE_MASK) {
314
+ /*
315
+ * ENABLE is set; start the timer after all other changes.
316
+ * We start it even if the ENABLE bit didn't actually change,
317
+ * in case the timer was an expired one-shot timer that has
318
+ * now been changed into a free-running or periodic timer.
319
+ */
320
+ ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
321
+ }
322
+
323
+ m->control = newctrl;
324
+}
325
+
326
+static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
327
+ unsigned size)
328
+{
329
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
330
+ uint64_t r;
331
+
332
+ if (offset >= A_TIMERITCR) {
333
+ switch (offset) {
334
+ case A_TIMERITCR:
335
+ r = s->timeritcr;
336
+ break;
337
+ case A_PID4 ... A_CID3:
338
+ r = timer_id[(offset - A_PID4) / 4];
339
+ break;
340
+ default:
341
+ bad_offset:
342
+ qemu_log_mask(LOG_GUEST_ERROR,
343
+ "CMSDK APB dual-timer read: bad offset %x\n",
344
+ (int) offset);
345
+ r = 0;
346
+ break;
347
+ }
348
+ } else {
349
+ int timer = offset >> 5;
350
+ CMSDKAPBDualTimerModule *m;
351
+
352
+ if (timer >= ARRAY_SIZE(s->timermod)) {
353
+ goto bad_offset;
354
+ }
355
+
356
+ m = &s->timermod[timer];
357
+
358
+ switch (offset & 0x1F) {
359
+ case A_TIMER1LOAD:
360
+ case A_TIMER1BGLOAD:
361
+ if (m->control & R_CONTROL_MODE_MASK) {
362
+ /*
363
+ * Periodic: the ptimer limit is the LOAD register value, (or
364
+ * just the low 16 bits of it if the timer is in 16-bit mode)
365
+ */
366
+ r = ptimer_get_limit(m->timer);
367
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
368
+ r = deposit32(m->load, 0, 16, r);
369
+ }
370
+ } else {
371
+ /* Free-running: LOAD register value is just in m->load */
372
+ r = m->load;
373
+ }
374
+ break;
375
+ case A_TIMER1VALUE:
376
+ r = ptimer_get_count(m->timer);
377
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
378
+ r = deposit32(m->value, 0, 16, r);
379
+ }
380
+ break;
381
+ case A_TIMER1CONTROL:
382
+ r = m->control;
383
+ break;
384
+ case A_TIMER1RIS:
385
+ r = m->intstatus;
386
+ break;
387
+ case A_TIMER1MIS:
388
+ r = cmsdk_dualtimermod_intstatus(m);
389
+ break;
390
+ default:
391
+ goto bad_offset;
392
+ }
393
+ }
394
+
395
+ trace_cmsdk_apb_dualtimer_read(offset, r, size);
396
+ return r;
397
+}
398
+
399
+static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
400
+ uint64_t value, unsigned size)
401
+{
402
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
403
+
404
+ trace_cmsdk_apb_dualtimer_write(offset, value, size);
405
+
406
+ if (offset >= A_TIMERITCR) {
407
+ switch (offset) {
408
+ case A_TIMERITCR:
409
+ s->timeritcr = value & R_TIMERITCR_VALID_MASK;
410
+ cmsdk_apb_dualtimer_update(s);
411
+ case A_TIMERITOP:
412
+ s->timeritop = value & R_TIMERITOP_VALID_MASK;
413
+ cmsdk_apb_dualtimer_update(s);
414
+ default:
415
+ bad_offset:
416
+ qemu_log_mask(LOG_GUEST_ERROR,
417
+ "CMSDK APB dual-timer write: bad offset %x\n",
418
+ (int) offset);
419
+ break;
420
+ }
421
+ } else {
422
+ int timer = offset >> 5;
423
+ CMSDKAPBDualTimerModule *m;
424
+
425
+ if (timer >= ARRAY_SIZE(s->timermod)) {
426
+ goto bad_offset;
427
+ }
428
+
429
+ m = &s->timermod[timer];
430
+
431
+ switch (offset & 0x1F) {
432
+ case A_TIMER1LOAD:
433
+ /* Set the limit, and immediately reload the count from it */
434
+ m->load = value;
435
+ m->value = value;
436
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
437
+ value &= 0xffff;
438
+ }
439
+ if (!(m->control & R_CONTROL_MODE_MASK)) {
440
+ /*
441
+ * In free-running mode this won't set the limit but will
442
+ * still change the current count value.
443
+ */
444
+ ptimer_set_count(m->timer, value);
445
+ } else {
446
+ if (!value) {
447
+ ptimer_stop(m->timer);
448
+ }
449
+ ptimer_set_limit(m->timer, value, 1);
450
+ if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
451
+ /* Force possibly-expired oneshot timer to restart */
452
+ ptimer_run(m->timer, 1);
453
+ }
454
+ }
455
+ break;
456
+ case A_TIMER1BGLOAD:
457
+ /* Set the limit, but not the current count */
458
+ m->load = value;
459
+ if (!(m->control & R_CONTROL_MODE_MASK)) {
460
+ /* In free-running mode there is no limit */
461
+ break;
462
+ }
463
+ if (!(m->control & R_CONTROL_SIZE_MASK)) {
464
+ value &= 0xffff;
465
+ }
466
+ ptimer_set_limit(m->timer, value, 0);
467
+ break;
468
+ case A_TIMER1CONTROL:
469
+ cmsdk_dualtimermod_write_control(m, value);
470
+ cmsdk_apb_dualtimer_update(s);
471
+ break;
472
+ case A_TIMER1INTCLR:
473
+ m->intstatus = 0;
474
+ cmsdk_apb_dualtimer_update(s);
475
+ break;
476
+ default:
477
+ goto bad_offset;
478
+ }
479
+ }
480
+}
481
+
482
+static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
483
+ .read = cmsdk_apb_dualtimer_read,
484
+ .write = cmsdk_apb_dualtimer_write,
485
+ .endianness = DEVICE_LITTLE_ENDIAN,
486
+ /* byte/halfword accesses are just zero-padded on reads and writes */
487
+ .impl.min_access_size = 4,
488
+ .impl.max_access_size = 4,
489
+ .valid.min_access_size = 1,
490
+ .valid.max_access_size = 4,
491
+};
492
+
493
+static void cmsdk_dualtimermod_tick(void *opaque)
494
+{
495
+ CMSDKAPBDualTimerModule *m = opaque;
496
+
497
+ m->intstatus = 1;
498
+ cmsdk_apb_dualtimer_update(m->parent);
499
+}
500
+
501
+static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
502
+{
503
+ m->control = R_CONTROL_INTEN_MASK;
504
+ m->intstatus = 0;
505
+ m->load = 0;
506
+ m->value = 0xffffffff;
507
+ ptimer_stop(m->timer);
508
+ /*
509
+ * We start in free-running mode, with VALUE at 0xffffffff, and
510
+ * in 16-bit counter mode. This means that the ptimer count and
511
+ * limit must both be set to 0xffff, so we wrap at 16 bits.
512
+ */
513
+ ptimer_set_limit(m->timer, 0xffff, 1);
514
+ ptimer_set_freq(m->timer, m->parent->pclk_frq);
515
+}
516
+
517
+static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
518
+{
519
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
520
+ int i;
521
+
522
+ trace_cmsdk_apb_dualtimer_reset();
523
+
524
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
525
+ cmsdk_dualtimermod_reset(&s->timermod[i]);
526
+ }
527
+ s->timeritcr = 0;
528
+ s->timeritop = 0;
529
+}
530
+
531
+static void cmsdk_apb_dualtimer_init(Object *obj)
532
+{
533
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
534
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
535
+ int i;
536
+
537
+ memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
538
+ s, "cmsdk-apb-dualtimer", 0x1000);
539
+ sysbus_init_mmio(sbd, &s->iomem);
540
+ sysbus_init_irq(sbd, &s->timerintc);
541
+
542
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
543
+ sysbus_init_irq(sbd, &s->timermod[i].timerint);
544
+ }
545
+}
546
+
547
+static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
548
+{
549
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
550
+ int i;
551
+
552
+ if (s->pclk_frq == 0) {
553
+ error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
554
+ return;
555
+ }
556
+
557
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
558
+ CMSDKAPBDualTimerModule *m = &s->timermod[i];
559
+ QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
560
+
561
+ m->parent = s;
562
+ m->timer = ptimer_init(bh,
563
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
564
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
565
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
566
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
567
+ }
568
+}
569
+
570
+static const VMStateDescription cmsdk_dualtimermod_vmstate = {
571
+ .name = "cmsdk-apb-dualtimer-module",
572
+ .version_id = 1,
573
+ .minimum_version_id = 1,
574
+ .fields = (VMStateField[]) {
575
+ VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
576
+ VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
577
+ VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
578
+ VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
579
+ VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
580
+ VMSTATE_END_OF_LIST()
581
+ }
582
+};
583
+
584
+static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
585
+ .name = "cmsdk-apb-dualtimer",
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]) {
589
+ VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
590
+ CMSDK_APB_DUALTIMER_NUM_MODULES,
591
+ 1, cmsdk_dualtimermod_vmstate,
592
+ CMSDKAPBDualTimerModule),
593
+ VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
594
+ VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
595
+ VMSTATE_END_OF_LIST()
596
+ }
597
+};
598
+
599
+static Property cmsdk_apb_dualtimer_properties[] = {
600
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
601
+ DEFINE_PROP_END_OF_LIST(),
602
+};
603
+
604
+static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
605
+{
606
+ DeviceClass *dc = DEVICE_CLASS(klass);
607
+
608
+ dc->realize = cmsdk_apb_dualtimer_realize;
609
+ dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
610
+ dc->reset = cmsdk_apb_dualtimer_reset;
611
+ dc->props = cmsdk_apb_dualtimer_properties;
612
+}
613
+
614
+static const TypeInfo cmsdk_apb_dualtimer_info = {
615
+ .name = TYPE_CMSDK_APB_DUALTIMER,
616
+ .parent = TYPE_SYS_BUS_DEVICE,
617
+ .instance_size = sizeof(CMSDKAPBDualTimer),
618
+ .instance_init = cmsdk_apb_dualtimer_init,
619
+ .class_init = cmsdk_apb_dualtimer_class_init,
620
+};
621
+
622
+static void cmsdk_apb_dualtimer_register_types(void)
623
+{
624
+ type_register_static(&cmsdk_apb_dualtimer_info);
625
+}
626
+
627
+type_init(cmsdk_apb_dualtimer_register_types);
628
diff --git a/MAINTAINERS b/MAINTAINERS
629
index XXXXXXX..XXXXXXX 100644
630
--- a/MAINTAINERS
631
+++ b/MAINTAINERS
632
@@ -XXX,XX +XXX,XX @@ F: hw/timer/pl031.c
633
F: include/hw/arm/primecell.h
634
F: hw/timer/cmsdk-apb-timer.c
635
F: include/hw/timer/cmsdk-apb-timer.h
636
+F: hw/timer/cmsdk-apb-dualtimer.c
637
+F: include/hw/timer/cmsdk-apb-dualtimer.h
638
F: hw/char/cmsdk-apb-uart.c
639
F: include/hw/char/cmsdk-apb-uart.h
640
F: hw/watchdog/cmsdk-apb-watchdog.c
641
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
642
index XXXXXXX..XXXXXXX 100644
643
--- a/default-configs/arm-softmmu.mak
644
+++ b/default-configs/arm-softmmu.mak
645
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_SPI=y
646
CONFIG_STM32F205_SOC=y
647
648
CONFIG_CMSDK_APB_TIMER=y
649
+CONFIG_CMSDK_APB_DUALTIMER=y
650
CONFIG_CMSDK_APB_UART=y
651
CONFIG_CMSDK_APB_WATCHDOG=y
652
653
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
654
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/timer/trace-events
656
+++ b/hw/timer/trace-events
657
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB t
658
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
659
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
660
661
+# hw/timer/cmsdk_apb_dualtimer.c
662
+cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
663
+cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
664
+cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
665
+
666
# hw/timer/xlnx-zynqmp-rtc.c
667
xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
668
--
669
2.18.0
670
671
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Now we have a model of the CMSDK dual timer, we can wire it
2
up in the IoTKit.
2
3
3
Binding to a particular netdev doesn't seem to belong to this layer
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
and should probably be done as a part of board or SoC specific code.
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-5-peter.maydell@linaro.org
8
---
9
include/hw/arm/iotkit.h | 3 ++-
10
hw/arm/iotkit.c | 8 +++++---
11
2 files changed, 7 insertions(+), 4 deletions(-)
5
12
6
Convert all of the users of this IP block to use
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
7
qdev_set_nic_properties() instead.
8
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Jason Wang <jasowang@redhat.com>
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Cc: qemu-devel@nongnu.org
13
Cc: qemu-arm@nongnu.org
14
Cc: yurovsky@gmail.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/arm/fsl-imx6.c | 1 +
20
hw/net/imx_fec.c | 2 --
21
2 files changed, 1 insertion(+), 2 deletions(-)
22
23
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/fsl-imx6.c
15
--- a/include/hw/arm/iotkit.h
26
+++ b/hw/arm/fsl-imx6.c
16
+++ b/include/hw/arm/iotkit.h
27
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@
28
spi_table[i].irq));
18
#include "hw/misc/tz-ppc.h"
19
#include "hw/misc/tz-mpc.h"
20
#include "hw/timer/cmsdk-apb-timer.h"
21
+#include "hw/timer/cmsdk-apb-dualtimer.h"
22
#include "hw/misc/unimp.h"
23
#include "hw/or-irq.h"
24
#include "hw/core/split-irq.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
26
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
27
qemu_or_irq mpc_irq_orgate;
28
29
- UnimplementedDeviceState dualtimer;
30
+ CMSDKAPBDualTimer dualtimer;
31
UnimplementedDeviceState s32ktimer;
32
33
MemoryRegion container;
34
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/iotkit.c
37
+++ b/hw/arm/iotkit.c
38
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
39
sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
40
TYPE_CMSDK_APB_TIMER);
41
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
42
- TYPE_UNIMPLEMENTED_DEVICE);
43
+ TYPE_CMSDK_APB_DUALTIMER);
44
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
45
sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
46
&error_abort, NULL);
47
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
48
return;
29
}
49
}
30
50
31
+ qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
51
- qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
32
object_property_set_bool(OBJECT(&s->eth), true, "realized", &err);
52
- qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
53
+
54
+ qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
55
object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
33
if (err) {
56
if (err) {
34
error_propagate(errp, err);
57
error_propagate(errp, err);
35
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
58
return;
36
index XXXXXXX..XXXXXXX 100644
59
}
37
--- a/hw/net/imx_fec.c
60
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
38
+++ b/hw/net/imx_fec.c
61
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
39
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
62
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
40
63
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
41
qemu_macaddr_default_if_unset(&s->conf.macaddr);
64
if (err) {
42
43
- s->conf.peers.ncs[0] = nd_table[0].netdev;
44
-
45
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
46
object_get_typename(OBJECT(dev)),
47
DEVICE(dev)->id, s);
48
--
65
--
49
2.7.4
66
2.18.0
50
67
51
68
diff view generated by jsdifflib
New patch
1
The MPS2 FPGA images for the Cortex-M3 (mps2-an385 and mps2-511)
2
both include a CMSDK dual-timer module. Wire this up.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-6-peter.maydell@linaro.org
8
---
9
hw/arm/mps2.c | 11 +++++++++++
10
1 file changed, 11 insertions(+)
11
12
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2.c
15
+++ b/hw/arm/mps2.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "hw/misc/unimp.h"
18
#include "hw/char/cmsdk-apb-uart.h"
19
#include "hw/timer/cmsdk-apb-timer.h"
20
+#include "hw/timer/cmsdk-apb-dualtimer.h"
21
#include "hw/misc/mps2-scc.h"
22
#include "hw/devices.h"
23
#include "net/net.h"
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
MemoryRegion blockram_m3;
26
MemoryRegion sram;
27
MPS2SCC scc;
28
+ CMSDKAPBDualTimer dualtimer;
29
} MPS2MachineState;
30
31
#define TYPE_MPS2_MACHINE "mps2"
32
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
33
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
34
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
35
36
+ sysbus_init_child_obj(OBJECT(mms), "dualtimer", &mms->dualtimer,
37
+ sizeof(mms->dualtimer), TYPE_CMSDK_APB_DUALTIMER);
38
+ qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
39
+ object_property_set_bool(OBJECT(&mms->dualtimer), true, "realized",
40
+ &error_fatal);
41
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
42
+ qdev_get_gpio_in(armv7m, 10));
43
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
44
+
45
object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC);
46
sccdev = DEVICE(&mms->scc);
47
qdev_set_parent_bus(sccdev, sysbus_get_default());
48
--
49
2.18.0
50
51
diff view generated by jsdifflib
New patch
1
The IoTKit includes three different instances of the
2
CMSDK APB watchdog; create and wire them up.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-7-peter.maydell@linaro.org
8
---
9
include/hw/arm/iotkit.h | 6 +++++
10
hw/arm/iotkit.c | 58 ++++++++++++++++++++++++++++++++++++++---
11
2 files changed, 61 insertions(+), 3 deletions(-)
12
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/iotkit.h
16
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/misc/tz-mpc.h"
19
#include "hw/timer/cmsdk-apb-timer.h"
20
#include "hw/timer/cmsdk-apb-dualtimer.h"
21
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
22
#include "hw/misc/unimp.h"
23
#include "hw/or-irq.h"
24
#include "hw/core/split-irq.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
26
SplitIRQ ppc_irq_splitter[NUM_PPCS];
27
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
28
qemu_or_irq mpc_irq_orgate;
29
+ qemu_or_irq nmi_orgate;
30
31
CMSDKAPBDualTimer dualtimer;
32
UnimplementedDeviceState s32ktimer;
33
34
+ CMSDKAPBWatchdog s32kwatchdog;
35
+ CMSDKAPBWatchdog nswatchdog;
36
+ CMSDKAPBWatchdog swatchdog;
37
+
38
MemoryRegion container;
39
MemoryRegion alias1;
40
MemoryRegion alias2;
41
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/iotkit.c
44
+++ b/hw/arm/iotkit.c
45
@@ -XXX,XX +XXX,XX @@
46
#include "hw/misc/unimp.h"
47
#include "hw/arm/arm.h"
48
49
+/* Clock frequency in HZ of the 32KHz "slow clock" */
50
+#define S32KCLK (32 * 1000)
51
+
52
/* Create an alias region of @size bytes starting at @base
53
* which mirrors the memory starting at @orig.
54
*/
55
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
56
TYPE_CMSDK_APB_TIMER);
57
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
58
TYPE_CMSDK_APB_DUALTIMER);
59
+ sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
60
+ sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG);
61
+ sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog,
62
+ sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
63
+ sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
64
+ sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
65
+ object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
66
+ sizeof(s->nmi_orgate), TYPE_OR_IRQ,
67
+ &error_abort, NULL);
68
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
69
sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ,
70
&error_abort, NULL);
71
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
72
create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
73
74
create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
75
- create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
76
+
77
+ /* This OR gate wires together outputs from the secure watchdogs to NMI */
78
+ object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
79
+ if (err) {
80
+ error_propagate(errp, err);
81
+ return;
82
+ }
83
+ object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &err);
84
+ if (err) {
85
+ error_propagate(errp, err);
86
+ return;
87
+ }
88
+ qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
89
+ qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
90
+
91
+ qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
92
+ object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &err);
93
+ if (err) {
94
+ error_propagate(errp, err);
95
+ return;
96
+ }
97
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
99
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
100
101
/* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
102
103
- create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
104
- create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
105
+ qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
106
+ object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
107
+ if (err) {
108
+ error_propagate(errp, err);
109
+ return;
110
+ }
111
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
112
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
113
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
114
+
115
+ qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
116
+ object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err);
117
+ if (err) {
118
+ error_propagate(errp, err);
119
+ return;
120
+ }
121
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
122
+ qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
123
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
124
125
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
126
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
127
--
128
2.18.0
129
130
diff view generated by jsdifflib
New patch
1
The IoTKit has a CMSDK timer device that runs on the S32KCLK.
2
Create this and wire it up.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180820141116.9118-8-peter.maydell@linaro.org
8
---
9
include/hw/arm/iotkit.h | 2 +-
10
hw/arm/iotkit.c | 9 +++++----
11
2 files changed, 6 insertions(+), 5 deletions(-)
12
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/iotkit.h
16
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
18
TZMPC mpc;
19
CMSDKAPBTIMER timer0;
20
CMSDKAPBTIMER timer1;
21
+ CMSDKAPBTIMER s32ktimer;
22
qemu_or_irq ppc_irq_orgate;
23
SplitIRQ sec_resp_splitter;
24
SplitIRQ ppc_irq_splitter[NUM_PPCS];
25
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
26
qemu_or_irq nmi_orgate;
27
28
CMSDKAPBDualTimer dualtimer;
29
- UnimplementedDeviceState s32ktimer;
30
31
CMSDKAPBWatchdog s32kwatchdog;
32
CMSDKAPBWatchdog nswatchdog;
33
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/iotkit.c
36
+++ b/hw/arm/iotkit.c
37
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
38
TYPE_CMSDK_APB_TIMER);
39
sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1),
40
TYPE_CMSDK_APB_TIMER);
41
+ sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
42
+ TYPE_CMSDK_APB_TIMER);
43
sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
44
TYPE_CMSDK_APB_DUALTIMER);
45
sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog,
46
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
47
TYPE_SPLIT_IRQ, &error_abort, NULL);
48
g_free(name);
49
}
50
- sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
51
- TYPE_UNIMPLEMENTED_DEVICE);
52
}
53
54
static void iotkit_exp_irq(void *opaque, int n, int level)
55
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
56
/* Devices behind APB PPC1:
57
* 0x4002f000: S32K timer
58
*/
59
- qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
60
- qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
61
+ qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
62
object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
63
if (err) {
64
error_propagate(errp, err);
65
return;
66
}
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
68
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
69
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
70
object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
71
if (err) {
72
--
73
2.18.0
74
75
diff view generated by jsdifflib
New patch
1
The Arm IoTKit includes a system control element which
2
provides a block of read-only ID registers and a block
3
of read-write control registers. Implement a minimal
4
version of this.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180820141116.9118-9-peter.maydell@linaro.org
9
---
10
hw/misc/Makefile.objs | 1 +
11
include/hw/misc/iotkit-sysctl.h | 49 ++++++
12
hw/misc/iotkit-sysctl.c | 261 ++++++++++++++++++++++++++++++++
13
MAINTAINERS | 2 +
14
default-configs/arm-softmmu.mak | 1 +
15
hw/misc/trace-events | 7 +
16
6 files changed, 321 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-sysctl.h
18
create mode 100644 hw/misc/iotkit-sysctl.c
19
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
23
+++ b/hw/misc/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
25
obj-$(CONFIG_TZ_MPC) += tz-mpc.o
26
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
27
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
28
+obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
29
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
32
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/iotkit-sysctl.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM IoTKit system control element
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
49
+/*
50
+ * This is a model of the "system control element" which is part of the
51
+ * Arm IoTKit and documented in
52
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
53
+ * Specifically, it implements the "system information block" and
54
+ * "system control register" blocks.
55
+ *
56
+ * QEMU interface:
57
+ * + sysbus MMIO region 0: the system information register bank
58
+ * + sysbus MMIO region 1: the system control register bank
59
+ */
60
+
61
+#ifndef HW_MISC_IOTKIT_SYSCTL_H
62
+#define HW_MISC_IOTKIT_SYSCTL_H
63
+
64
+#include "hw/sysbus.h"
65
+
66
+#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
67
+#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \
68
+ TYPE_IOTKIT_SYSCTL)
69
+
70
+typedef struct IoTKitSysCtl {
71
+ /*< private >*/
72
+ SysBusDevice parent_obj;
73
+
74
+ /*< public >*/
75
+ MemoryRegion iomem;
76
+
77
+ uint32_t secure_debug;
78
+ uint32_t reset_syndrome;
79
+ uint32_t reset_mask;
80
+ uint32_t gretreg;
81
+ uint32_t initsvrtor0;
82
+ uint32_t cpuwait;
83
+ uint32_t wicctrl;
84
+} IoTKitSysCtl;
85
+
86
+#endif
87
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
88
new file mode 100644
89
index XXXXXXX..XXXXXXX
90
--- /dev/null
91
+++ b/hw/misc/iotkit-sysctl.c
92
@@ -XXX,XX +XXX,XX @@
93
+/*
94
+ * ARM IoTKit system control element
95
+ *
96
+ * Copyright (c) 2018 Linaro Limited
97
+ * Written by Peter Maydell
98
+ *
99
+ * This program is free software; you can redistribute it and/or modify
100
+ * it under the terms of the GNU General Public License version 2 or
101
+ * (at your option) any later version.
102
+ */
103
+
104
+/*
105
+ * This is a model of the "system control element" which is part of the
106
+ * Arm IoTKit and documented in
107
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
108
+ * Specifically, it implements the "system control register" blocks.
109
+ */
110
+
111
+#include "qemu/osdep.h"
112
+#include "qemu/log.h"
113
+#include "trace.h"
114
+#include "qapi/error.h"
115
+#include "sysemu/sysemu.h"
116
+#include "hw/sysbus.h"
117
+#include "hw/registerfields.h"
118
+#include "hw/misc/iotkit-sysctl.h"
119
+
120
+REG32(SECDBGSTAT, 0x0)
121
+REG32(SECDBGSET, 0x4)
122
+REG32(SECDBGCLR, 0x8)
123
+REG32(RESET_SYNDROME, 0x100)
124
+REG32(RESET_MASK, 0x104)
125
+REG32(SWRESET, 0x108)
126
+ FIELD(SWRESET, SWRESETREQ, 9, 1)
127
+REG32(GRETREG, 0x10c)
128
+REG32(INITSVRTOR0, 0x110)
129
+REG32(CPUWAIT, 0x118)
130
+REG32(BUSWAIT, 0x11c)
131
+REG32(WICCTRL, 0x120)
132
+REG32(PID4, 0xfd0)
133
+REG32(PID5, 0xfd4)
134
+REG32(PID6, 0xfd8)
135
+REG32(PID7, 0xfdc)
136
+REG32(PID0, 0xfe0)
137
+REG32(PID1, 0xfe4)
138
+REG32(PID2, 0xfe8)
139
+REG32(PID3, 0xfec)
140
+REG32(CID0, 0xff0)
141
+REG32(CID1, 0xff4)
142
+REG32(CID2, 0xff8)
143
+REG32(CID3, 0xffc)
144
+
145
+/* PID/CID values */
146
+static const int sysctl_id[] = {
147
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
148
+ 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
149
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
150
+};
151
+
152
+static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
153
+ unsigned size)
154
+{
155
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
156
+ uint64_t r;
157
+
158
+ switch (offset) {
159
+ case A_SECDBGSTAT:
160
+ r = s->secure_debug;
161
+ break;
162
+ case A_RESET_SYNDROME:
163
+ r = s->reset_syndrome;
164
+ break;
165
+ case A_RESET_MASK:
166
+ r = s->reset_mask;
167
+ break;
168
+ case A_GRETREG:
169
+ r = s->gretreg;
170
+ break;
171
+ case A_INITSVRTOR0:
172
+ r = s->initsvrtor0;
173
+ break;
174
+ case A_CPUWAIT:
175
+ r = s->cpuwait;
176
+ break;
177
+ case A_BUSWAIT:
178
+ /* In IoTKit BUSWAIT is reserved, R/O, zero */
179
+ r = 0;
180
+ break;
181
+ case A_WICCTRL:
182
+ r = s->wicctrl;
183
+ break;
184
+ case A_PID4 ... A_CID3:
185
+ r = sysctl_id[(offset - A_PID4) / 4];
186
+ break;
187
+ case A_SECDBGSET:
188
+ case A_SECDBGCLR:
189
+ case A_SWRESET:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "IoTKit SysCtl read: read of WO offset %x\n",
192
+ (int)offset);
193
+ r = 0;
194
+ break;
195
+ default:
196
+ qemu_log_mask(LOG_GUEST_ERROR,
197
+ "IoTKit SysCtl read: bad offset %x\n", (int)offset);
198
+ r = 0;
199
+ break;
200
+ }
201
+ trace_iotkit_sysctl_read(offset, r, size);
202
+ return r;
203
+}
204
+
205
+static void iotkit_sysctl_write(void *opaque, hwaddr offset,
206
+ uint64_t value, unsigned size)
207
+{
208
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
209
+
210
+ trace_iotkit_sysctl_write(offset, value, size);
211
+
212
+ /*
213
+ * Most of the state here has to do with control of reset and
214
+ * similar kinds of power up -- for instance the guest can ask
215
+ * what the reason for the last reset was, or forbid reset for
216
+ * some causes (like the non-secure watchdog). Most of this is
217
+ * not relevant to QEMU, which doesn't really model anything other
218
+ * than a full power-on reset.
219
+ * We just model the registers as reads-as-written.
220
+ */
221
+
222
+ switch (offset) {
223
+ case A_RESET_SYNDROME:
224
+ qemu_log_mask(LOG_UNIMP,
225
+ "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
226
+ s->reset_syndrome = value;
227
+ break;
228
+ case A_RESET_MASK:
229
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
230
+ s->reset_mask = value;
231
+ break;
232
+ case A_GRETREG:
233
+ /*
234
+ * General retention register, which is only reset by a power-on
235
+ * reset. Technically this implementation is complete, since
236
+ * QEMU only supports power-on resets...
237
+ */
238
+ s->gretreg = value;
239
+ break;
240
+ case A_INITSVRTOR0:
241
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\n");
242
+ s->initsvrtor0 = value;
243
+ break;
244
+ case A_CPUWAIT:
245
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
246
+ s->cpuwait = value;
247
+ break;
248
+ case A_WICCTRL:
249
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
250
+ s->wicctrl = value;
251
+ break;
252
+ case A_SECDBGSET:
253
+ /* write-1-to-set */
254
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
255
+ s->secure_debug |= value;
256
+ break;
257
+ case A_SECDBGCLR:
258
+ /* write-1-to-clear */
259
+ s->secure_debug &= ~value;
260
+ break;
261
+ case A_SWRESET:
262
+ /* One w/o bit to request a reset; all other bits reserved */
263
+ if (value & R_SWRESET_SWRESETREQ_MASK) {
264
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
265
+ }
266
+ break;
267
+ case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */
268
+ case A_SECDBGSTAT:
269
+ case A_PID4 ... A_CID3:
270
+ qemu_log_mask(LOG_GUEST_ERROR,
271
+ "IoTKit SysCtl write: write of RO offset %x\n",
272
+ (int)offset);
273
+ break;
274
+ default:
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IoTKit SysCtl write: bad offset %x\n", (int)offset);
277
+ break;
278
+ }
279
+}
280
+
281
+static const MemoryRegionOps iotkit_sysctl_ops = {
282
+ .read = iotkit_sysctl_read,
283
+ .write = iotkit_sysctl_write,
284
+ .endianness = DEVICE_LITTLE_ENDIAN,
285
+ /* byte/halfword accesses are just zero-padded on reads and writes */
286
+ .impl.min_access_size = 4,
287
+ .impl.max_access_size = 4,
288
+ .valid.min_access_size = 1,
289
+ .valid.max_access_size = 4,
290
+};
291
+
292
+static void iotkit_sysctl_reset(DeviceState *dev)
293
+{
294
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
295
+
296
+ trace_iotkit_sysctl_reset();
297
+ s->secure_debug = 0;
298
+ s->reset_syndrome = 1;
299
+ s->reset_mask = 0;
300
+ s->gretreg = 0;
301
+ s->initsvrtor0 = 0x10000000;
302
+ s->cpuwait = 0;
303
+ s->wicctrl = 0;
304
+}
305
+
306
+static void iotkit_sysctl_init(Object *obj)
307
+{
308
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
309
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
310
+
311
+ memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
312
+ s, "iotkit-sysctl", 0x1000);
313
+ sysbus_init_mmio(sbd, &s->iomem);
314
+}
315
+
316
+static const VMStateDescription iotkit_sysctl_vmstate = {
317
+ .name = "iotkit-sysctl",
318
+ .version_id = 1,
319
+ .minimum_version_id = 1,
320
+ .fields = (VMStateField[]) {
321
+ VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
322
+ VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
323
+ VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
324
+ VMSTATE_UINT32(gretreg, IoTKitSysCtl),
325
+ VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl),
326
+ VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
327
+ VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
328
+ VMSTATE_END_OF_LIST()
329
+ }
330
+};
331
+
332
+static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
333
+{
334
+ DeviceClass *dc = DEVICE_CLASS(klass);
335
+
336
+ dc->vmsd = &iotkit_sysctl_vmstate;
337
+ dc->reset = iotkit_sysctl_reset;
338
+}
339
+
340
+static const TypeInfo iotkit_sysctl_info = {
341
+ .name = TYPE_IOTKIT_SYSCTL,
342
+ .parent = TYPE_SYS_BUS_DEVICE,
343
+ .instance_size = sizeof(IoTKitSysCtl),
344
+ .instance_init = iotkit_sysctl_init,
345
+ .class_init = iotkit_sysctl_class_init,
346
+};
347
+
348
+static void iotkit_sysctl_register_types(void)
349
+{
350
+ type_register_static(&iotkit_sysctl_info);
351
+}
352
+
353
+type_init(iotkit_sysctl_register_types);
354
diff --git a/MAINTAINERS b/MAINTAINERS
355
index XXXXXXX..XXXXXXX 100644
356
--- a/MAINTAINERS
357
+++ b/MAINTAINERS
358
@@ -XXX,XX +XXX,XX @@ F: hw/misc/mps2-*.c
359
F: include/hw/misc/mps2-*.h
360
F: hw/arm/iotkit.c
361
F: include/hw/arm/iotkit.h
362
+F: hw/misc/iotkit-sysctl.c
363
+F: include/hw/misc/iotkit-sysctl.h
364
365
Musicpal
366
M: Jan Kiszka <jan.kiszka@web.de>
367
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
368
index XXXXXXX..XXXXXXX 100644
369
--- a/default-configs/arm-softmmu.mak
370
+++ b/default-configs/arm-softmmu.mak
371
@@ -XXX,XX +XXX,XX @@ CONFIG_TZ_MPC=y
372
CONFIG_TZ_PPC=y
373
CONFIG_IOTKIT=y
374
CONFIG_IOTKIT_SECCTL=y
375
+CONFIG_IOTKIT_SYSCTL=y
376
377
CONFIG_VERSATILE=y
378
CONFIG_VERSATILE_PCI=y
379
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
380
index XXXXXXX..XXXXXXX 100644
381
--- a/hw/misc/trace-events
382
+++ b/hw/misc/trace-events
383
@@ -XXX,XX +XXX,XX @@ ccm_freq(uint32_t freq) "freq = %d\n"
384
ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d\n"
385
ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32 "\n"
386
ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32 "\n"
387
+
388
+# hw/misc/iotkit-sysctl.c
389
+iotkit_sysinfo_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
390
+iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
391
+iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
392
+iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
393
+iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
394
--
395
2.18.0
396
397
diff view generated by jsdifflib
New patch
1
1
Implement the IoTKit system control element's system information
2
block; this is just a pair of read-only version/config registers,
3
plus the usual PID/CID ID registers.
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180820141116.9118-10-peter.maydell@linaro.org
9
---
10
hw/misc/Makefile.objs | 1 +
11
include/hw/misc/iotkit-sysinfo.h | 37 +++++++++
12
hw/misc/iotkit-sysinfo.c | 128 +++++++++++++++++++++++++++++++
13
MAINTAINERS | 2 +
14
default-configs/arm-softmmu.mak | 1 +
15
5 files changed, 169 insertions(+)
16
create mode 100644 include/hw/misc/iotkit-sysinfo.h
17
create mode 100644 hw/misc/iotkit-sysinfo.c
18
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
22
+++ b/hw/misc/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_TZ_MPC) += tz-mpc.o
24
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
25
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
26
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
27
+obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
28
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
31
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
32
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
+++ b/include/hw/misc/iotkit-sysinfo.h
36
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+ * ARM IoTKit system information block
39
+ *
40
+ * Copyright (c) 2018 Linaro Limited
41
+ * Written by Peter Maydell
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify
44
+ * it under the terms of the GNU General Public License version 2 or
45
+ * (at your option) any later version.
46
+ */
47
+
48
+/*
49
+ * This is a model of the "system information block" which is part of the
50
+ * Arm IoTKit and documented in
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
52
+ * QEMU interface:
53
+ * + sysbus MMIO region 0: the system information register bank
54
+ */
55
+
56
+#ifndef HW_MISC_IOTKIT_SYSINFO_H
57
+#define HW_MISC_IOTKIT_SYSINFO_H
58
+
59
+#include "hw/sysbus.h"
60
+
61
+#define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
62
+#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \
63
+ TYPE_IOTKIT_SYSINFO)
64
+
65
+typedef struct IoTKitSysInfo {
66
+ /*< private >*/
67
+ SysBusDevice parent_obj;
68
+
69
+ /*< public >*/
70
+ MemoryRegion iomem;
71
+} IoTKitSysInfo;
72
+
73
+#endif
74
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/hw/misc/iotkit-sysinfo.c
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * ARM IoTKit system information block
82
+ *
83
+ * Copyright (c) 2018 Linaro Limited
84
+ * Written by Peter Maydell
85
+ *
86
+ * This program is free software; you can redistribute it and/or modify
87
+ * it under the terms of the GNU General Public License version 2 or
88
+ * (at your option) any later version.
89
+ */
90
+
91
+/*
92
+ * This is a model of the "system information block" which is part of the
93
+ * Arm IoTKit and documented in
94
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
95
+ * It consists of 2 read-only version/config registers, plus the
96
+ * usual ID registers.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "qemu/log.h"
101
+#include "trace.h"
102
+#include "qapi/error.h"
103
+#include "sysemu/sysemu.h"
104
+#include "hw/sysbus.h"
105
+#include "hw/registerfields.h"
106
+#include "hw/misc/iotkit-sysinfo.h"
107
+
108
+REG32(SYS_VERSION, 0x0)
109
+REG32(SYS_CONFIG, 0x4)
110
+REG32(PID4, 0xfd0)
111
+REG32(PID5, 0xfd4)
112
+REG32(PID6, 0xfd8)
113
+REG32(PID7, 0xfdc)
114
+REG32(PID0, 0xfe0)
115
+REG32(PID1, 0xfe4)
116
+REG32(PID2, 0xfe8)
117
+REG32(PID3, 0xfec)
118
+REG32(CID0, 0xff0)
119
+REG32(CID1, 0xff4)
120
+REG32(CID2, 0xff8)
121
+REG32(CID3, 0xffc)
122
+
123
+/* PID/CID values */
124
+static const int sysinfo_id[] = {
125
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
126
+ 0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
127
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
128
+};
129
+
130
+static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
131
+ unsigned size)
132
+{
133
+ uint64_t r;
134
+
135
+ switch (offset) {
136
+ case A_SYS_VERSION:
137
+ r = 0x41743;
138
+ break;
139
+
140
+ case A_SYS_CONFIG:
141
+ r = 0x31;
142
+ break;
143
+ case A_PID4 ... A_CID3:
144
+ r = sysinfo_id[(offset - A_PID4) / 4];
145
+ break;
146
+ default:
147
+ qemu_log_mask(LOG_GUEST_ERROR,
148
+ "IoTKit SysInfo read: bad offset %x\n", (int)offset);
149
+ r = 0;
150
+ break;
151
+ }
152
+ trace_iotkit_sysinfo_read(offset, r, size);
153
+ return r;
154
+}
155
+
156
+static void iotkit_sysinfo_write(void *opaque, hwaddr offset,
157
+ uint64_t value, unsigned size)
158
+{
159
+ trace_iotkit_sysinfo_write(offset, value, size);
160
+
161
+ qemu_log_mask(LOG_GUEST_ERROR,
162
+ "IoTKit SysInfo: write to RO offset 0x%x\n", (int)offset);
163
+}
164
+
165
+static const MemoryRegionOps iotkit_sysinfo_ops = {
166
+ .read = iotkit_sysinfo_read,
167
+ .write = iotkit_sysinfo_write,
168
+ .endianness = DEVICE_LITTLE_ENDIAN,
169
+ /* byte/halfword accesses are just zero-padded on reads and writes */
170
+ .impl.min_access_size = 4,
171
+ .impl.max_access_size = 4,
172
+ .valid.min_access_size = 1,
173
+ .valid.max_access_size = 4,
174
+};
175
+
176
+static void iotkit_sysinfo_init(Object *obj)
177
+{
178
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
179
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(obj);
180
+
181
+ memory_region_init_io(&s->iomem, obj, &iotkit_sysinfo_ops,
182
+ s, "iotkit-sysinfo", 0x1000);
183
+ sysbus_init_mmio(sbd, &s->iomem);
184
+}
185
+
186
+static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
187
+{
188
+ /*
189
+ * This device has no guest-modifiable state and so it
190
+ * does not need a reset function or VMState.
191
+ */
192
+}
193
+
194
+static const TypeInfo iotkit_sysinfo_info = {
195
+ .name = TYPE_IOTKIT_SYSINFO,
196
+ .parent = TYPE_SYS_BUS_DEVICE,
197
+ .instance_size = sizeof(IoTKitSysInfo),
198
+ .instance_init = iotkit_sysinfo_init,
199
+ .class_init = iotkit_sysinfo_class_init,
200
+};
201
+
202
+static void iotkit_sysinfo_register_types(void)
203
+{
204
+ type_register_static(&iotkit_sysinfo_info);
205
+}
206
+
207
+type_init(iotkit_sysinfo_register_types);
208
diff --git a/MAINTAINERS b/MAINTAINERS
209
index XXXXXXX..XXXXXXX 100644
210
--- a/MAINTAINERS
211
+++ b/MAINTAINERS
212
@@ -XXX,XX +XXX,XX @@ F: hw/arm/iotkit.c
213
F: include/hw/arm/iotkit.h
214
F: hw/misc/iotkit-sysctl.c
215
F: include/hw/misc/iotkit-sysctl.h
216
+F: hw/misc/iotkit-sysinfo.c
217
+F: include/hw/misc/iotkit-sysinfo.h
218
219
Musicpal
220
M: Jan Kiszka <jan.kiszka@web.de>
221
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
222
index XXXXXXX..XXXXXXX 100644
223
--- a/default-configs/arm-softmmu.mak
224
+++ b/default-configs/arm-softmmu.mak
225
@@ -XXX,XX +XXX,XX @@ CONFIG_TZ_PPC=y
226
CONFIG_IOTKIT=y
227
CONFIG_IOTKIT_SECCTL=y
228
CONFIG_IOTKIT_SYSCTL=y
229
+CONFIG_IOTKIT_SYSINFO=y
230
231
CONFIG_VERSATILE=y
232
CONFIG_VERSATILE_PCI=y
233
--
234
2.18.0
235
236
diff view generated by jsdifflib
New patch
1
Wire up the system control element's register banks
2
(sysctl and sysinfo).
1
3
4
This is the last of the previously completely unimplemented
5
components in the IoTKit.
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180820141116.9118-11-peter.maydell@linaro.org
11
---
12
include/hw/arm/iotkit.h | 6 +++++-
13
hw/arm/iotkit.c | 26 ++++++++++++++++++--------
14
2 files changed, 23 insertions(+), 9 deletions(-)
15
16
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/iotkit.h
19
+++ b/include/hw/arm/iotkit.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/timer/cmsdk-apb-timer.h"
22
#include "hw/timer/cmsdk-apb-dualtimer.h"
23
#include "hw/watchdog/cmsdk-apb-watchdog.h"
24
-#include "hw/misc/unimp.h"
25
+#include "hw/misc/iotkit-sysctl.h"
26
+#include "hw/misc/iotkit-sysinfo.h"
27
#include "hw/or-irq.h"
28
#include "hw/core/split-irq.h"
29
30
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
31
CMSDKAPBWatchdog nswatchdog;
32
CMSDKAPBWatchdog swatchdog;
33
34
+ IoTKitSysCtl sysctl;
35
+ IoTKitSysCtl sysinfo;
36
+
37
MemoryRegion container;
38
MemoryRegion alias1;
39
MemoryRegion alias2;
40
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/iotkit.c
43
+++ b/hw/arm/iotkit.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/sysbus.h"
46
#include "hw/registerfields.h"
47
#include "hw/arm/iotkit.h"
48
-#include "hw/misc/unimp.h"
49
#include "hw/arm/arm.h"
50
51
/* Clock frequency in HZ of the 32KHz "slow clock" */
52
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
53
sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
54
sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
55
sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
56
+ sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl,
57
+ sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
58
+ sysbus_init_child_obj(obj, "iotkit-sysinfo", &s->sysinfo,
59
+ sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
60
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
61
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
62
&error_abort, NULL);
63
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
64
qdev_get_gpio_in_named(dev_apb_ppc1,
65
"cfg_sec_resp", 0));
66
67
- /* Using create_unimplemented_device() maps the stub into the
68
- * system address space rather than into our container, but the
69
- * overall effect to the guest is the same.
70
- */
71
- create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
72
-
73
- create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
74
+ object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
78
+ }
79
+ /* System information registers */
80
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
81
+ /* System control registers */
82
+ object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
83
+ if (err) {
84
+ error_propagate(errp, err);
85
+ return;
86
+ }
87
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
88
89
/* This OR gate wires together outputs from the secure watchdogs to NMI */
90
object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
91
--
92
2.18.0
93
94
diff view generated by jsdifflib
New patch
1
Implement a model of the TrustZone Master Securtiy Controller,
2
as documented in the Arm CoreLink SIE-200 System IP for
3
Embedded TRM (DDI0571G):
4
https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
1
5
6
The MSC is intended to sit in front of a device which can
7
be a bus master (eg a DMA controller) and programmably gate
8
its transactions. This allows a bus-mastering device to be
9
controlled by non-secure code but still restricted from
10
making accesses to addresses which are secure-only.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20180820141116.9118-12-peter.maydell@linaro.org
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
---
16
hw/misc/Makefile.objs | 1 +
17
include/hw/misc/tz-msc.h | 79 ++++++++
18
hw/misc/tz-msc.c | 308 ++++++++++++++++++++++++++++++++
19
MAINTAINERS | 2 +
20
default-configs/arm-softmmu.mak | 1 +
21
hw/misc/trace-events | 9 +
22
6 files changed, 400 insertions(+)
23
create mode 100644 include/hw/misc/tz-msc.h
24
create mode 100644 hw/misc/tz-msc.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
29
+++ b/hw/misc/Makefile.objs
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
31
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
32
33
obj-$(CONFIG_TZ_MPC) += tz-mpc.o
34
+obj-$(CONFIG_TZ_MSC) += tz-msc.o
35
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
36
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
37
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
38
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/misc/tz-msc.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * ARM TrustZone master security controller emulation
46
+ *
47
+ * Copyright (c) 2018 Linaro Limited
48
+ * Written by Peter Maydell
49
+ *
50
+ * This program is free software; you can redistribute it and/or modify
51
+ * it under the terms of the GNU General Public License version 2 or
52
+ * (at your option) any later version.
53
+ */
54
+
55
+/*
56
+ * This is a model of the TrustZone master security controller (MSC).
57
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
58
+ * (DDI 0571G):
59
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
60
+ *
61
+ * The MSC sits in front of a device which can be a bus master (such as
62
+ * a DMA controller) and allows secure software to configure it to either
63
+ * pass through or reject transactions made by that bus master.
64
+ * Rejected transactions may be configured to either be aborted, or to
65
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
66
+ *
67
+ * The MSC has no register interface -- it is configured purely by a
68
+ * collection of input signals from other hardware in the system. Typically
69
+ * they are either hardwired or exposed in an ad-hoc register interface by
70
+ * the SoC that uses the MSC.
71
+ *
72
+ * We don't currently implement the irq_enable GPIO input, because on
73
+ * the MPS2 FPGA images it is always tied high, which is awkward to
74
+ * implement in QEMU.
75
+ *
76
+ * QEMU interface:
77
+ * + Named GPIO input "cfg_nonsec": set to 1 if the bus master should be
78
+ * treated as nonsecure, or 0 for secure
79
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
80
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
81
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
82
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
83
+ * + Property "downstream": MemoryRegion defining where bus master transactions
84
+ * are made if they are not blocked
85
+ * + Property "idau": an object implementing IDAUInterface, which defines which
86
+ * addresses should be treated as secure and which as non-secure.
87
+ * This need not be the same IDAU as the one used by the CPU.
88
+ * + sysbus MMIO region 0: MemoryRegion defining the upstream end of the MSC;
89
+ * this should be passed to the bus master device as the region it should
90
+ * make memory transactions to
91
+ */
92
+
93
+#ifndef TZ_MSC_H
94
+#define TZ_MSC_H
95
+
96
+#include "hw/sysbus.h"
97
+#include "target/arm/idau.h"
98
+
99
+#define TYPE_TZ_MSC "tz-msc"
100
+#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC)
101
+
102
+typedef struct TZMSC {
103
+ /*< private >*/
104
+ SysBusDevice parent_obj;
105
+
106
+ /*< public >*/
107
+
108
+ /* State: these just track the values of our input signals */
109
+ bool cfg_nonsec;
110
+ bool cfg_sec_resp;
111
+ bool irq_clear;
112
+ /* State: are we asserting irq ? */
113
+ bool irq_status;
114
+
115
+ qemu_irq irq;
116
+ MemoryRegion *downstream;
117
+ AddressSpace downstream_as;
118
+ MemoryRegion upstream;
119
+ IDAUInterface *idau;
120
+} TZMSC;
121
+
122
+#endif
123
diff --git a/hw/misc/tz-msc.c b/hw/misc/tz-msc.c
124
new file mode 100644
125
index XXXXXXX..XXXXXXX
126
--- /dev/null
127
+++ b/hw/misc/tz-msc.c
128
@@ -XXX,XX +XXX,XX @@
129
+/*
130
+ * ARM TrustZone master security controller emulation
131
+ *
132
+ * Copyright (c) 2018 Linaro Limited
133
+ * Written by Peter Maydell
134
+ *
135
+ * This program is free software; you can redistribute it and/or modify
136
+ * it under the terms of the GNU General Public License version 2 or
137
+ * (at your option) any later version.
138
+ */
139
+
140
+#include "qemu/osdep.h"
141
+#include "qemu/log.h"
142
+#include "qapi/error.h"
143
+#include "trace.h"
144
+#include "hw/sysbus.h"
145
+#include "hw/registerfields.h"
146
+#include "hw/misc/tz-msc.h"
147
+
148
+static void tz_msc_update_irq(TZMSC *s)
149
+{
150
+ bool level = s->irq_status;
151
+
152
+ trace_tz_msc_update_irq(level);
153
+ qemu_set_irq(s->irq, level);
154
+}
155
+
156
+static void tz_msc_cfg_nonsec(void *opaque, int n, int level)
157
+{
158
+ TZMSC *s = TZ_MSC(opaque);
159
+
160
+ trace_tz_msc_cfg_nonsec(level);
161
+ s->cfg_nonsec = level;
162
+}
163
+
164
+static void tz_msc_cfg_sec_resp(void *opaque, int n, int level)
165
+{
166
+ TZMSC *s = TZ_MSC(opaque);
167
+
168
+ trace_tz_msc_cfg_sec_resp(level);
169
+ s->cfg_sec_resp = level;
170
+}
171
+
172
+static void tz_msc_irq_clear(void *opaque, int n, int level)
173
+{
174
+ TZMSC *s = TZ_MSC(opaque);
175
+
176
+ trace_tz_msc_irq_clear(level);
177
+
178
+ s->irq_clear = level;
179
+ if (level) {
180
+ s->irq_status = false;
181
+ tz_msc_update_irq(s);
182
+ }
183
+}
184
+
185
+/* The MSC may either block a transaction by aborting it, block a
186
+ * transaction by making it RAZ/WI, allow it through with
187
+ * MemTxAttrs indicating a secure transaction, or allow it with
188
+ * MemTxAttrs indicating a non-secure transaction.
189
+ */
190
+typedef enum MSCAction {
191
+ MSCBlockAbort,
192
+ MSCBlockRAZWI,
193
+ MSCAllowSecure,
194
+ MSCAllowNonSecure,
195
+} MSCAction;
196
+
197
+static MSCAction tz_msc_check(TZMSC *s, hwaddr addr)
198
+{
199
+ /*
200
+ * Check whether to allow an access from the bus master, returning
201
+ * an MSCAction indicating the required behaviour. If the transaction
202
+ * is blocked, the caller must check cfg_sec_resp to determine
203
+ * whether to abort or RAZ/WI the transaction.
204
+ */
205
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(s->idau);
206
+ IDAUInterface *ii = IDAU_INTERFACE(s->idau);
207
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
208
+ int idau_region = IREGION_NOTVALID;
209
+
210
+ iic->check(ii, addr, &idau_region, &idau_exempt, &idau_ns, &idau_nsc);
211
+
212
+ if (idau_exempt) {
213
+ /*
214
+ * Uncheck region -- OK, transaction type depends on
215
+ * whether bus master is configured as Secure or NonSecure
216
+ */
217
+ return s->cfg_nonsec ? MSCAllowNonSecure : MSCAllowSecure;
218
+ }
219
+
220
+ if (idau_ns) {
221
+ /* NonSecure region -- always forward as NS transaction */
222
+ return MSCAllowNonSecure;
223
+ }
224
+
225
+ if (!s->cfg_nonsec) {
226
+ /* Access to Secure region by Secure bus master: OK */
227
+ return MSCAllowSecure;
228
+ }
229
+
230
+ /* Attempted access to Secure region by NS bus master: block */
231
+ trace_tz_msc_access_blocked(addr);
232
+ if (!s->cfg_sec_resp) {
233
+ return MSCBlockRAZWI;
234
+ }
235
+
236
+ /*
237
+ * The TRM isn't clear on behaviour if irq_clear is high when a
238
+ * transaction is blocked. We assume that the MSC behaves like the
239
+ * PPC, where holding irq_clear high suppresses the interrupt.
240
+ */
241
+ if (!s->irq_clear) {
242
+ s->irq_status = true;
243
+ tz_msc_update_irq(s);
244
+ }
245
+ return MSCBlockAbort;
246
+}
247
+
248
+static MemTxResult tz_msc_read(void *opaque, hwaddr addr, uint64_t *pdata,
249
+ unsigned size, MemTxAttrs attrs)
250
+{
251
+ TZMSC *s = opaque;
252
+ AddressSpace *as = &s->downstream_as;
253
+ uint64_t data;
254
+ MemTxResult res;
255
+
256
+ switch (tz_msc_check(s, addr)) {
257
+ case MSCBlockAbort:
258
+ return MEMTX_ERROR;
259
+ case MSCBlockRAZWI:
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ case MSCAllowSecure:
263
+ attrs.secure = 1;
264
+ attrs.unspecified = 0;
265
+ break;
266
+ case MSCAllowNonSecure:
267
+ attrs.secure = 0;
268
+ attrs.unspecified = 0;
269
+ break;
270
+ }
271
+
272
+ switch (size) {
273
+ case 1:
274
+ data = address_space_ldub(as, addr, attrs, &res);
275
+ break;
276
+ case 2:
277
+ data = address_space_lduw_le(as, addr, attrs, &res);
278
+ break;
279
+ case 4:
280
+ data = address_space_ldl_le(as, addr, attrs, &res);
281
+ break;
282
+ case 8:
283
+ data = address_space_ldq_le(as, addr, attrs, &res);
284
+ break;
285
+ default:
286
+ g_assert_not_reached();
287
+ }
288
+ *pdata = data;
289
+ return res;
290
+}
291
+
292
+static MemTxResult tz_msc_write(void *opaque, hwaddr addr, uint64_t val,
293
+ unsigned size, MemTxAttrs attrs)
294
+{
295
+ TZMSC *s = opaque;
296
+ AddressSpace *as = &s->downstream_as;
297
+ MemTxResult res;
298
+
299
+ switch (tz_msc_check(s, addr)) {
300
+ case MSCBlockAbort:
301
+ return MEMTX_ERROR;
302
+ case MSCBlockRAZWI:
303
+ return MEMTX_OK;
304
+ case MSCAllowSecure:
305
+ attrs.secure = 1;
306
+ attrs.unspecified = 0;
307
+ break;
308
+ case MSCAllowNonSecure:
309
+ attrs.secure = 0;
310
+ attrs.unspecified = 0;
311
+ break;
312
+ }
313
+
314
+ switch (size) {
315
+ case 1:
316
+ address_space_stb(as, addr, val, attrs, &res);
317
+ break;
318
+ case 2:
319
+ address_space_stw_le(as, addr, val, attrs, &res);
320
+ break;
321
+ case 4:
322
+ address_space_stl_le(as, addr, val, attrs, &res);
323
+ break;
324
+ case 8:
325
+ address_space_stq_le(as, addr, val, attrs, &res);
326
+ break;
327
+ default:
328
+ g_assert_not_reached();
329
+ }
330
+ return res;
331
+}
332
+
333
+static const MemoryRegionOps tz_msc_ops = {
334
+ .read_with_attrs = tz_msc_read,
335
+ .write_with_attrs = tz_msc_write,
336
+ .endianness = DEVICE_LITTLE_ENDIAN,
337
+};
338
+
339
+static void tz_msc_reset(DeviceState *dev)
340
+{
341
+ TZMSC *s = TZ_MSC(dev);
342
+
343
+ trace_tz_msc_reset();
344
+ s->cfg_sec_resp = false;
345
+ s->cfg_nonsec = false;
346
+ s->irq_clear = 0;
347
+ s->irq_status = 0;
348
+}
349
+
350
+static void tz_msc_init(Object *obj)
351
+{
352
+ DeviceState *dev = DEVICE(obj);
353
+ TZMSC *s = TZ_MSC(obj);
354
+
355
+ qdev_init_gpio_in_named(dev, tz_msc_cfg_nonsec, "cfg_nonsec", 1);
356
+ qdev_init_gpio_in_named(dev, tz_msc_cfg_sec_resp, "cfg_sec_resp", 1);
357
+ qdev_init_gpio_in_named(dev, tz_msc_irq_clear, "irq_clear", 1);
358
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
359
+}
360
+
361
+static void tz_msc_realize(DeviceState *dev, Error **errp)
362
+{
363
+ Object *obj = OBJECT(dev);
364
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
365
+ TZMSC *s = TZ_MSC(dev);
366
+ const char *name = "tz-msc-downstream";
367
+ uint64_t size;
368
+
369
+ /*
370
+ * We can't create the upstream end of the port until realize,
371
+ * as we don't know the size of the MR used as the downstream until then.
372
+ * We insist on having a downstream, to avoid complicating the
373
+ * code with handling the "don't know how big this is" case. It's easy
374
+ * enough for the user to create an unimplemented_device as downstream
375
+ * if they have nothing else to plug into this.
376
+ */
377
+ if (!s->downstream) {
378
+ error_setg(errp, "MSC 'downstream' link not set");
379
+ return;
380
+ }
381
+ if (!s->idau) {
382
+ error_setg(errp, "MSC 'idau' link not set");
383
+ return;
384
+ }
385
+
386
+ size = memory_region_size(s->downstream);
387
+ address_space_init(&s->downstream_as, s->downstream, name);
388
+ memory_region_init_io(&s->upstream, obj, &tz_msc_ops, s, name, size);
389
+ sysbus_init_mmio(sbd, &s->upstream);
390
+}
391
+
392
+static const VMStateDescription tz_msc_vmstate = {
393
+ .name = "tz-msc",
394
+ .version_id = 1,
395
+ .minimum_version_id = 1,
396
+ .fields = (VMStateField[]) {
397
+ VMSTATE_BOOL(cfg_nonsec, TZMSC),
398
+ VMSTATE_BOOL(cfg_sec_resp, TZMSC),
399
+ VMSTATE_BOOL(irq_clear, TZMSC),
400
+ VMSTATE_BOOL(irq_status, TZMSC),
401
+ VMSTATE_END_OF_LIST()
402
+ }
403
+};
404
+
405
+static Property tz_msc_properties[] = {
406
+ DEFINE_PROP_LINK("downstream", TZMSC, downstream,
407
+ TYPE_MEMORY_REGION, MemoryRegion *),
408
+ DEFINE_PROP_LINK("idau", TZMSC, idau,
409
+ TYPE_IDAU_INTERFACE, IDAUInterface *),
410
+ DEFINE_PROP_END_OF_LIST(),
411
+};
412
+
413
+static void tz_msc_class_init(ObjectClass *klass, void *data)
414
+{
415
+ DeviceClass *dc = DEVICE_CLASS(klass);
416
+
417
+ dc->realize = tz_msc_realize;
418
+ dc->vmsd = &tz_msc_vmstate;
419
+ dc->reset = tz_msc_reset;
420
+ dc->props = tz_msc_properties;
421
+}
422
+
423
+static const TypeInfo tz_msc_info = {
424
+ .name = TYPE_TZ_MSC,
425
+ .parent = TYPE_SYS_BUS_DEVICE,
426
+ .instance_size = sizeof(TZMSC),
427
+ .instance_init = tz_msc_init,
428
+ .class_init = tz_msc_class_init,
429
+};
430
+
431
+static void tz_msc_register_types(void)
432
+{
433
+ type_register_static(&tz_msc_info);
434
+}
435
+
436
+type_init(tz_msc_register_types);
437
diff --git a/MAINTAINERS b/MAINTAINERS
438
index XXXXXXX..XXXXXXX 100644
439
--- a/MAINTAINERS
440
+++ b/MAINTAINERS
441
@@ -XXX,XX +XXX,XX @@ F: hw/misc/tz-ppc.c
442
F: include/hw/misc/tz-ppc.h
443
F: hw/misc/tz-mpc.c
444
F: include/hw/misc/tz-mpc.h
445
+F: hw/misc/tz-msc.c
446
+F: include/hw/misc/tz-msc.h
447
448
ARM cores
449
M: Peter Maydell <peter.maydell@linaro.org>
450
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
451
index XXXXXXX..XXXXXXX 100644
452
--- a/default-configs/arm-softmmu.mak
453
+++ b/default-configs/arm-softmmu.mak
454
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
455
CONFIG_MPS2_SCC=y
456
457
CONFIG_TZ_MPC=y
458
+CONFIG_TZ_MSC=y
459
CONFIG_TZ_PPC=y
460
CONFIG_IOTKIT=y
461
CONFIG_IOTKIT_SECCTL=y
462
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
463
index XXXXXXX..XXXXXXX 100644
464
--- a/hw/misc/trace-events
465
+++ b/hw/misc/trace-events
466
@@ -XXX,XX +XXX,XX @@ tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secur
467
tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
468
tz_mpc_iommu_notify(uint64_t addr) "TZ MPC iommu: notifying UNMAP/MAP for 0x%" PRIx64
469
470
+# hw/misc/tz-msc.c
471
+tz_msc_reset(void) "TZ MSC: reset"
472
+tz_msc_cfg_nonsec(int level) "TZ MSC: cfg_nonsec = %d"
473
+tz_msc_cfg_sec_resp(int level) "TZ MSC: cfg_sec_resp = %d"
474
+tz_msc_irq_enable(int level) "TZ MSC: int_enable = %d"
475
+tz_msc_irq_clear(int level) "TZ MSC: int_clear = %d"
476
+tz_msc_update_irq(int level) "TZ MSC: setting irq line to %d"
477
+tz_msc_access_blocked(uint64_t offset) "TZ MSC: offset 0x%" PRIx64 " access blocked"
478
+
479
# hw/misc/tz-ppc.c
480
tz_ppc_reset(void) "TZ PPC: reset"
481
tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
482
--
483
2.18.0
484
485
diff view generated by jsdifflib
New patch
1
1
The IoTKit does not have any Master Security Contollers itself,
2
but it does provide registers in the secure privilege control
3
block which allow control of MSCs in the external system.
4
Add support for these registers.
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180820141116.9118-13-peter.maydell@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
include/hw/misc/iotkit-secctl.h | 14 +++++++
12
hw/misc/iotkit-secctl.c | 73 +++++++++++++++++++++++++++++----
13
2 files changed, 79 insertions(+), 8 deletions(-)
14
15
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/iotkit-secctl.h
18
+++ b/include/hw/misc/iotkit-secctl.h
19
@@ -XXX,XX +XXX,XX @@
20
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
21
* should RAZ/WI or bus error
22
* + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
23
+ * + named GPIO output "msc_irq" for the combined IRQ line from the MSCs
24
* Controlling the 2 APB PPCs in the IoTKit:
25
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
26
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
27
@@ -XXX,XX +XXX,XX @@
28
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
29
* might provide:
30
* + named GPIO inputs mpcexp_status[0..15]
31
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
32
+ * might provide:
33
+ * + named GPIO inputs mscexp_status[0..15]
34
+ * + named GPIO outputs mscexp_clear[0..15]
35
+ * + named GPIO outputs mscexp_ns[0..15]
36
*/
37
38
#ifndef IOTKIT_SECCTL_H
39
@@ -XXX,XX +XXX,XX @@
40
#define IOTS_NUM_AHB_EXP_PPC 4
41
#define IOTS_NUM_EXP_MPC 16
42
#define IOTS_NUM_MPC 1
43
+#define IOTS_NUM_EXP_MSC 16
44
45
typedef struct IoTKitSecCtl IoTKitSecCtl;
46
47
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
48
uint32_t brginten;
49
uint32_t mpcintstatus;
50
51
+ uint32_t secmscintstat;
52
+ uint32_t secmscinten;
53
+ uint32_t nsmscexp;
54
+ qemu_irq mscexp_clear[IOTS_NUM_EXP_MSC];
55
+ qemu_irq mscexp_ns[IOTS_NUM_EXP_MSC];
56
+ qemu_irq msc_irq;
57
+
58
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
59
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
60
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
61
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/misc/iotkit-secctl.c
64
+++ b/hw/misc/iotkit-secctl.c
65
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
66
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
67
break;
68
case A_SECMSCINTSTAT:
69
+ r = s->secmscintstat;
70
+ break;
71
case A_SECMSCINTEN:
72
+ r = s->secmscinten;
73
+ break;
74
case A_NSMSCEXP:
75
- qemu_log_mask(LOG_UNIMP,
76
- "IoTKit SecCtl S block read: "
77
- "unimplemented offset 0x%x\n", offset);
78
- r = 0;
79
+ r = s->nsmscexp;
80
break;
81
case A_PID4:
82
case A_PID5:
83
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
84
qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
85
}
86
87
+static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
88
+{
89
+ int i;
90
+
91
+ for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
92
+ qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
93
+ }
94
+}
95
+
96
+static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
97
+{
98
+ /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
99
+ bool level = s->secmscintstat & s->secmscinten;
100
+
101
+ qemu_set_irq(s->msc_irq, level);
102
+}
103
+
104
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
105
uint64_t value,
106
unsigned size, MemTxAttrs attrs)
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
iotkit_secctl_ppc_sp_write(ppc, value);
109
break;
110
case A_SECMSCINTCLR:
111
+ iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
112
+ break;
113
case A_SECMSCINTEN:
114
- qemu_log_mask(LOG_UNIMP,
115
- "IoTKit SecCtl S block write: "
116
- "unimplemented offset 0x%x\n", offset);
117
+ s->secmscinten = value;
118
+ iotkit_secctl_update_msc_irq(s);
119
+ break;
120
+ case A_NSMSCEXP:
121
+ s->nsmscexp = value;
122
+ iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
123
break;
124
case A_SECMPCINTSTATUS:
125
case A_SECPPCINTSTAT:
126
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
127
case A_BRGINTSTAT:
128
case A_AHBNSPPC0:
129
case A_AHBSPPPC0:
130
- case A_NSMSCEXP:
131
case A_PID4:
132
case A_PID5:
133
case A_PID6:
134
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
135
s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
136
}
137
138
+static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
139
+{
140
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
141
+
142
+ s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
143
+ iotkit_secctl_update_msc_irq(s);
144
+}
145
+
146
static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
147
{
148
IoTKitSecCtlPPC *ppc = opaque;
149
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
150
qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
151
"mpcexp_status", IOTS_NUM_EXP_MPC);
152
153
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
154
+ "mscexp_status", IOTS_NUM_EXP_MSC);
155
+ qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
156
+ IOTS_NUM_EXP_MSC);
157
+ qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
158
+ IOTS_NUM_EXP_MSC);
159
+ qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
160
+
161
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
162
s, "iotkit-secctl-s-regs", 0x1000);
163
memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
164
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
165
}
166
};
167
168
+static bool needed_always(void *opaque)
169
+{
170
+ return true;
171
+}
172
+
173
+static const VMStateDescription iotkit_secctl_msc_vmstate = {
174
+ .name = "iotkit-secctl/msc",
175
+ .version_id = 1,
176
+ .minimum_version_id = 1,
177
+ .needed = needed_always,
178
+ .fields = (VMStateField[]) {
179
+ VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
180
+ VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
181
+ VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
182
+ VMSTATE_END_OF_LIST()
183
+ }
184
+};
185
+
186
static const VMStateDescription iotkit_secctl_vmstate = {
187
.name = "iotkit-secctl",
188
.version_id = 1,
189
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
190
},
191
.subsections = (const VMStateDescription*[]) {
192
&iotkit_secctl_mpcintstatus_vmstate,
193
+ &iotkit_secctl_msc_vmstate,
194
NULL
195
},
196
};
197
--
198
2.18.0
199
200
diff view generated by jsdifflib
1
Our copy of the nwfpe code for emulating of the old FPA11 floating
1
The IoTKit doesn't have any MSCs itself but it does need
2
point unit doesn't check the coprocessor number in the instruction
2
some wiring to connect the external signals from MSCs
3
when it emulates it. This means that we might treat some
3
in the outer board model up to the registers and the
4
instructions which should really UNDEF as being FPA11 instructions by
4
NVIC IRQ line.
5
accident.
6
5
7
The kernel's copy of the nwfpe code doesn't make this error; I suspect
6
We also need to expose a MemoryRegion corresponding to
8
the bug was noticed and fixed as part of the process of mainlining
7
the AHB bus, so that MSCs in the outer board model can
9
the nwfpe code more than a decade ago.
8
use that as their downstream port. (In the FPGA this is
9
the "AHB Slave Expansion" ports shown in the block
10
diagram in the AN505 documentation.)
10
11
11
Add a check that the coprocessor number (which is always in bits
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
[11:8] of the instruction) is either 1 or 2, which is where the
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
FPA11 lives.
14
Message-id: 20180820141116.9118-14-peter.maydell@linaro.org
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
include/hw/arm/iotkit.h | 8 ++++++++
18
hw/arm/iotkit.c | 15 +++++++++++++++
19
2 files changed, 23 insertions(+)
14
20
15
Reported-by: Richard Henderson <richard.henderson@linaro.org>
21
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
linux-user/arm/nwfpe/fpa11.c | 9 +++++++++
19
1 file changed, 9 insertions(+)
20
21
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/linux-user/arm/nwfpe/fpa11.c
23
--- a/include/hw/arm/iotkit.h
24
+++ b/linux-user/arm/nwfpe/fpa11.c
24
+++ b/include/hw/arm/iotkit.h
25
@@ -XXX,XX +XXX,XX @@ unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs)
25
@@ -XXX,XX +XXX,XX @@
26
unsigned int nRc = 0;
26
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
27
// unsigned long flags;
27
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
28
FPA11 *fpa11;
28
* are wired to the NVIC lines 32 .. n+32
29
+ unsigned int cp;
29
+ * + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
30
// save_flags(flags); sti();
30
+ * bus master devices in the board model to make transactions into
31
31
+ * all the devices and memory areas in the IoTKit
32
+ /* Check that this is really an FPA11 instruction: the coprocessor
32
* Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
33
+ * field in bits [11:8] must be 1 or 2.
33
* might provide:
34
+ */
34
* + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
35
+ cp = (opcode >> 8) & 0xf;
35
@@ -XXX,XX +XXX,XX @@
36
+ if (cp != 1 && cp != 2) {
36
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
37
+ return 0;
37
* might provide:
38
+ }
38
* + named GPIO inputs mpcexp_status[0..15]
39
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
40
+ * might provide:
41
+ * + named GPIO inputs mscexp_status[0..15]
42
+ * + named GPIO outputs mscexp_clear[0..15]
43
+ * + named GPIO outputs mscexp_ns[0..15]
44
*/
45
46
#ifndef IOTKIT_H
47
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/iotkit.c
50
+++ b/hw/arm/iotkit.c
51
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
52
53
iotkit_forward_sec_resp_cfg(s);
54
55
+ /* Forward the MSC related signals */
56
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
57
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
58
+ qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
59
+ qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
60
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
39
+
61
+
40
qemufpa=qfpa;
62
+ /*
41
user_registers=qregs;
63
+ * Expose our container region to the board model; this corresponds
64
+ * to the AHB Slave Expansion ports which allow bus master devices
65
+ * (eg DMA controllers) in the board model to make transactions into
66
+ * devices in the IoTKit.
67
+ */
68
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
69
+
70
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
71
}
42
72
43
--
73
--
44
2.7.4
74
2.18.0
45
75
46
76
diff view generated by jsdifflib
New patch
1
The AN505 FPGA image includes four PL081 DMA controllers, each
2
of which is gated by a Master Security Controller that allows
3
the guest to prevent a non-secure DMA controller from accessing
4
memory that is used by secure guest code. Create and wire
5
up these devices.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20180820141116.9118-15-peter.maydell@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
hw/arm/mps2-tz.c | 100 +++++++++++++++++++++++++++++++++++++++++++----
13
1 file changed, 93 insertions(+), 7 deletions(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/misc/mps2-scc.h"
21
#include "hw/misc/mps2-fpgaio.h"
22
#include "hw/misc/tz-mpc.h"
23
+#include "hw/misc/tz-msc.h"
24
#include "hw/arm/iotkit.h"
25
+#include "hw/dma/pl080.h"
26
#include "hw/devices.h"
27
#include "net/net.h"
28
#include "hw/core/split-irq.h"
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
UnimplementedDeviceState i2c[4];
31
UnimplementedDeviceState i2s_audio;
32
UnimplementedDeviceState gpio[4];
33
- UnimplementedDeviceState dma[4];
34
UnimplementedDeviceState gfx;
35
+ PL080State dma[4];
36
+ TZMSC msc[4];
37
CMSDKAPBUART uart[5];
38
SplitIRQ sec_resp_splitter;
39
qemu_or_irq uart_irq_orgate;
40
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
41
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
42
}
43
44
+static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
45
+ const char *name, hwaddr size)
46
+{
47
+ PL080State *dma = opaque;
48
+ int i = dma - &mms->dma[0];
49
+ SysBusDevice *s;
50
+ char *mscname = g_strdup_printf("%s-msc", name);
51
+ TZMSC *msc = &mms->msc[i];
52
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
53
+ MemoryRegion *msc_upstream;
54
+ MemoryRegion *msc_downstream;
55
+
56
+ /*
57
+ * Each DMA device is a PL081 whose transaction master interface
58
+ * is guarded by a Master Security Controller. The downstream end of
59
+ * the MSC connects to the IoTKit AHB Slave Expansion port, so the
60
+ * DMA devices can see all devices and memory that the CPU does.
61
+ */
62
+ sysbus_init_child_obj(OBJECT(mms), mscname, msc, sizeof(*msc), TYPE_TZ_MSC);
63
+ msc_downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit), 0);
64
+ object_property_set_link(OBJECT(msc), OBJECT(msc_downstream),
65
+ "downstream", &error_fatal);
66
+ object_property_set_link(OBJECT(msc), OBJECT(mms),
67
+ "idau", &error_fatal);
68
+ object_property_set_bool(OBJECT(msc), true, "realized", &error_fatal);
69
+
70
+ qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0,
71
+ qdev_get_gpio_in_named(iotkitdev,
72
+ "mscexp_status", i));
73
+ qdev_connect_gpio_out_named(iotkitdev, "mscexp_clear", i,
74
+ qdev_get_gpio_in_named(DEVICE(msc),
75
+ "irq_clear", 0));
76
+ qdev_connect_gpio_out_named(iotkitdev, "mscexp_ns", i,
77
+ qdev_get_gpio_in_named(DEVICE(msc),
78
+ "cfg_nonsec", 0));
79
+ qdev_connect_gpio_out(DEVICE(&mms->sec_resp_splitter),
80
+ ARRAY_SIZE(mms->ppc) + i,
81
+ qdev_get_gpio_in_named(DEVICE(msc),
82
+ "cfg_sec_resp", 0));
83
+ msc_upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0);
84
+
85
+ sysbus_init_child_obj(OBJECT(mms), name, dma, sizeof(*dma), TYPE_PL081);
86
+ object_property_set_link(OBJECT(dma), OBJECT(msc_upstream),
87
+ "downstream", &error_fatal);
88
+ object_property_set_bool(OBJECT(dma), true, "realized", &error_fatal);
89
+
90
+ s = SYS_BUS_DEVICE(dma);
91
+ /* Wire up DMACINTR, DMACINTERR, DMACINTTC */
92
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
93
+ "EXP_IRQ", 58 + i * 3));
94
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
95
+ "EXP_IRQ", 56 + i * 3));
96
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
97
+ "EXP_IRQ", 57 + i * 3));
98
+
99
+ return sysbus_mmio_get_region(s, 0);
100
+}
101
+
102
static void mps2tz_common_init(MachineState *machine)
103
{
104
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
105
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
106
&error_fatal);
107
108
/* The sec_resp_cfg output from the IoTKit must be split into multiple
109
- * lines, one for each of the PPCs we create here.
110
+ * lines, one for each of the PPCs we create here, plus one per MSC.
111
*/
112
object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
113
TYPE_SPLIT_IRQ);
114
object_property_add_child(OBJECT(machine), "sec-resp-splitter",
115
OBJECT(&mms->sec_resp_splitter), &error_abort);
116
- object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
117
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
118
+ ARRAY_SIZE(mms->ppc) + ARRAY_SIZE(mms->msc),
119
"num-lines", &error_fatal);
120
object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
121
"realized", &error_fatal);
122
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
123
}, {
124
.name = "ahb_ppcexp1",
125
.ports = {
126
- { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
127
- { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
128
- { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
129
- { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
130
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
131
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
132
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
133
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
134
},
135
},
136
};
137
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
138
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
139
}
140
141
+static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
142
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
143
+{
144
+ /*
145
+ * The MPS2 TZ FPGA images have IDAUs in them which are connected to
146
+ * the Master Security Controllers. Thes have the same logic as
147
+ * is used by the IoTKit for the IDAU connected to the CPU, except
148
+ * that MSCs don't care about the NSC attribute.
149
+ */
150
+ int region = extract32(address, 28, 4);
151
+
152
+ *ns = !(region & 1);
153
+ *nsc = false;
154
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
155
+ *exempt = (address & 0xeff00000) == 0xe0000000;
156
+ *iregion = region;
157
+}
158
+
159
static void mps2tz_class_init(ObjectClass *oc, void *data)
160
{
161
MachineClass *mc = MACHINE_CLASS(oc);
162
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
163
164
mc->init = mps2tz_common_init;
165
mc->max_cpus = 1;
166
+ iic->check = mps2_tz_idau_check;
167
}
168
169
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
170
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_info = {
171
.instance_size = sizeof(MPS2TZMachineState),
172
.class_size = sizeof(MPS2TZMachineClass),
173
.class_init = mps2tz_class_init,
174
+ .interfaces = (InterfaceInfo[]) {
175
+ { TYPE_IDAU_INTERFACE },
176
+ { }
177
+ },
178
};
179
180
static const TypeInfo mps2tz_an505_info = {
181
--
182
2.18.0
183
184
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Create a new include file for the pl022's device struct,
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
2
4
3
Add target aarch64_be-linux-user. This allows a qemu-aarch64_be binary
5
While we're adding the new file to MAINTAINERS, add
4
to be built that will run big-endian aarch64 binaries.
6
also the .c file, which was missing an entry.
5
7
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20180820141116.9118-16-peter.maydell@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
9
Message-id: 20171220212308.12614-5-michael.weiser@gmx.de
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
configure | 5 +++--
13
include/hw/ssi/pl022.h | 51 ++++++++++++++++++++++++++++++++++++++++++
13
default-configs/aarch64_be-linux-user.mak | 1 +
14
hw/ssi/pl022.c | 26 +--------------------
14
2 files changed, 4 insertions(+), 2 deletions(-)
15
MAINTAINERS | 2 ++
15
create mode 100644 default-configs/aarch64_be-linux-user.mak
16
3 files changed, 54 insertions(+), 25 deletions(-)
17
create mode 100644 include/hw/ssi/pl022.h
16
18
17
diff --git a/configure b/configure
19
diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h
18
index XXXXXXX..XXXXXXX 100755
19
--- a/configure
20
+++ b/configure
21
@@ -XXX,XX +XXX,XX @@ target_name=$(echo $target | cut -d '-' -f 1)
22
target_bigendian="no"
23
24
case "$target_name" in
25
- armeb|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
26
+ armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
27
target_bigendian=yes
28
;;
29
esac
30
@@ -XXX,XX +XXX,XX @@ case "$target_name" in
31
mttcg="yes"
32
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
33
;;
34
- aarch64)
35
+ aarch64|aarch64_be)
36
+ TARGET_ARCH=aarch64
37
TARGET_BASE_ARCH=arm
38
bflt="yes"
39
mttcg="yes"
40
diff --git a/default-configs/aarch64_be-linux-user.mak b/default-configs/aarch64_be-linux-user.mak
41
new file mode 100644
20
new file mode 100644
42
index XXXXXXX..XXXXXXX
21
index XXXXXXX..XXXXXXX
43
--- /dev/null
22
--- /dev/null
44
+++ b/default-configs/aarch64_be-linux-user.mak
23
+++ b/include/hw/ssi/pl022.h
45
@@ -0,0 +1 @@
24
@@ -XXX,XX +XXX,XX @@
46
+# Default configuration for aarch64_be-linux-user
25
+/*
26
+ * ARM PrimeCell PL022 Synchronous Serial Port
27
+ *
28
+ * Copyright (c) 2007 CodeSourcery.
29
+ * Written by Paul Brook
30
+ *
31
+ * This program is free software; you can redistribute it and/or modify
32
+ * it under the terms of the GNU General Public License version 2 or
33
+ * (at your option) any later version.
34
+ */
35
+
36
+/* This is a model of the Arm PrimeCell PL022 synchronous serial port.
37
+ * The PL022 TRM is:
38
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/DDI0194H_ssp_pl022_trm.pdf
39
+ *
40
+ * QEMU interface:
41
+ * + sysbus IRQ: SSPINTR combined interrupt line
42
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
43
+ */
44
+
45
+#ifndef HW_SSI_PL022_H
46
+#define HW_SSI_PL022_H
47
+
48
+#include "hw/sysbus.h"
49
+
50
+#define TYPE_PL022 "pl022"
51
+#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
52
+
53
+typedef struct PL022State {
54
+ SysBusDevice parent_obj;
55
+
56
+ MemoryRegion iomem;
57
+ uint32_t cr0;
58
+ uint32_t cr1;
59
+ uint32_t bitmask;
60
+ uint32_t sr;
61
+ uint32_t cpsr;
62
+ uint32_t is;
63
+ uint32_t im;
64
+ /* The FIFO head points to the next empty entry. */
65
+ int tx_fifo_head;
66
+ int rx_fifo_head;
67
+ int tx_fifo_len;
68
+ int rx_fifo_len;
69
+ uint16_t tx_fifo[8];
70
+ uint16_t rx_fifo[8];
71
+ qemu_irq irq;
72
+ SSIBus *ssi;
73
+} PL022State;
74
+
75
+#endif
76
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/ssi/pl022.c
79
+++ b/hw/ssi/pl022.c
80
@@ -XXX,XX +XXX,XX @@
81
82
#include "qemu/osdep.h"
83
#include "hw/sysbus.h"
84
+#include "hw/ssi/pl022.h"
85
#include "hw/ssi/ssi.h"
86
#include "qemu/log.h"
87
88
@@ -XXX,XX +XXX,XX @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
89
#define PL022_INT_RX 0x04
90
#define PL022_INT_TX 0x08
91
92
-#define TYPE_PL022 "pl022"
93
-#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
94
-
95
-typedef struct PL022State {
96
- SysBusDevice parent_obj;
97
-
98
- MemoryRegion iomem;
99
- uint32_t cr0;
100
- uint32_t cr1;
101
- uint32_t bitmask;
102
- uint32_t sr;
103
- uint32_t cpsr;
104
- uint32_t is;
105
- uint32_t im;
106
- /* The FIFO head points to the next empty entry. */
107
- int tx_fifo_head;
108
- int rx_fifo_head;
109
- int tx_fifo_len;
110
- int rx_fifo_len;
111
- uint16_t tx_fifo[8];
112
- uint16_t rx_fifo[8];
113
- qemu_irq irq;
114
- SSIBus *ssi;
115
-} PL022State;
116
-
117
static const unsigned char pl022_id[8] =
118
{ 0x22, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
119
120
diff --git a/MAINTAINERS b/MAINTAINERS
121
index XXXXXXX..XXXXXXX 100644
122
--- a/MAINTAINERS
123
+++ b/MAINTAINERS
124
@@ -XXX,XX +XXX,XX @@ F: hw/gpio/pl061.c
125
F: hw/input/pl050.c
126
F: hw/intc/pl190.c
127
F: hw/sd/pl181.c
128
+F: hw/ssi/pl022.c
129
+F: include/hw/ssi/pl022.h
130
F: hw/timer/pl031.c
131
F: include/hw/arm/primecell.h
132
F: hw/timer/cmsdk-apb-timer.c
47
--
133
--
48
2.7.4
134
2.18.0
49
135
50
136
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Currently the PL022 calls pl022_reset() from its class init
2
function. Make it register a DeviceState reset method instead,
3
so that we reset the device on system reset.
2
4
3
ldxp loads two consecutive doublewords from memory regardless of CPU
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
endianness. On store, stlxp currently assumes to work with a 128bit
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
value and consequently switches order in big-endian mode. With this
7
Message-id: 20180820141116.9118-17-peter.maydell@linaro.org
6
change it packs the doublewords in reverse order in anticipation of the
7
128bit big-endian store operation interposing them so they end up in
8
memory in the right order. This makes it work for both MTTCG and !MTTCG.
9
It effectively implements the ARM ARM STLXP operation pseudo-code:
10
11
data = if BigEndian() then el1:el2 else el2:el1;
12
13
With this change an aarch64_be Linux 4.14.4 kernel succeeds to boot up
14
in system emulation mode.
15
16
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
9
---
20
target/arm/helper-a64.c | 7 +++++--
10
hw/ssi/pl022.c | 7 +++++--
21
1 file changed, 5 insertions(+), 2 deletions(-)
11
1 file changed, 5 insertions(+), 2 deletions(-)
22
12
23
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
13
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.c
15
--- a/hw/ssi/pl022.c
26
+++ b/target/arm/helper-a64.c
16
+++ b/hw/ssi/pl022.c
27
@@ -XXX,XX +XXX,XX @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
17
@@ -XXX,XX +XXX,XX @@ static void pl022_write(void *opaque, hwaddr offset,
28
Int128 oldv, cmpv, newv;
18
}
29
bool success;
19
}
30
20
31
- cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
21
-static void pl022_reset(PL022State *s)
32
- newv = int128_make128(new_lo, new_hi);
22
+static void pl022_reset(DeviceState *dev)
33
+ /* high and low need to be switched here because this is not actually a
23
{
34
+ * 128bit store but two doublewords stored consecutively
24
+ PL022State *s = PL022(dev);
35
+ */
25
+
36
+ cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
26
s->rx_fifo_len = 0;
37
+ newv = int128_make128(new_hi, new_lo);
27
s->tx_fifo_len = 0;
38
28
s->im = 0;
39
if (parallel) {
29
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
40
#ifndef CONFIG_ATOMIC128
30
sysbus_init_mmio(sbd, &s->iomem);
31
sysbus_init_irq(sbd, &s->irq);
32
s->ssi = ssi_create_bus(dev, "ssi");
33
- pl022_reset(s);
34
vmstate_register(dev, -1, &vmstate_pl022, s);
35
return 0;
36
}
37
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
38
static void pl022_class_init(ObjectClass *klass, void *data)
39
{
40
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
41
+ DeviceClass *dc = DEVICE_CLASS(klass);
42
43
sdc->init = pl022_init;
44
+ dc->reset = pl022_reset;
45
}
46
47
static const TypeInfo pl022_info = {
41
--
48
--
42
2.7.4
49
2.18.0
43
50
44
51
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Use the DeviceState vmsd pointer rather than calling vmstate_register()
2
directly.
2
3
3
Use 'frame_size' instead of 'len' when calling qemu_send_packet(),
4
failing to do so results in malformed packets send in case when that
5
packed is fragmented into multiple DMA transactions.
6
7
Cc: Peter Maydell <peter.maydell@linaro.org>
8
Cc: Jason Wang <jasowang@redhat.com>
9
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180820141116.9118-18-peter.maydell@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
7
---
17
hw/net/imx_fec.c | 2 +-
8
hw/ssi/pl022.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
19
10
20
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
11
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/imx_fec.c
13
--- a/hw/ssi/pl022.c
23
+++ b/hw/net/imx_fec.c
14
+++ b/hw/ssi/pl022.c
24
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
15
@@ -XXX,XX +XXX,XX @@ static int pl022_init(SysBusDevice *sbd)
25
}
16
sysbus_init_mmio(sbd, &s->iomem);
26
/* Last buffer in frame. */
17
sysbus_init_irq(sbd, &s->irq);
27
18
s->ssi = ssi_create_bus(dev, "ssi");
28
- qemu_send_packet(qemu_get_queue(s->nic), s->frame, len);
19
- vmstate_register(dev, -1, &vmstate_pl022, s);
29
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
20
return 0;
30
ptr = s->frame;
21
}
31
22
32
frame_size = 0;
23
@@ -XXX,XX +XXX,XX @@ static void pl022_class_init(ObjectClass *klass, void *data)
24
25
sdc->init = pl022_init;
26
dc->reset = pl022_reset;
27
+ dc->vmsd = &vmstate_pl022;
28
}
29
30
static const TypeInfo pl022_info = {
33
--
31
--
34
2.7.4
32
2.18.0
35
33
36
34
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Move from the legacy SysBusDevice::init method to using
2
DeviceState::realize.
2
3
3
Make big-endian aarch64 systems identify as aarch64_be as expected by
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
big-endian userland and toolchains.
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20180820141116.9118-19-peter.maydell@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
hw/ssi/pl022.c | 8 +++-----
10
1 file changed, 3 insertions(+), 5 deletions(-)
5
11
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
12
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
9
Message-id: 20171220212308.12614-3-michael.weiser@gmx.de
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/aarch64/target_syscall.h | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_syscall.h
14
--- a/hw/ssi/pl022.c
18
+++ b/linux-user/aarch64/target_syscall.h
15
+++ b/hw/ssi/pl022.c
19
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
16
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl022 = {
20
uint64_t pstate;
17
}
21
};
18
};
22
19
23
+#if defined(TARGET_WORDS_BIGENDIAN)
20
-static int pl022_init(SysBusDevice *sbd)
24
+#define UNAME_MACHINE "aarch64_be"
21
+static void pl022_realize(DeviceState *dev, Error **errp)
25
+#else
22
{
26
#define UNAME_MACHINE "aarch64"
23
- DeviceState *dev = DEVICE(sbd);
27
+#endif
24
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
28
#define UNAME_MINIMUM_RELEASE "3.8.0"
25
PL022State *s = PL022(dev);
29
#define TARGET_CLONE_BACKWARDS
26
30
#define TARGET_MINSIGSTKSZ 2048
27
memory_region_init_io(&s->iomem, OBJECT(s), &pl022_ops, s, "pl022", 0x1000);
28
sysbus_init_mmio(sbd, &s->iomem);
29
sysbus_init_irq(sbd, &s->irq);
30
s->ssi = ssi_create_bus(dev, "ssi");
31
- return 0;
32
}
33
34
static void pl022_class_init(ObjectClass *klass, void *data)
35
{
36
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
37
DeviceClass *dc = DEVICE_CLASS(klass);
38
39
- sdc->init = pl022_init;
40
dc->reset = pl022_reset;
41
dc->vmsd = &vmstate_pl022;
42
+ dc->realize = pl022_realize;
43
}
44
45
static const TypeInfo pl022_info = {
31
--
46
--
32
2.7.4
47
2.18.0
33
48
34
49
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
The PL022 interrupt registers have bits allocated as:
2
0: ROR (receive overrun)
3
1: RT (receive timeout)
4
2: RX (receive FIFO half full or less)
5
3: TX (transmit FIFO half full or less)
2
6
3
Cc: Peter Maydell <peter.maydell@linaro.org>
7
A cut and paste error meant we had the wrong value for
4
Cc: Jason Wang <jasowang@redhat.com>
8
the PL022_INT_RT constant. This bug doesn't affect device
5
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
behaviour, because we don't implement the receive timeout
6
Cc: qemu-devel@nongnu.org
10
feature and so never set that interrupt bit.
7
Cc: qemu-arm@nongnu.org
11
8
Cc: yurovsky@gmail.com
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20180820141116.9118-20-peter.maydell@linaro.org
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
15
---
13
hw/net/imx_fec.c | 2 +-
16
hw/ssi/pl022.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
18
16
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
19
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/imx_fec.c
21
--- a/hw/ssi/pl022.c
19
+++ b/hw/net/imx_fec.c
22
+++ b/hw/ssi/pl022.c
20
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
23
@@ -XXX,XX +XXX,XX @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
21
TYPE_IMX_FEC, __func__);
24
#define PL022_SR_BSY 0x10
22
break;
25
23
}
26
#define PL022_INT_ROR 0x01
24
- buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
27
-#define PL022_INT_RT 0x04
25
+ buf_len = MIN(size, s->regs[ENET_MRBR]);
28
+#define PL022_INT_RT 0x02
26
bd.length = buf_len;
29
#define PL022_INT_RX 0x04
27
size -= buf_len;
30
#define PL022_INT_TX 0x08
28
31
29
--
32
--
30
2.7.4
33
2.18.0
31
34
32
35
diff view generated by jsdifflib
New patch
1
In the PL022, register offset 0x20 is the ICR, a write-only
2
interrupt-clear register. Register offset 0x24 is DMACR, the DMA
3
control register. We were incorrectly implementing (a stub version
4
of) DMACR at 0x20, and not implementing anything at 0x24. Fix this
5
bug.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180820141116.9118-21-peter.maydell@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
hw/ssi/pl022.c | 12 ++++++++++--
12
1 file changed, 10 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/ssi/pl022.c
17
+++ b/hw/ssi/pl022.c
18
@@ -XXX,XX +XXX,XX @@ static uint64_t pl022_read(void *opaque, hwaddr offset,
19
return s->is;
20
case 0x1c: /* MIS */
21
return s->im & s->is;
22
- case 0x20: /* DMACR */
23
+ case 0x24: /* DMACR */
24
/* Not implemented. */
25
return 0;
26
default:
27
@@ -XXX,XX +XXX,XX @@ static void pl022_write(void *opaque, hwaddr offset,
28
s->im = value;
29
pl022_update(s);
30
break;
31
- case 0x20: /* DMACR */
32
+ case 0x20: /* ICR */
33
+ /*
34
+ * write-1-to-clear: bit 0 clears ROR, bit 1 clears RT;
35
+ * RX and TX interrupts cannot be cleared this way.
36
+ */
37
+ value &= PL022_INT_ROR | PL022_INT_RT;
38
+ s->is &= ~value;
39
+ break;
40
+ case 0x24: /* DMACR */
41
if (value) {
42
qemu_log_mask(LOG_UNIMP, "pl022: DMA not implemented\n");
43
}
44
--
45
2.18.0
46
47
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
The SPI controllers in the MPS2 AN505 board are PL022s.
2
We have a model of the PL022, so create these devices.
2
3
3
Some i.MX SoCs (e.g. i.MX7) have FEC registers going as far as offset
4
We don't currently model the LCD controller that sits behind
4
0x614, so to avoid getting aborts when accessing those on QEMU, extend
5
one of the PL022s; the others are intended to control devices
5
the register file to cover FSL_IMX25_FEC_SIZE(16K) of address space
6
that sit on the FPGA's general purpose SPI connector or
6
instead of just 1K.
7
"shield" expansion connectors.
7
8
8
Cc: Peter Maydell <peter.maydell@linaro.org>
9
Cc: Jason Wang <jasowang@redhat.com>
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20180820141116.9118-22-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
---
12
---
18
include/hw/arm/fsl-imx25.h | 1 -
13
hw/arm/mps2-tz.c | 38 ++++++++++++++++++++++++++++++++------
19
include/hw/net/imx_fec.h | 1 +
14
1 file changed, 32 insertions(+), 6 deletions(-)
20
hw/net/imx_fec.c | 2 +-
21
3 files changed, 2 insertions(+), 2 deletions(-)
22
15
23
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/fsl-imx25.h
18
--- a/hw/arm/mps2-tz.c
26
+++ b/include/hw/arm/fsl-imx25.h
19
+++ b/hw/arm/mps2-tz.c
27
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
20
@@ -XXX,XX +XXX,XX @@
28
#define FSL_IMX25_UART5_ADDR 0x5002C000
21
#include "hw/misc/tz-msc.h"
29
#define FSL_IMX25_UART5_SIZE 0x4000
22
#include "hw/arm/iotkit.h"
30
#define FSL_IMX25_FEC_ADDR 0x50038000
23
#include "hw/dma/pl080.h"
31
-#define FSL_IMX25_FEC_SIZE 0x4000
24
+#include "hw/ssi/pl022.h"
32
#define FSL_IMX25_CCM_ADDR 0x53F80000
25
#include "hw/devices.h"
33
#define FSL_IMX25_CCM_SIZE 0x4000
26
#include "net/net.h"
34
#define FSL_IMX25_GPT4_ADDR 0x53F84000
27
#include "hw/core/split-irq.h"
35
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/net/imx_fec.h
38
+++ b/include/hw/net/imx_fec.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
40
29
MPS2FPGAIO fpgaio;
41
#define ENET_TX_RING_NUM 3
30
TZPPC ppc[5];
42
31
TZMPC ssram_mpc[3];
43
+#define FSL_IMX25_FEC_SIZE 0x4000
32
- UnimplementedDeviceState spi[5];
44
33
+ PL022State spi[5];
45
typedef struct IMXFECState {
34
UnimplementedDeviceState i2c[4];
46
/*< private >*/
35
UnimplementedDeviceState i2s_audio;
47
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
36
UnimplementedDeviceState gpio[4];
48
index XXXXXXX..XXXXXXX 100644
37
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
49
--- a/hw/net/imx_fec.c
38
return sysbus_mmio_get_region(s, 0);
50
+++ b/hw/net/imx_fec.c
39
}
51
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
40
52
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
41
+static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
53
42
+ const char *name, hwaddr size)
54
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
43
+{
55
- TYPE_IMX_FEC, 0x400);
44
+ /*
56
+ TYPE_IMX_FEC, FSL_IMX25_FEC_SIZE);
45
+ * The AN505 has five PL022 SPI controllers.
57
sysbus_init_mmio(sbd, &s->iomem);
46
+ * One of these should have the LCD controller behind it; the others
58
sysbus_init_irq(sbd, &s->irq[0]);
47
+ * are connected only to the FPGA's "general purpose SPI connector"
59
sysbus_init_irq(sbd, &s->irq[1]);
48
+ * or "shield" expansion connectors.
49
+ * Note that if we do implement devices behind SPI, the chip select
50
+ * lines are set via the "MISC" register in the MPS2 FPGAIO device.
51
+ */
52
+ PL022State *spi = opaque;
53
+ int i = spi - &mms->spi[0];
54
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
55
+ SysBusDevice *s;
56
+
57
+ sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
58
+ TYPE_PL022);
59
+ object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
60
+ s = SYS_BUS_DEVICE(spi);
61
+ sysbus_connect_irq(s, 0,
62
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
63
+ return sysbus_mmio_get_region(s, 0);
64
+}
65
+
66
static void mps2tz_common_init(MachineState *machine)
67
{
68
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
69
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
70
}, {
71
.name = "apb_ppcexp1",
72
.ports = {
73
- { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
74
- { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
75
- { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
76
- { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
77
- { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
78
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
79
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
80
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
81
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
82
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
83
{ "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
84
{ "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
85
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
60
--
86
--
61
2.7.4
87
2.18.0
62
88
63
89
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Some of the config register values we were setting for the MPS2 SCC
2
weren't correct:
3
* the SCC_AID bits [23:20] specify the FPGA build target board revision,
4
and the SCC_CFG4 register specifies the actual board revision, so
5
these should have matching values. Claim to be board revision C,
6
consistently -- we had the revision in the wrong part of SCC_AID.
7
* SCC_ID bits [15:4] should be 0x505, not decimal 505
2
8
3
Give big-endian arm and aarch64 CPUs their own family in
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
qemu-binfmt-conf.sh to make sure we register qemu-user for binaries of
10
Message-id: 20180820141116.9118-23-peter.maydell@linaro.org
5
the opposite endianness on arm and aarch64. Apart from the family
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
assignments of the magic values, qemu_get_family() needs to be able to
12
---
7
distinguish the two and recognise aarch64{,_be} as well.
13
hw/arm/mps2-tz.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
8
15
9
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
10
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
17
index XXXXXXX..XXXXXXX 100644
11
Message-id: 20171220212308.12614-7-michael.weiser@gmx.de
18
--- a/hw/arm/mps2-tz.c
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
+++ b/hw/arm/mps2-tz.c
13
---
20
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
14
scripts/qemu-binfmt-conf.sh | 9 ++++++---
21
sccdev = DEVICE(scc);
15
1 file changed, 6 insertions(+), 3 deletions(-)
22
qdev_set_parent_bus(sccdev, sysbus_get_default());
16
23
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
17
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
24
- qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
18
index XXXXXXX..XXXXXXX 100755
25
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
19
--- a/scripts/qemu-binfmt-conf.sh
26
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
20
+++ b/scripts/qemu-binfmt-conf.sh
27
object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
21
@@ -XXX,XX +XXX,XX @@ arm_family=arm
28
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
22
29
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
23
armeb_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28'
30
mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
24
armeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
31
mmc->fpga_type = FPGA_AN505;
25
-armeb_family=arm
32
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
26
+armeb_family=armeb
33
- mmc->scc_id = 0x41040000 | (505 << 4);
27
34
+ mmc->scc_id = 0x41045050;
28
sparc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02'
35
}
29
sparc_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
36
30
@@ -XXX,XX +XXX,XX @@ aarch64_family=arm
37
static const TypeInfo mps2tz_info = {
31
32
aarch64_be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7'
33
aarch64_be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
34
-aarch64_be_family=arm
35
+aarch64_be_family=armeb
36
37
hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f'
38
hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
39
@@ -XXX,XX +XXX,XX @@ qemu_get_family() {
40
ppc64el|ppc64le)
41
echo "ppcle"
42
;;
43
- arm|armel|armhf|arm64|armv[4-9]*)
44
+ arm|armel|armhf|arm64|armv[4-9]*l|aarch64)
45
echo "arm"
46
;;
47
+ armeb|armv[4-9]*b|aarch64_be)
48
+ echo "armeb"
49
+ ;;
50
sparc*)
51
echo "sparc"
52
;;
53
--
38
--
54
2.7.4
39
2.18.0
55
40
56
41
diff view generated by jsdifflib
1
Refactor disas_thumb2_insn() so that it generates the code for raising
1
Untabify the arm translate.c. This affects only some lines,
2
an UNDEF exception for invalid insns, rather than returning a flag
2
mostly comments, in the iwMMXt code. We've never touched
3
which the caller must check to see if it needs to generate the UNDEF
3
that code in years, so it's not going to get fixed up
4
code. This brings the function in to line with the behaviour of
4
by our "change when touched" process, and a bulk change
5
disas_thumb_insn() and disas_arm_insn().
5
is not going to be too disruptive.
6
7
This commit was produced using Emacs "untabify"; it is
8
a whitespace-only change.
6
9
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180821165215.29069-2-peter.maydell@linaro.org
9
Message-id: 1513080506-17703-1-git-send-email-peter.maydell@linaro.org
10
---
12
---
11
target/arm/translate.c | 23 ++++++++++-------------
13
target/arm/translate.c | 122 ++++++++++++++++++++---------------------
12
1 file changed, 10 insertions(+), 13 deletions(-)
14
1 file changed, 61 insertions(+), 61 deletions(-)
13
15
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
18
--- a/target/arm/translate.c
17
+++ b/target/arm/translate.c
19
+++ b/target/arm/translate.c
18
@@ -XXX,XX +XXX,XX @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
20
@@ -XXX,XX +XXX,XX @@ static inline void gen_mov_vreg_F0(int dp, int reg)
19
return 0;
21
tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
20
}
22
}
21
23
22
-/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
24
-#define ARM_CP_RW_BIT    (1 << 20)
23
- is not legal. */
25
+#define ARM_CP_RW_BIT (1 << 20)
24
-static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
26
25
+/* Translate a 32-bit thumb instruction. */
27
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
26
+static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
27
{
28
{
28
uint32_t imm, shift, offset;
29
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
29
uint32_t rd, rn, rm, rs;
30
wrd = insn & 0xf;
30
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
31
rdlo = (insn >> 12) & 0xf;
31
/* UNPREDICTABLE, unallocated hint or
32
rdhi = (insn >> 16) & 0xf;
32
* PLD/PLDW/PLI (literal)
33
- if (insn & ARM_CP_RW_BIT) {            /* TMRRC */
33
*/
34
+ if (insn & ARM_CP_RW_BIT) { /* TMRRC */
34
- return 0;
35
iwmmxt_load_reg(cpu_V0, wrd);
35
+ return;
36
tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
37
tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
38
tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
39
- } else {                    /* TMCRR */
40
+ } else { /* TMCRR */
41
tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
42
iwmmxt_store_reg(cpu_V0, wrd);
43
gen_op_iwmmxt_set_mup();
44
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
45
return 1;
46
}
47
if (insn & ARM_CP_RW_BIT) {
48
- if ((insn >> 28) == 0xf) {            /* WLDRW wCx */
49
+ if ((insn >> 28) == 0xf) { /* WLDRW wCx */
50
tmp = tcg_temp_new_i32();
51
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
52
iwmmxt_store_creg(wrd, tmp);
53
} else {
54
i = 1;
55
if (insn & (1 << 8)) {
56
- if (insn & (1 << 22)) {        /* WLDRD */
57
+ if (insn & (1 << 22)) { /* WLDRD */
58
gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
59
i = 0;
60
- } else {                /* WLDRW wRd */
61
+ } else { /* WLDRW wRd */
62
tmp = tcg_temp_new_i32();
63
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
64
}
65
} else {
66
tmp = tcg_temp_new_i32();
67
- if (insn & (1 << 22)) {        /* WLDRH */
68
+ if (insn & (1 << 22)) { /* WLDRH */
69
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
70
- } else {                /* WLDRB */
71
+ } else { /* WLDRB */
72
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
73
}
36
}
74
}
37
if (op1 & 1) {
75
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
38
- return 0; /* PLD/PLDW/PLI or unallocated hint */
76
gen_op_iwmmxt_movq_wRn_M0(wrd);
39
+ return; /* PLD/PLDW/PLI or unallocated hint */
40
}
41
if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
42
- return 0; /* PLD/PLDW/PLI or unallocated hint */
43
+ return; /* PLD/PLDW/PLI or unallocated hint */
44
}
45
/* UNDEF space, or an UNPREDICTABLE */
46
- return 1;
47
+ goto illegal_op;
48
}
77
}
78
} else {
79
- if ((insn >> 28) == 0xf) {            /* WSTRW wCx */
80
+ if ((insn >> 28) == 0xf) { /* WSTRW wCx */
81
tmp = iwmmxt_load_creg(wrd);
82
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
83
} else {
84
gen_op_iwmmxt_movq_M0_wRn(wrd);
85
tmp = tcg_temp_new_i32();
86
if (insn & (1 << 8)) {
87
- if (insn & (1 << 22)) {        /* WSTRD */
88
+ if (insn & (1 << 22)) { /* WSTRD */
89
gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
90
- } else {                /* WSTRW wRd */
91
+ } else { /* WSTRW wRd */
92
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
93
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
94
}
95
} else {
96
- if (insn & (1 << 22)) {        /* WSTRH */
97
+ if (insn & (1 << 22)) { /* WSTRH */
98
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
99
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
100
- } else {                /* WSTRB */
101
+ } else { /* WSTRB */
102
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
103
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
104
}
105
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
106
return 1;
107
108
switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
109
- case 0x000:                        /* WOR */
110
+ case 0x000: /* WOR */
111
wrd = (insn >> 12) & 0xf;
112
rd0 = (insn >> 0) & 0xf;
113
rd1 = (insn >> 16) & 0xf;
114
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
115
gen_op_iwmmxt_set_mup();
116
gen_op_iwmmxt_set_cup();
117
break;
118
- case 0x011:                        /* TMCR */
119
+ case 0x011: /* TMCR */
120
if (insn & 0xf)
121
return 1;
122
rd = (insn >> 12) & 0xf;
123
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
124
return 1;
49
}
125
}
50
memidx = get_mem_index(s);
126
break;
51
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
127
- case 0x100:                        /* WXOR */
52
default:
128
+ case 0x100: /* WXOR */
53
goto illegal_op;
129
wrd = (insn >> 12) & 0xf;
54
}
130
rd0 = (insn >> 0) & 0xf;
55
- return 0;
131
rd1 = (insn >> 16) & 0xf;
56
+ return;
132
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
57
illegal_op:
133
gen_op_iwmmxt_set_mup();
58
- return 1;
134
gen_op_iwmmxt_set_cup();
59
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
135
break;
60
+ default_exception_el(s));
136
- case 0x111:                        /* TMRC */
61
}
137
+ case 0x111: /* TMRC */
62
138
if (insn & 0xf)
63
static void disas_thumb_insn(DisasContext *s, uint32_t insn)
139
return 1;
64
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
140
rd = (insn >> 12) & 0xf;
65
if (is_16bit) {
141
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
66
disas_thumb_insn(dc, insn);
142
tmp = iwmmxt_load_creg(wrd);
67
} else {
143
store_reg(s, rd, tmp);
68
- if (disas_thumb2_insn(dc, insn)) {
144
break;
69
- gen_exception_insn(dc, 4, EXCP_UDEF, syn_uncategorized(),
145
- case 0x300:                        /* WANDN */
70
- default_exception_el(dc));
146
+ case 0x300: /* WANDN */
71
- }
147
wrd = (insn >> 12) & 0xf;
72
+ disas_thumb2_insn(dc, insn);
148
rd0 = (insn >> 0) & 0xf;
73
}
149
rd1 = (insn >> 16) & 0xf;
74
150
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
75
/* Advance the Thumb condexec condition. */
151
gen_op_iwmmxt_set_mup();
152
gen_op_iwmmxt_set_cup();
153
break;
154
- case 0x200:                        /* WAND */
155
+ case 0x200: /* WAND */
156
wrd = (insn >> 12) & 0xf;
157
rd0 = (insn >> 0) & 0xf;
158
rd1 = (insn >> 16) & 0xf;
159
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
160
gen_op_iwmmxt_set_mup();
161
gen_op_iwmmxt_set_cup();
162
break;
163
- case 0x810: case 0xa10:                /* WMADD */
164
+ case 0x810: case 0xa10: /* WMADD */
165
wrd = (insn >> 12) & 0xf;
166
rd0 = (insn >> 0) & 0xf;
167
rd1 = (insn >> 16) & 0xf;
168
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
169
gen_op_iwmmxt_movq_wRn_M0(wrd);
170
gen_op_iwmmxt_set_mup();
171
break;
172
- case 0x10e: case 0x50e: case 0x90e: case 0xd0e:    /* WUNPCKIL */
173
+ case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
174
wrd = (insn >> 12) & 0xf;
175
rd0 = (insn >> 16) & 0xf;
176
rd1 = (insn >> 0) & 0xf;
177
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
178
gen_op_iwmmxt_set_mup();
179
gen_op_iwmmxt_set_cup();
180
break;
181
- case 0x10c: case 0x50c: case 0x90c: case 0xd0c:    /* WUNPCKIH */
182
+ case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
183
wrd = (insn >> 12) & 0xf;
184
rd0 = (insn >> 16) & 0xf;
185
rd1 = (insn >> 0) & 0xf;
186
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
187
gen_op_iwmmxt_set_mup();
188
gen_op_iwmmxt_set_cup();
189
break;
190
- case 0x012: case 0x112: case 0x412: case 0x512:    /* WSAD */
191
+ case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
192
wrd = (insn >> 12) & 0xf;
193
rd0 = (insn >> 16) & 0xf;
194
rd1 = (insn >> 0) & 0xf;
195
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
196
gen_op_iwmmxt_movq_wRn_M0(wrd);
197
gen_op_iwmmxt_set_mup();
198
break;
199
- case 0x010: case 0x110: case 0x210: case 0x310:    /* WMUL */
200
+ case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
201
wrd = (insn >> 12) & 0xf;
202
rd0 = (insn >> 16) & 0xf;
203
rd1 = (insn >> 0) & 0xf;
204
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
205
gen_op_iwmmxt_movq_wRn_M0(wrd);
206
gen_op_iwmmxt_set_mup();
207
break;
208
- case 0x410: case 0x510: case 0x610: case 0x710:    /* WMAC */
209
+ case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
210
wrd = (insn >> 12) & 0xf;
211
rd0 = (insn >> 16) & 0xf;
212
rd1 = (insn >> 0) & 0xf;
213
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
214
gen_op_iwmmxt_movq_wRn_M0(wrd);
215
gen_op_iwmmxt_set_mup();
216
break;
217
- case 0x006: case 0x406: case 0x806: case 0xc06:    /* WCMPEQ */
218
+ case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
219
wrd = (insn >> 12) & 0xf;
220
rd0 = (insn >> 16) & 0xf;
221
rd1 = (insn >> 0) & 0xf;
222
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
223
gen_op_iwmmxt_set_mup();
224
gen_op_iwmmxt_set_cup();
225
break;
226
- case 0x800: case 0x900: case 0xc00: case 0xd00:    /* WAVG2 */
227
+ case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
228
wrd = (insn >> 12) & 0xf;
229
rd0 = (insn >> 16) & 0xf;
230
rd1 = (insn >> 0) & 0xf;
231
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
232
gen_op_iwmmxt_set_mup();
233
gen_op_iwmmxt_set_cup();
234
break;
235
- case 0x802: case 0x902: case 0xa02: case 0xb02:    /* WALIGNR */
236
+ case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
237
wrd = (insn >> 12) & 0xf;
238
rd0 = (insn >> 16) & 0xf;
239
rd1 = (insn >> 0) & 0xf;
240
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
241
gen_op_iwmmxt_movq_wRn_M0(wrd);
242
gen_op_iwmmxt_set_mup();
243
break;
244
- case 0x601: case 0x605: case 0x609: case 0x60d:    /* TINSR */
245
+ case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
246
if (((insn >> 6) & 3) == 3)
247
return 1;
248
rd = (insn >> 12) & 0xf;
249
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
250
gen_op_iwmmxt_movq_wRn_M0(wrd);
251
gen_op_iwmmxt_set_mup();
252
break;
253
- case 0x107: case 0x507: case 0x907: case 0xd07:    /* TEXTRM */
254
+ case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
255
rd = (insn >> 12) & 0xf;
256
wrd = (insn >> 16) & 0xf;
257
if (rd == 15 || ((insn >> 22) & 3) == 3)
258
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
259
}
260
store_reg(s, rd, tmp);
261
break;
262
- case 0x117: case 0x517: case 0x917: case 0xd17:    /* TEXTRC */
263
+ case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
264
if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
265
return 1;
266
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
267
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
268
gen_set_nzcv(tmp);
269
tcg_temp_free_i32(tmp);
270
break;
271
- case 0x401: case 0x405: case 0x409: case 0x40d:    /* TBCST */
272
+ case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
273
if (((insn >> 6) & 3) == 3)
274
return 1;
275
rd = (insn >> 12) & 0xf;
276
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
277
gen_op_iwmmxt_movq_wRn_M0(wrd);
278
gen_op_iwmmxt_set_mup();
279
break;
280
- case 0x113: case 0x513: case 0x913: case 0xd13:    /* TANDC */
281
+ case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
282
if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
283
return 1;
284
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
285
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
286
tcg_temp_free_i32(tmp2);
287
tcg_temp_free_i32(tmp);
288
break;
289
- case 0x01c: case 0x41c: case 0x81c: case 0xc1c:    /* WACC */
290
+ case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
291
wrd = (insn >> 12) & 0xf;
292
rd0 = (insn >> 16) & 0xf;
293
gen_op_iwmmxt_movq_M0_wRn(rd0);
294
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
295
gen_op_iwmmxt_movq_wRn_M0(wrd);
296
gen_op_iwmmxt_set_mup();
297
break;
298
- case 0x115: case 0x515: case 0x915: case 0xd15:    /* TORC */
299
+ case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
300
if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
301
return 1;
302
tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
303
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
304
tcg_temp_free_i32(tmp2);
305
tcg_temp_free_i32(tmp);
306
break;
307
- case 0x103: case 0x503: case 0x903: case 0xd03:    /* TMOVMSK */
308
+ case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
309
rd = (insn >> 12) & 0xf;
310
rd0 = (insn >> 16) & 0xf;
311
if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
312
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
313
}
314
store_reg(s, rd, tmp);
315
break;
316
- case 0x106: case 0x306: case 0x506: case 0x706:    /* WCMPGT */
317
+ case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
318
case 0x906: case 0xb06: case 0xd06: case 0xf06:
319
wrd = (insn >> 12) & 0xf;
320
rd0 = (insn >> 16) & 0xf;
321
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
322
gen_op_iwmmxt_set_mup();
323
gen_op_iwmmxt_set_cup();
324
break;
325
- case 0x00e: case 0x20e: case 0x40e: case 0x60e:    /* WUNPCKEL */
326
+ case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
327
case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
328
wrd = (insn >> 12) & 0xf;
329
rd0 = (insn >> 16) & 0xf;
330
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
331
gen_op_iwmmxt_set_mup();
332
gen_op_iwmmxt_set_cup();
333
break;
334
- case 0x00c: case 0x20c: case 0x40c: case 0x60c:    /* WUNPCKEH */
335
+ case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
336
case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
337
wrd = (insn >> 12) & 0xf;
338
rd0 = (insn >> 16) & 0xf;
339
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
340
gen_op_iwmmxt_set_mup();
341
gen_op_iwmmxt_set_cup();
342
break;
343
- case 0x204: case 0x604: case 0xa04: case 0xe04:    /* WSRL */
344
+ case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
345
case 0x214: case 0x614: case 0xa14: case 0xe14:
346
if (((insn >> 22) & 3) == 0)
347
return 1;
348
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
349
gen_op_iwmmxt_set_mup();
350
gen_op_iwmmxt_set_cup();
351
break;
352
- case 0x004: case 0x404: case 0x804: case 0xc04:    /* WSRA */
353
+ case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
354
case 0x014: case 0x414: case 0x814: case 0xc14:
355
if (((insn >> 22) & 3) == 0)
356
return 1;
357
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
358
gen_op_iwmmxt_set_mup();
359
gen_op_iwmmxt_set_cup();
360
break;
361
- case 0x104: case 0x504: case 0x904: case 0xd04:    /* WSLL */
362
+ case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
363
case 0x114: case 0x514: case 0x914: case 0xd14:
364
if (((insn >> 22) & 3) == 0)
365
return 1;
366
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
367
gen_op_iwmmxt_set_mup();
368
gen_op_iwmmxt_set_cup();
369
break;
370
- case 0x304: case 0x704: case 0xb04: case 0xf04:    /* WROR */
371
+ case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
372
case 0x314: case 0x714: case 0xb14: case 0xf14:
373
if (((insn >> 22) & 3) == 0)
374
return 1;
375
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
376
gen_op_iwmmxt_set_mup();
377
gen_op_iwmmxt_set_cup();
378
break;
379
- case 0x116: case 0x316: case 0x516: case 0x716:    /* WMIN */
380
+ case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
381
case 0x916: case 0xb16: case 0xd16: case 0xf16:
382
wrd = (insn >> 12) & 0xf;
383
rd0 = (insn >> 16) & 0xf;
384
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
385
gen_op_iwmmxt_movq_wRn_M0(wrd);
386
gen_op_iwmmxt_set_mup();
387
break;
388
- case 0x016: case 0x216: case 0x416: case 0x616:    /* WMAX */
389
+ case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
390
case 0x816: case 0xa16: case 0xc16: case 0xe16:
391
wrd = (insn >> 12) & 0xf;
392
rd0 = (insn >> 16) & 0xf;
393
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
394
gen_op_iwmmxt_movq_wRn_M0(wrd);
395
gen_op_iwmmxt_set_mup();
396
break;
397
- case 0x002: case 0x102: case 0x202: case 0x302:    /* WALIGNI */
398
+ case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
399
case 0x402: case 0x502: case 0x602: case 0x702:
400
wrd = (insn >> 12) & 0xf;
401
rd0 = (insn >> 16) & 0xf;
402
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
403
gen_op_iwmmxt_movq_wRn_M0(wrd);
404
gen_op_iwmmxt_set_mup();
405
break;
406
- case 0x01a: case 0x11a: case 0x21a: case 0x31a:    /* WSUB */
407
+ case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
408
case 0x41a: case 0x51a: case 0x61a: case 0x71a:
409
case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
410
case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
411
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
412
gen_op_iwmmxt_set_mup();
413
gen_op_iwmmxt_set_cup();
414
break;
415
- case 0x01e: case 0x11e: case 0x21e: case 0x31e:    /* WSHUFH */
416
+ case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
417
case 0x41e: case 0x51e: case 0x61e: case 0x71e:
418
case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
419
case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
420
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
421
gen_op_iwmmxt_set_mup();
422
gen_op_iwmmxt_set_cup();
423
break;
424
- case 0x018: case 0x118: case 0x218: case 0x318:    /* WADD */
425
+ case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
426
case 0x418: case 0x518: case 0x618: case 0x718:
427
case 0x818: case 0x918: case 0xa18: case 0xb18:
428
case 0xc18: case 0xd18: case 0xe18: case 0xf18:
429
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
430
gen_op_iwmmxt_set_mup();
431
gen_op_iwmmxt_set_cup();
432
break;
433
- case 0x008: case 0x108: case 0x208: case 0x308:    /* WPACK */
434
+ case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
435
case 0x408: case 0x508: case 0x608: case 0x708:
436
case 0x808: case 0x908: case 0xa08: case 0xb08:
437
case 0xc08: case 0xd08: case 0xe08: case 0xf08:
438
@@ -XXX,XX +XXX,XX @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
439
tmp = load_reg(s, rd0);
440
tmp2 = load_reg(s, rd1);
441
switch ((insn >> 16) & 0xf) {
442
- case 0x0:                    /* TMIA */
443
+ case 0x0: /* TMIA */
444
gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
445
break;
446
- case 0x8:                    /* TMIAPH */
447
+ case 0x8: /* TMIAPH */
448
gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
449
break;
450
- case 0xc: case 0xd: case 0xe: case 0xf:        /* TMIAxy */
451
+ case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
452
if (insn & (1 << 16))
453
tcg_gen_shri_i32(tmp, tmp, 16);
454
if (insn & (1 << 17))
455
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
456
tmp = load_reg(s, rd0);
457
tmp2 = load_reg(s, rd1);
458
switch ((insn >> 16) & 0xf) {
459
- case 0x0:                    /* MIA */
460
+ case 0x0: /* MIA */
461
gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
462
break;
463
- case 0x8:                    /* MIAPH */
464
+ case 0x8: /* MIAPH */
465
gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
466
break;
467
- case 0xc:                    /* MIABB */
468
- case 0xd:                    /* MIABT */
469
- case 0xe:                    /* MIATB */
470
- case 0xf:                    /* MIATT */
471
+ case 0xc: /* MIABB */
472
+ case 0xd: /* MIABT */
473
+ case 0xe: /* MIATB */
474
+ case 0xf: /* MIATT */
475
if (insn & (1 << 16))
476
tcg_gen_shri_i32(tmp, tmp, 16);
477
if (insn & (1 << 17))
478
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
479
if (acc != 0)
480
return 1;
481
482
- if (insn & ARM_CP_RW_BIT) {            /* MRA */
483
+ if (insn & ARM_CP_RW_BIT) { /* MRA */
484
iwmmxt_load_reg(cpu_V0, acc);
485
tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
486
tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
487
tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
488
tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
489
- } else {                    /* MAR */
490
+ } else { /* MAR */
491
tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
492
iwmmxt_store_reg(cpu_V0, acc);
493
}
76
--
494
--
77
2.7.4
495
2.18.0
78
496
79
497
diff view generated by jsdifflib
New patch
1
1
Untabify the arm iwmmxt_helper.c. This affects only the iwMMXt code.
2
We've never touched that code in years, so it's not going to get
3
fixed up by our "change when touched" process, and a bulk change is
4
not going to be too disruptive.
5
6
This commit was produced using Emacs "untabify" (plus one
7
by-hand removal of a space to fix a checkpatch nit); it is
8
a whitespace-only change.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20180821165215.29069-3-peter.maydell@linaro.org
12
---
13
target/arm/iwmmxt_helper.c | 234 ++++++++++++++++++-------------------
14
1 file changed, 117 insertions(+), 117 deletions(-)
15
16
diff --git a/target/arm/iwmmxt_helper.c b/target/arm/iwmmxt_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/iwmmxt_helper.c
19
+++ b/target/arm/iwmmxt_helper.c
20
@@ -XXX,XX +XXX,XX @@
21
/* iwMMXt macros extracted from GNU gdb. */
22
23
/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations. */
24
-#define SIMD8_SET( v, n, b)    ((v != 0) << ((((b) + 1) * 4) + (n)))
25
-#define SIMD16_SET(v, n, h)    ((v != 0) << ((((h) + 1) * 8) + (n)))
26
-#define SIMD32_SET(v, n, w)    ((v != 0) << ((((w) + 1) * 16) + (n)))
27
-#define SIMD64_SET(v, n)    ((v != 0) << (32 + (n)))
28
+#define SIMD8_SET(v, n, b) ((v != 0) << ((((b) + 1) * 4) + (n)))
29
+#define SIMD16_SET(v, n, h) ((v != 0) << ((((h) + 1) * 8) + (n)))
30
+#define SIMD32_SET(v, n, w) ((v != 0) << ((((w) + 1) * 16) + (n)))
31
+#define SIMD64_SET(v, n) ((v != 0) << (32 + (n)))
32
/* Flags to pass as "n" above. */
33
-#define SIMD_NBIT    -1
34
-#define SIMD_ZBIT    -2
35
-#define SIMD_CBIT    -3
36
-#define SIMD_VBIT    -4
37
+#define SIMD_NBIT -1
38
+#define SIMD_ZBIT -2
39
+#define SIMD_CBIT -3
40
+#define SIMD_VBIT -4
41
/* Various status bit macros. */
42
-#define NBIT8(x)    ((x) & 0x80)
43
-#define NBIT16(x)    ((x) & 0x8000)
44
-#define NBIT32(x)    ((x) & 0x80000000)
45
-#define NBIT64(x)    ((x) & 0x8000000000000000ULL)
46
-#define ZBIT8(x)    (((x) & 0xff) == 0)
47
-#define ZBIT16(x)    (((x) & 0xffff) == 0)
48
-#define ZBIT32(x)    (((x) & 0xffffffff) == 0)
49
-#define ZBIT64(x)    (x == 0)
50
+#define NBIT8(x) ((x) & 0x80)
51
+#define NBIT16(x) ((x) & 0x8000)
52
+#define NBIT32(x) ((x) & 0x80000000)
53
+#define NBIT64(x) ((x) & 0x8000000000000000ULL)
54
+#define ZBIT8(x) (((x) & 0xff) == 0)
55
+#define ZBIT16(x) (((x) & 0xffff) == 0)
56
+#define ZBIT32(x) (((x) & 0xffffffff) == 0)
57
+#define ZBIT64(x) (x == 0)
58
/* Sign extension macros. */
59
-#define EXTEND8H(a)    ((uint16_t) (int8_t) (a))
60
-#define EXTEND8(a)    ((uint32_t) (int8_t) (a))
61
-#define EXTEND16(a)    ((uint32_t) (int16_t) (a))
62
-#define EXTEND16S(a)    ((int32_t) (int16_t) (a))
63
-#define EXTEND32(a)    ((uint64_t) (int32_t) (a))
64
+#define EXTEND8H(a) ((uint16_t) (int8_t) (a))
65
+#define EXTEND8(a) ((uint32_t) (int8_t) (a))
66
+#define EXTEND16(a) ((uint32_t) (int16_t) (a))
67
+#define EXTEND16S(a) ((int32_t) (int16_t) (a))
68
+#define EXTEND32(a) ((uint64_t) (int32_t) (a))
69
70
uint64_t HELPER(iwmmxt_maddsq)(uint64_t a, uint64_t b)
71
{
72
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
73
#define NZBIT64(x) \
74
SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
75
SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
76
-#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)            \
77
+#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3) \
78
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUARMState *env, \
79
uint64_t a, uint64_t b) \
80
-{                                \
81
- a =                             \
82
- (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) |    \
83
- (((a >> SH1) & 0xff) << 16) | (((b >> SH1) & 0xff) << 24) |    \
84
- (((a >> SH2) & 0xff) << 32) | (((b >> SH2) & 0xff) << 40) |    \
85
- (((a >> SH3) & 0xff) << 48) | (((b >> SH3) & 0xff) << 56);    \
86
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
87
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) |         \
88
- NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) |        \
89
- NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) |        \
90
- NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);        \
91
+{ \
92
+ a = \
93
+ (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) | \
94
+ (((a >> SH1) & 0xff) << 16) | (((b >> SH1) & 0xff) << 24) | \
95
+ (((a >> SH2) & 0xff) << 32) | (((b >> SH2) & 0xff) << 40) | \
96
+ (((a >> SH3) & 0xff) << 48) | (((b >> SH3) & 0xff) << 56); \
97
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
98
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) | \
99
+ NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) | \
100
+ NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) | \
101
+ NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7); \
102
return a; \
103
-}                                \
104
+} \
105
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUARMState *env, \
106
uint64_t a, uint64_t b) \
107
-{                                \
108
- a =                             \
109
- (((a >> SH0) & 0xffff) << 0) |                \
110
- (((b >> SH0) & 0xffff) << 16) |             \
111
- (((a >> SH2) & 0xffff) << 32) |             \
112
- (((b >> SH2) & 0xffff) << 48);                \
113
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
114
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 16, 1) |        \
115
- NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3);        \
116
+{ \
117
+ a = \
118
+ (((a >> SH0) & 0xffff) << 0) | \
119
+ (((b >> SH0) & 0xffff) << 16) | \
120
+ (((a >> SH2) & 0xffff) << 32) | \
121
+ (((b >> SH2) & 0xffff) << 48); \
122
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
123
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 16, 1) | \
124
+ NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3); \
125
return a; \
126
-}                                \
127
+} \
128
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUARMState *env, \
129
uint64_t a, uint64_t b) \
130
-{                                \
131
- a =                             \
132
- (((a >> SH0) & 0xffffffff) << 0) |            \
133
- (((b >> SH0) & 0xffffffff) << 32);            \
134
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
135
- NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);        \
136
+{ \
137
+ a = \
138
+ (((a >> SH0) & 0xffffffff) << 0) | \
139
+ (((b >> SH0) & 0xffffffff) << 32); \
140
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
141
+ NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1); \
142
return a; \
143
-}                                \
144
+} \
145
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUARMState *env, \
146
uint64_t x) \
147
-{                                \
148
- x =                             \
149
- (((x >> SH0) & 0xff) << 0) |                \
150
- (((x >> SH1) & 0xff) << 16) |                \
151
- (((x >> SH2) & 0xff) << 32) |                \
152
- (((x >> SH3) & 0xff) << 48);                \
153
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
154
- NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) |        \
155
- NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);        \
156
+{ \
157
+ x = \
158
+ (((x >> SH0) & 0xff) << 0) | \
159
+ (((x >> SH1) & 0xff) << 16) | \
160
+ (((x >> SH2) & 0xff) << 32) | \
161
+ (((x >> SH3) & 0xff) << 48); \
162
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
163
+ NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) | \
164
+ NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3); \
165
return x; \
166
-}                                \
167
+} \
168
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUARMState *env, \
169
uint64_t x) \
170
-{                                \
171
- x =                             \
172
- (((x >> SH0) & 0xffff) << 0) |                \
173
- (((x >> SH2) & 0xffff) << 32);                \
174
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
175
- NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);        \
176
+{ \
177
+ x = \
178
+ (((x >> SH0) & 0xffff) << 0) | \
179
+ (((x >> SH2) & 0xffff) << 32); \
180
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
181
+ NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1); \
182
return x; \
183
-}                                \
184
+} \
185
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUARMState *env, \
186
uint64_t x) \
187
-{                                \
188
- x = (((x >> SH0) & 0xffffffff) << 0);            \
189
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);    \
190
+{ \
191
+ x = (((x >> SH0) & 0xffffffff) << 0); \
192
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0); \
193
return x; \
194
-}                                \
195
+} \
196
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUARMState *env, \
197
uint64_t x) \
198
-{                                \
199
- x =                             \
200
- ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) |     \
201
- ((uint64_t) EXTEND8H((x >> SH1) & 0xff) << 16) |    \
202
- ((uint64_t) EXTEND8H((x >> SH2) & 0xff) << 32) |    \
203
- ((uint64_t) EXTEND8H((x >> SH3) & 0xff) << 48);     \
204
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
205
- NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) |        \
206
- NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);        \
207
+{ \
208
+ x = \
209
+ ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) | \
210
+ ((uint64_t) EXTEND8H((x >> SH1) & 0xff) << 16) | \
211
+ ((uint64_t) EXTEND8H((x >> SH2) & 0xff) << 32) | \
212
+ ((uint64_t) EXTEND8H((x >> SH3) & 0xff) << 48); \
213
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
214
+ NZBIT16(x >> 0, 0) | NZBIT16(x >> 16, 1) | \
215
+ NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3); \
216
return x; \
217
-}                                \
218
+} \
219
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUARMState *env, \
220
uint64_t x) \
221
-{                                \
222
- x =                             \
223
- ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) |    \
224
- ((uint64_t) EXTEND16((x >> SH2) & 0xffff) << 32);    \
225
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
226
- NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);        \
227
+{ \
228
+ x = \
229
+ ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) | \
230
+ ((uint64_t) EXTEND16((x >> SH2) & 0xffff) << 32); \
231
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
232
+ NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1); \
233
return x; \
234
-}                                \
235
+} \
236
uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUARMState *env, \
237
uint64_t x) \
238
-{                                \
239
- x = EXTEND32((x >> SH0) & 0xffffffff);            \
240
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);    \
241
+{ \
242
+ x = EXTEND32((x >> SH0) & 0xffffffff); \
243
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0); \
244
return x; \
245
}
246
IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
247
IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
248
249
-#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)            \
250
+#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O) \
251
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUARMState *env, \
252
uint64_t a, uint64_t b) \
253
-{                                \
254
- a =                             \
255
- CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |        \
256
- CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) |        \
257
- CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) |        \
258
- CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff);        \
259
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
260
- NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) |         \
261
- NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) |        \
262
- NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) |        \
263
- NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);        \
264
+{ \
265
+ a = \
266
+ CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) | \
267
+ CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) | \
268
+ CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) | \
269
+ CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff); \
270
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
271
+ NZBIT8(a >> 0, 0) | NZBIT8(a >> 8, 1) | \
272
+ NZBIT8(a >> 16, 2) | NZBIT8(a >> 24, 3) | \
273
+ NZBIT8(a >> 32, 4) | NZBIT8(a >> 40, 5) | \
274
+ NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7); \
275
return a; \
276
-}                                \
277
+} \
278
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUARMState *env, \
279
uint64_t a, uint64_t b) \
280
-{                                \
281
- a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |    \
282
- CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);    \
283
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
284
- NZBIT16(a >> 0, 0) | NZBIT16(a >> 16, 1) |        \
285
- NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3);        \
286
+{ \
287
+ a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) | \
288
+ CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff); \
289
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
290
+ NZBIT16(a >> 0, 0) | NZBIT16(a >> 16, 1) | \
291
+ NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3); \
292
return a; \
293
-}                                \
294
+} \
295
uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUARMState *env, \
296
uint64_t a, uint64_t b) \
297
-{                                \
298
- a = CMP(0, Tl, O, 0xffffffff) |                \
299
- CMP(32, Tl, O, 0xffffffff);                \
300
- env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =            \
301
- NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);        \
302
+{ \
303
+ a = CMP(0, Tl, O, 0xffffffff) | \
304
+ CMP(32, Tl, O, 0xffffffff); \
305
+ env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = \
306
+ NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1); \
307
return a; \
308
}
309
#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((a >> SHR) & MASK) OPER \
310
--
311
2.18.0
312
313
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
Following the bulk conversion of the iwMMXt code, there are
2
just a handful of hard coded tabs in target/arm; fix them.
3
This is a whitespace-only patch.
2
4
3
As we now have a linux-user aarch64_be target, we can add it to the list
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
of supported targets in qemu-binfmt-conf.sh
6
Message-id: 20180821165215.29069-4-peter.maydell@linaro.org
7
---
8
target/arm/cpu.h | 16 ++++++++--------
9
target/arm/arm-semi.c | 2 +-
10
2 files changed, 9 insertions(+), 9 deletions(-)
5
11
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
7
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
13
index XXXXXXX..XXXXXXX 100644
8
Message-id: 20171220212308.12614-6-michael.weiser@gmx.de
14
--- a/target/arm/cpu.h
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
+++ b/target/arm/cpu.h
10
---
16
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
11
scripts/qemu-binfmt-conf.sh | 6 +++++-
17
#define ARM_VFP_FPINST2 10
12
1 file changed, 5 insertions(+), 1 deletion(-)
18
13
19
/* iwMMXt coprocessor control registers. */
14
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
20
-#define ARM_IWMMXT_wCID        0
15
index XXXXXXX..XXXXXXX 100755
21
-#define ARM_IWMMXT_wCon        1
16
--- a/scripts/qemu-binfmt-conf.sh
22
-#define ARM_IWMMXT_wCSSF    2
17
+++ b/scripts/qemu-binfmt-conf.sh
23
-#define ARM_IWMMXT_wCASF    3
18
@@ -XXX,XX +XXX,XX @@
24
-#define ARM_IWMMXT_wCGR0    8
19
25
-#define ARM_IWMMXT_wCGR1    9
20
qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \
26
-#define ARM_IWMMXT_wCGR2    10
21
mips mipsel mipsn32 mipsn32el mips64 mips64el \
27
-#define ARM_IWMMXT_wCGR3    11
22
-sh4 sh4eb s390x aarch64 hppa"
28
+#define ARM_IWMMXT_wCID 0
23
+sh4 sh4eb s390x aarch64 aarch64_be hppa"
29
+#define ARM_IWMMXT_wCon 1
24
30
+#define ARM_IWMMXT_wCSSF 2
25
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
31
+#define ARM_IWMMXT_wCASF 3
26
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
32
+#define ARM_IWMMXT_wCGR0 8
27
@@ -XXX,XX +XXX,XX @@ aarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
33
+#define ARM_IWMMXT_wCGR1 9
28
aarch64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
34
+#define ARM_IWMMXT_wCGR2 10
29
aarch64_family=arm
35
+#define ARM_IWMMXT_wCGR3 11
30
36
31
+aarch64_be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7'
37
/* V7M CCR bits */
32
+aarch64_be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
38
FIELD(V7M_CCR, NONBASETHRDENA, 0, 1)
33
+aarch64_be_family=arm
39
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
34
+
40
index XXXXXXX..XXXXXXX 100644
35
hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f'
41
--- a/target/arm/arm-semi.c
36
hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
42
+++ b/target/arm/arm-semi.c
37
hppa_family=hppa
43
@@ -XXX,XX +XXX,XX @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
44
#ifdef CONFIG_USER_ONLY
45
ts->swi_errno = err;
46
#else
47
-    syscall_err = err;
48
+ syscall_err = err;
49
#endif
50
reg0 = ret;
51
} else {
38
--
52
--
39
2.7.4
53
2.18.0
40
54
41
55
diff view generated by jsdifflib
New patch
1
1
The handling of framebuffer properties in the bcm2835_property code
2
is a bit clumsy, because for each of the many fb related properties
3
we try to track the value we're about to set and whether we're going
4
to be setting a value, and then we hand all the new values off
5
to the framebuffer via a function which takes them all as separate
6
arguments. It would be simpler if the property code could easily
7
copy all the framebuffer's current settings, update them with
8
the new specified values and then ask the framebuffer to switch
9
to the new set.
10
11
As the first part of this refactoring, pull all the fb config
12
settings fields in BCM2835FBState out into their own struct.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20180814144436.679-2-peter.maydell@linaro.org
17
---
18
include/hw/display/bcm2835_fb.h | 26 ++++++--
19
hw/display/bcm2835_fb.c | 114 +++++++++++++++++---------------
20
hw/misc/bcm2835_property.c | 28 ++++----
21
3 files changed, 94 insertions(+), 74 deletions(-)
22
23
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/display/bcm2835_fb.h
26
+++ b/include/hw/display/bcm2835_fb.h
27
@@ -XXX,XX +XXX,XX @@
28
#define TYPE_BCM2835_FB "bcm2835-fb"
29
#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
30
31
+/*
32
+ * Configuration information about the fb which the guest can program
33
+ * via the mailbox property interface.
34
+ */
35
+typedef struct {
36
+ uint32_t xres, yres;
37
+ uint32_t xres_virtual, yres_virtual;
38
+ uint32_t xoffset, yoffset;
39
+ uint32_t bpp;
40
+ uint32_t base;
41
+ uint32_t pixo;
42
+ uint32_t alpha;
43
+} BCM2835FBConfig;
44
+
45
typedef struct {
46
/*< private >*/
47
SysBusDevice busdev;
48
@@ -XXX,XX +XXX,XX @@ typedef struct {
49
qemu_irq mbox_irq;
50
51
bool lock, invalidate, pending;
52
- uint32_t xres, yres;
53
- uint32_t xres_virtual, yres_virtual;
54
- uint32_t xoffset, yoffset;
55
- uint32_t bpp;
56
- uint32_t base, pitch, size;
57
- uint32_t pixo, alpha;
58
+
59
+ BCM2835FBConfig config;
60
+
61
+ /* These are just cached values calculated from the config settings */
62
+ uint32_t size;
63
+ uint32_t pitch;
64
} BCM2835FBState;
65
66
void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
67
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/display/bcm2835_fb.c
70
+++ b/hw/display/bcm2835_fb.c
71
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
72
int bpp = surface_bits_per_pixel(surface);
73
74
while (width--) {
75
- switch (s->bpp) {
76
+ switch (s->config.bpp) {
77
case 8:
78
/* lookup palette starting at video ram base
79
* TODO: cache translation, rather than doing this each time!
80
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
81
break;
82
}
83
84
- if (s->pixo == 0) {
85
+ if (s->config.pixo == 0) {
86
/* swap to BGR pixel format */
87
uint8_t tmp = r;
88
r = b;
89
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
90
int src_width = 0;
91
int dest_width = 0;
92
93
- if (s->lock || !s->xres) {
94
+ if (s->lock || !s->config.xres) {
95
return;
96
}
97
98
- src_width = s->xres * (s->bpp >> 3);
99
- dest_width = s->xres;
100
+ src_width = s->config.xres * (s->config.bpp >> 3);
101
+ dest_width = s->config.xres;
102
103
switch (surface_bits_per_pixel(surface)) {
104
case 0:
105
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
106
}
107
108
if (s->invalidate) {
109
- framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base,
110
- s->yres, src_width);
111
+ framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
112
+ s->config.base,
113
+ s->config.yres, src_width);
114
}
115
116
- framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
117
+ framebuffer_update_display(surface, &s->fbsection,
118
+ s->config.xres, s->config.yres,
119
src_width, dest_width, 0, s->invalidate,
120
draw_line_src16, s, &first, &last);
121
122
if (first >= 0) {
123
- dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1);
124
+ dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
125
}
126
127
s->invalidate = false;
128
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
129
130
s->lock = true;
131
132
- s->xres = ldl_le_phys(&s->dma_as, value);
133
- s->yres = ldl_le_phys(&s->dma_as, value + 4);
134
- s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
135
- s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
136
- s->bpp = ldl_le_phys(&s->dma_as, value + 20);
137
- s->xoffset = ldl_le_phys(&s->dma_as, value + 24);
138
- s->yoffset = ldl_le_phys(&s->dma_as, value + 28);
139
+ s->config.xres = ldl_le_phys(&s->dma_as, value);
140
+ s->config.yres = ldl_le_phys(&s->dma_as, value + 4);
141
+ s->config.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
142
+ s->config.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
143
+ s->config.bpp = ldl_le_phys(&s->dma_as, value + 20);
144
+ s->config.xoffset = ldl_le_phys(&s->dma_as, value + 24);
145
+ s->config.yoffset = ldl_le_phys(&s->dma_as, value + 28);
146
147
- s->base = s->vcram_base | (value & 0xc0000000);
148
- s->base += BCM2835_FB_OFFSET;
149
+ s->config.base = s->vcram_base | (value & 0xc0000000);
150
+ s->config.base += BCM2835_FB_OFFSET;
151
152
/* TODO - Manage properly virtual resolution */
153
154
- s->pitch = s->xres * (s->bpp >> 3);
155
- s->size = s->yres * s->pitch;
156
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
157
+ s->size = s->config.yres * s->pitch;
158
159
stl_le_phys(&s->dma_as, value + 16, s->pitch);
160
- stl_le_phys(&s->dma_as, value + 32, s->base);
161
+ stl_le_phys(&s->dma_as, value + 32, s->config.base);
162
stl_le_phys(&s->dma_as, value + 36, s->size);
163
164
s->invalidate = true;
165
- qemu_console_resize(s->con, s->xres, s->yres);
166
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
167
s->lock = false;
168
}
169
170
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
171
172
/* TODO: input validation! */
173
if (xres) {
174
- s->xres = *xres;
175
+ s->config.xres = *xres;
176
}
177
if (yres) {
178
- s->yres = *yres;
179
+ s->config.yres = *yres;
180
}
181
if (xoffset) {
182
- s->xoffset = *xoffset;
183
+ s->config.xoffset = *xoffset;
184
}
185
if (yoffset) {
186
- s->yoffset = *yoffset;
187
+ s->config.yoffset = *yoffset;
188
}
189
if (bpp) {
190
- s->bpp = *bpp;
191
+ s->config.bpp = *bpp;
192
}
193
if (pixo) {
194
- s->pixo = *pixo;
195
+ s->config.pixo = *pixo;
196
}
197
if (alpha) {
198
- s->alpha = *alpha;
199
+ s->config.alpha = *alpha;
200
}
201
202
/* TODO - Manage properly virtual resolution */
203
204
- s->pitch = s->xres * (s->bpp >> 3);
205
- s->size = s->yres * s->pitch;
206
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
207
+ s->size = s->config.yres * s->pitch;
208
209
s->invalidate = true;
210
- qemu_console_resize(s->con, s->xres, s->yres);
211
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
212
s->lock = false;
213
}
214
215
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_bcm2835_fb = {
216
VMSTATE_BOOL(lock, BCM2835FBState),
217
VMSTATE_BOOL(invalidate, BCM2835FBState),
218
VMSTATE_BOOL(pending, BCM2835FBState),
219
- VMSTATE_UINT32(xres, BCM2835FBState),
220
- VMSTATE_UINT32(yres, BCM2835FBState),
221
- VMSTATE_UINT32(xres_virtual, BCM2835FBState),
222
- VMSTATE_UINT32(yres_virtual, BCM2835FBState),
223
- VMSTATE_UINT32(xoffset, BCM2835FBState),
224
- VMSTATE_UINT32(yoffset, BCM2835FBState),
225
- VMSTATE_UINT32(bpp, BCM2835FBState),
226
- VMSTATE_UINT32(base, BCM2835FBState),
227
+ VMSTATE_UINT32(config.xres, BCM2835FBState),
228
+ VMSTATE_UINT32(config.yres, BCM2835FBState),
229
+ VMSTATE_UINT32(config.xres_virtual, BCM2835FBState),
230
+ VMSTATE_UINT32(config.yres_virtual, BCM2835FBState),
231
+ VMSTATE_UINT32(config.xoffset, BCM2835FBState),
232
+ VMSTATE_UINT32(config.yoffset, BCM2835FBState),
233
+ VMSTATE_UINT32(config.bpp, BCM2835FBState),
234
+ VMSTATE_UINT32(config.base, BCM2835FBState),
235
VMSTATE_UINT32(pitch, BCM2835FBState),
236
VMSTATE_UINT32(size, BCM2835FBState),
237
- VMSTATE_UINT32(pixo, BCM2835FBState),
238
- VMSTATE_UINT32(alpha, BCM2835FBState),
239
+ VMSTATE_UINT32(config.pixo, BCM2835FBState),
240
+ VMSTATE_UINT32(config.alpha, BCM2835FBState),
241
VMSTATE_END_OF_LIST()
242
}
243
};
244
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
245
246
s->pending = false;
247
248
- s->xres_virtual = s->xres;
249
- s->yres_virtual = s->yres;
250
- s->xoffset = 0;
251
- s->yoffset = 0;
252
- s->base = s->vcram_base + BCM2835_FB_OFFSET;
253
- s->pitch = s->xres * (s->bpp >> 3);
254
- s->size = s->yres * s->pitch;
255
+ s->config.xres_virtual = s->config.xres;
256
+ s->config.yres_virtual = s->config.yres;
257
+ s->config.xoffset = 0;
258
+ s->config.yoffset = 0;
259
+ s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
260
+ s->pitch = s->config.xres * (s->config.bpp >> 3);
261
+ s->size = s->config.yres * s->pitch;
262
263
s->invalidate = true;
264
s->lock = false;
265
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
266
bcm2835_fb_reset(dev);
267
268
s->con = graphic_console_init(dev, 0, &vgafb_ops, s);
269
- qemu_console_resize(s->con, s->xres, s->yres);
270
+ qemu_console_resize(s->con, s->config.xres, s->config.yres);
271
}
272
273
static Property bcm2835_fb_props[] = {
274
DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
275
DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
276
DEFAULT_VCRAM_SIZE),
277
- DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640),
278
- DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480),
279
- DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16),
280
- DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */
281
- DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */
282
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, config.xres, 640),
283
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, config.yres, 480),
284
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, config.bpp, 16),
285
+ DEFINE_PROP_UINT32("pixo",
286
+ BCM2835FBState, config.pixo, 1), /* 1=RGB, 0=BGR */
287
+ DEFINE_PROP_UINT32("alpha",
288
+ BCM2835FBState, config.alpha, 2), /* alpha ignored */
289
DEFINE_PROP_END_OF_LIST()
290
};
291
292
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/hw/misc/bcm2835_property.c
295
+++ b/hw/misc/bcm2835_property.c
296
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
297
/* Frame buffer */
298
299
case 0x00040001: /* Allocate buffer */
300
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
301
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
302
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
303
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
304
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->config.base);
305
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
306
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
307
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
308
stl_le_phys(&s->dma_as, value + 16,
309
tmp_xres * tmp_yres * tmp_bpp / 8);
310
resplen = 8;
311
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
312
break;
313
case 0x00040003: /* Get display width/height */
314
case 0x00040004:
315
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
316
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
317
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
318
+ tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
319
stl_le_phys(&s->dma_as, value + 12, tmp_xres);
320
stl_le_phys(&s->dma_as, value + 16, tmp_yres);
321
resplen = 8;
322
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
323
resplen = 8;
324
break;
325
case 0x00040005: /* Get depth */
326
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
327
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
328
stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
329
resplen = 4;
330
break;
331
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
332
resplen = 4;
333
break;
334
case 0x00040006: /* Get pixel order */
335
- tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->pixo;
336
+ tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->config.pixo;
337
stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
338
resplen = 4;
339
break;
340
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
341
resplen = 4;
342
break;
343
case 0x00040007: /* Get alpha */
344
- tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->alpha;
345
+ tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->config.alpha;
346
stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
347
resplen = 4;
348
break;
349
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
350
resplen = 4;
351
break;
352
case 0x00040008: /* Get pitch */
353
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
354
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
355
+ tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
356
+ tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
357
stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
358
resplen = 4;
359
break;
360
case 0x00040009: /* Get virtual offset */
361
- tmp_xoffset = newxoffset != NULL ? *newxoffset : s->fbdev->xoffset;
362
- tmp_yoffset = newyoffset != NULL ? *newyoffset : s->fbdev->yoffset;
363
+ tmp_xoffset = newxoffset != NULL ?
364
+ *newxoffset : s->fbdev->config.xoffset;
365
+ tmp_yoffset = newyoffset != NULL ?
366
+ *newyoffset : s->fbdev->config.yoffset;
367
stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
368
stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
369
resplen = 8;
370
--
371
2.18.0
372
373
diff view generated by jsdifflib
New patch
1
1
Refactor the fb property setting code so that rather than
2
using a set of pointers to local variables to track
3
whether a config value has been updated in the current
4
mbox and if so what its new value is, we just copy
5
all the current settings of the fb at the start, and
6
then update that copy as we go along, before asking
7
the fb to switch to it at the end.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180814144436.679-3-peter.maydell@linaro.org
12
---
13
include/hw/display/bcm2835_fb.h | 4 +-
14
hw/display/bcm2835_fb.c | 27 ++---------
15
hw/misc/bcm2835_property.c | 80 ++++++++++++++-------------------
16
3 files changed, 37 insertions(+), 74 deletions(-)
17
18
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/display/bcm2835_fb.h
21
+++ b/include/hw/display/bcm2835_fb.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
uint32_t pitch;
24
} BCM2835FBState;
25
26
-void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
27
- uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
28
- uint32_t *pixo, uint32_t *alpha);
29
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
30
31
#endif
32
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/display/bcm2835_fb.c
35
+++ b/hw/display/bcm2835_fb.c
36
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
37
s->lock = false;
38
}
39
40
-void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
41
- uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
42
- uint32_t *pixo, uint32_t *alpha)
43
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
44
{
45
s->lock = true;
46
47
/* TODO: input validation! */
48
- if (xres) {
49
- s->config.xres = *xres;
50
- }
51
- if (yres) {
52
- s->config.yres = *yres;
53
- }
54
- if (xoffset) {
55
- s->config.xoffset = *xoffset;
56
- }
57
- if (yoffset) {
58
- s->config.yoffset = *yoffset;
59
- }
60
- if (bpp) {
61
- s->config.bpp = *bpp;
62
- }
63
- if (pixo) {
64
- s->config.pixo = *pixo;
65
- }
66
- if (alpha) {
67
- s->config.alpha = *alpha;
68
- }
69
+
70
+ s->config = *newconfig;
71
72
/* TODO - Manage properly virtual resolution */
73
74
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/misc/bcm2835_property.c
77
+++ b/hw/misc/bcm2835_property.c
78
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
79
uint32_t tmp;
80
int n;
81
uint32_t offset, length, color;
82
- uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
83
- uint32_t tmp_xres, tmp_yres, tmp_xoffset, tmp_yoffset;
84
- uint32_t tmp_bpp, tmp_pixo, tmp_alpha;
85
- uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
86
- *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;
87
+
88
+ /*
89
+ * Copy the current state of the framebuffer config; we will update
90
+ * this copy as we process tags and then ask the framebuffer to use
91
+ * it at the end.
92
+ */
93
+ BCM2835FBConfig fbconfig = s->fbdev->config;
94
+ bool fbconfig_updated = false;
95
96
value &= ~0xf;
97
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
99
/* Frame buffer */
100
101
case 0x00040001: /* Allocate buffer */
102
- stl_le_phys(&s->dma_as, value + 12, s->fbdev->config.base);
103
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
104
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
105
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
106
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
107
stl_le_phys(&s->dma_as, value + 16,
108
- tmp_xres * tmp_yres * tmp_bpp / 8);
109
+ fbconfig.xres * fbconfig.yres * fbconfig.bpp / 8);
110
resplen = 8;
111
break;
112
case 0x00048001: /* Release buffer */
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
114
break;
115
case 0x00040003: /* Get display width/height */
116
case 0x00040004:
117
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
118
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->config.yres;
119
- stl_le_phys(&s->dma_as, value + 12, tmp_xres);
120
- stl_le_phys(&s->dma_as, value + 16, tmp_yres);
121
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
122
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
123
resplen = 8;
124
break;
125
case 0x00044003: /* Test display width/height */
126
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
127
break;
128
case 0x00048003: /* Set display width/height */
129
case 0x00048004:
130
- xres = ldl_le_phys(&s->dma_as, value + 12);
131
- newxres = &xres;
132
- yres = ldl_le_phys(&s->dma_as, value + 16);
133
- newyres = &yres;
134
+ fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
135
+ fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
136
+ fbconfig_updated = true;
137
resplen = 8;
138
break;
139
case 0x00040005: /* Get depth */
140
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
141
- stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
142
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
143
resplen = 4;
144
break;
145
case 0x00044005: /* Test depth */
146
resplen = 4;
147
break;
148
case 0x00048005: /* Set depth */
149
- bpp = ldl_le_phys(&s->dma_as, value + 12);
150
- newbpp = &bpp;
151
+ fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
152
+ fbconfig_updated = true;
153
resplen = 4;
154
break;
155
case 0x00040006: /* Get pixel order */
156
- tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->config.pixo;
157
- stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
158
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
159
resplen = 4;
160
break;
161
case 0x00044006: /* Test pixel order */
162
resplen = 4;
163
break;
164
case 0x00048006: /* Set pixel order */
165
- pixo = ldl_le_phys(&s->dma_as, value + 12);
166
- newpixo = &pixo;
167
+ fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
168
+ fbconfig_updated = true;
169
resplen = 4;
170
break;
171
case 0x00040007: /* Get alpha */
172
- tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->config.alpha;
173
- stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
174
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
175
resplen = 4;
176
break;
177
case 0x00044007: /* Test pixel alpha */
178
resplen = 4;
179
break;
180
case 0x00048007: /* Set alpha */
181
- alpha = ldl_le_phys(&s->dma_as, value + 12);
182
- newalpha = &alpha;
183
+ fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
184
+ fbconfig_updated = true;
185
resplen = 4;
186
break;
187
case 0x00040008: /* Get pitch */
188
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->config.xres;
189
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->config.bpp;
190
- stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
191
+ stl_le_phys(&s->dma_as, value + 12,
192
+ fbconfig.xres * fbconfig.bpp / 8);
193
resplen = 4;
194
break;
195
case 0x00040009: /* Get virtual offset */
196
- tmp_xoffset = newxoffset != NULL ?
197
- *newxoffset : s->fbdev->config.xoffset;
198
- tmp_yoffset = newyoffset != NULL ?
199
- *newyoffset : s->fbdev->config.yoffset;
200
- stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
201
- stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
202
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
203
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
204
resplen = 8;
205
break;
206
case 0x00044009: /* Test virtual offset */
207
resplen = 8;
208
break;
209
case 0x00048009: /* Set virtual offset */
210
- xoffset = ldl_le_phys(&s->dma_as, value + 12);
211
- newxoffset = &xoffset;
212
- yoffset = ldl_le_phys(&s->dma_as, value + 16);
213
- newyoffset = &yoffset;
214
+ fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
215
+ fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
216
+ fbconfig_updated = true;
217
resplen = 8;
218
break;
219
case 0x0004000a: /* Get/Test/Set overscan */
220
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
221
}
222
223
/* Reconfigure framebuffer if required */
224
- if (newxres || newyres || newxoffset || newyoffset || newbpp || newpixo
225
- || newalpha) {
226
- bcm2835_fb_reconfigure(s->fbdev, newxres, newyres, newxoffset,
227
- newyoffset, newbpp, newpixo, newalpha);
228
+ if (fbconfig_updated) {
229
+ bcm2835_fb_reconfigure(s->fbdev, &fbconfig);
230
}
231
232
/* Buffer response code */
233
--
234
2.18.0
235
236
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
The BCM2835FBState struct has a 'pitch' field which is a
2
cached copy of xres * (bpp >> 3), and a 'size' field which is
3
a cached copy of pitch * yres. However we don't actually do
4
anything with these fields; delete them. We retain the
5
now-unused slots in the VMState struct for migration
6
compatibility.
2
7
3
Since for aarch64 the signal trampoline is synthesized directly into the
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
signal frame we need to make sure the instructions end up little-endian.
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Otherwise the wrong endianness will cause a SIGILL upon return from the
10
Message-id: 20180814144436.679-4-peter.maydell@linaro.org
6
signal handler on big-endian targets.
11
---
12
include/hw/display/bcm2835_fb.h | 4 ----
13
hw/display/bcm2835_fb.c | 19 ++++++++-----------
14
2 files changed, 8 insertions(+), 15 deletions(-)
7
15
8
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
16
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20171220212308.12614-4-michael.weiser@gmx.de
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
linux-user/signal.c | 10 +++++++---
14
1 file changed, 7 insertions(+), 3 deletions(-)
15
16
diff --git a/linux-user/signal.c b/linux-user/signal.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/linux-user/signal.c
18
--- a/include/hw/display/bcm2835_fb.h
19
+++ b/linux-user/signal.c
19
+++ b/include/hw/display/bcm2835_fb.h
20
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
20
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
if (ka->sa_flags & TARGET_SA_RESTORER) {
21
bool lock, invalidate, pending;
22
return_addr = ka->sa_restorer;
22
23
} else {
23
BCM2835FBConfig config;
24
- /* mov x8,#__NR_rt_sigreturn; svc #0 */
24
-
25
- __put_user(0xd2801168, &frame->tramp[0]);
25
- /* These are just cached values calculated from the config settings */
26
- __put_user(0xd4000001, &frame->tramp[1]);
26
- uint32_t size;
27
+ /*
27
- uint32_t pitch;
28
+ * mov x8,#__NR_rt_sigreturn; svc #0
28
} BCM2835FBState;
29
+ * Since these are instructions they need to be put as little-endian
29
30
+ * regardless of target default or current CPU endianness.
30
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
31
+ */
31
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
32
+ __put_user_e(0xd2801168, &frame->tramp[0], le);
32
index XXXXXXX..XXXXXXX 100644
33
+ __put_user_e(0xd4000001, &frame->tramp[1], le);
33
--- a/hw/display/bcm2835_fb.c
34
return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
34
+++ b/hw/display/bcm2835_fb.c
35
}
35
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
36
env->xregs[0] = usig;
36
37
static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
38
{
39
+ uint32_t pitch;
40
+ uint32_t size;
41
+
42
value &= ~0xf;
43
44
s->lock = true;
45
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
46
47
/* TODO - Manage properly virtual resolution */
48
49
- s->pitch = s->config.xres * (s->config.bpp >> 3);
50
- s->size = s->config.yres * s->pitch;
51
+ pitch = s->config.xres * (s->config.bpp >> 3);
52
+ size = s->config.yres * pitch;
53
54
- stl_le_phys(&s->dma_as, value + 16, s->pitch);
55
+ stl_le_phys(&s->dma_as, value + 16, pitch);
56
stl_le_phys(&s->dma_as, value + 32, s->config.base);
57
- stl_le_phys(&s->dma_as, value + 36, s->size);
58
+ stl_le_phys(&s->dma_as, value + 36, size);
59
60
s->invalidate = true;
61
qemu_console_resize(s->con, s->config.xres, s->config.yres);
62
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
63
64
/* TODO - Manage properly virtual resolution */
65
66
- s->pitch = s->config.xres * (s->config.bpp >> 3);
67
- s->size = s->config.yres * s->pitch;
68
-
69
s->invalidate = true;
70
qemu_console_resize(s->con, s->config.xres, s->config.yres);
71
s->lock = false;
72
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_bcm2835_fb = {
73
VMSTATE_UINT32(config.yoffset, BCM2835FBState),
74
VMSTATE_UINT32(config.bpp, BCM2835FBState),
75
VMSTATE_UINT32(config.base, BCM2835FBState),
76
- VMSTATE_UINT32(pitch, BCM2835FBState),
77
- VMSTATE_UINT32(size, BCM2835FBState),
78
+ VMSTATE_UNUSED(8), /* Was pitch and size */
79
VMSTATE_UINT32(config.pixo, BCM2835FBState),
80
VMSTATE_UINT32(config.alpha, BCM2835FBState),
81
VMSTATE_END_OF_LIST()
82
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
83
s->config.xoffset = 0;
84
s->config.yoffset = 0;
85
s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
86
- s->pitch = s->config.xres * (s->config.bpp >> 3);
87
- s->size = s->config.yres * s->pitch;
88
89
s->invalidate = true;
90
s->lock = false;
37
--
91
--
38
2.7.4
92
2.18.0
39
93
40
94
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
The bcm2835_fb's initial resolution and other parameters are set
2
via QOM properties. We should reset to those initial values on
3
device reset, which means we need to save the QOM property
4
values somewhere that they are not overwritten by guest
5
changes to the framebuffer configuration.
2
6
3
armeb is missing from the target list in qemu-binfmt-conf.sh. Add it so
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the handler for those binaries gets registered by the script.
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180814144436.679-5-peter.maydell@linaro.org
10
---
11
include/hw/display/bcm2835_fb.h | 1 +
12
hw/display/bcm2835_fb.c | 27 +++++++++++++++------------
13
2 files changed, 16 insertions(+), 12 deletions(-)
5
14
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
15
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
7
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
16
index XXXXXXX..XXXXXXX 100644
8
Message-id: 20171220212308.12614-8-michael.weiser@gmx.de
17
--- a/include/hw/display/bcm2835_fb.h
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
+++ b/include/hw/display/bcm2835_fb.h
10
---
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
11
scripts/qemu-binfmt-conf.sh | 2 +-
20
bool lock, invalidate, pending;
12
1 file changed, 1 insertion(+), 1 deletion(-)
21
13
22
BCM2835FBConfig config;
14
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
23
+ BCM2835FBConfig initial_config;
15
index XXXXXXX..XXXXXXX 100755
24
} BCM2835FBState;
16
--- a/scripts/qemu-binfmt-conf.sh
25
17
+++ b/scripts/qemu-binfmt-conf.sh
26
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
18
@@ -XXX,XX +XXX,XX @@
27
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
19
# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390/HPPA
28
index XXXXXXX..XXXXXXX 100644
20
# program execution by the kernel
29
--- a/hw/display/bcm2835_fb.c
21
30
+++ b/hw/display/bcm2835_fb.c
22
-qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \
31
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_reset(DeviceState *dev)
23
+qemu_target_list="i386 i486 alpha arm armeb sparc32plus ppc ppc64 ppc64le m68k \
32
24
mips mipsel mipsn32 mipsn32el mips64 mips64el \
33
s->pending = false;
25
sh4 sh4eb s390x aarch64 aarch64_be hppa"
34
35
- s->config.xres_virtual = s->config.xres;
36
- s->config.yres_virtual = s->config.yres;
37
- s->config.xoffset = 0;
38
- s->config.yoffset = 0;
39
- s->config.base = s->vcram_base + BCM2835_FB_OFFSET;
40
+ s->config = s->initial_config;
41
42
s->invalidate = true;
43
s->lock = false;
44
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
45
return;
46
}
47
48
+ /* Fill in the parts of initial_config that are not set by QOM properties */
49
+ s->initial_config.xres_virtual = s->initial_config.xres;
50
+ s->initial_config.yres_virtual = s->initial_config.yres;
51
+ s->initial_config.xoffset = 0;
52
+ s->initial_config.yoffset = 0;
53
+ s->initial_config.base = s->vcram_base + BCM2835_FB_OFFSET;
54
+
55
s->dma_mr = MEMORY_REGION(obj);
56
address_space_init(&s->dma_as, s->dma_mr, NULL);
57
58
@@ -XXX,XX +XXX,XX @@ static Property bcm2835_fb_props[] = {
59
DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
60
DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
61
DEFAULT_VCRAM_SIZE),
62
- DEFINE_PROP_UINT32("xres", BCM2835FBState, config.xres, 640),
63
- DEFINE_PROP_UINT32("yres", BCM2835FBState, config.yres, 480),
64
- DEFINE_PROP_UINT32("bpp", BCM2835FBState, config.bpp, 16),
65
- DEFINE_PROP_UINT32("pixo",
66
- BCM2835FBState, config.pixo, 1), /* 1=RGB, 0=BGR */
67
- DEFINE_PROP_UINT32("alpha",
68
- BCM2835FBState, config.alpha, 2), /* alpha ignored */
69
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, initial_config.xres, 640),
70
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, initial_config.yres, 480),
71
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, initial_config.bpp, 16),
72
+ DEFINE_PROP_UINT32("pixo", BCM2835FBState,
73
+ initial_config.pixo, 1), /* 1=RGB, 0=BGR */
74
+ DEFINE_PROP_UINT32("alpha", BCM2835FBState,
75
+ initial_config.alpha, 2), /* alpha ignored */
76
DEFINE_PROP_END_OF_LIST()
77
};
26
78
27
--
79
--
28
2.7.4
80
2.18.0
29
81
30
82
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Abstract out the calculation of the pitch and size of the
2
framebuffer into functions that operate on the BCM2835FBConfig
3
struct -- these are about to get a little more complicated
4
when we add support for virtual and physical sizes differing.
2
5
3
Cc: Peter Maydell <peter.maydell@linaro.org>
4
Cc: Jason Wang <jasowang@redhat.com>
5
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Cc: qemu-devel@nongnu.org
7
Cc: qemu-arm@nongnu.org
8
Cc: yurovsky@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180814144436.679-6-peter.maydell@linaro.org
12
---
9
---
13
hw/net/imx_fec.c | 2 +-
10
include/hw/display/bcm2835_fb.h | 22 ++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
11
hw/display/bcm2835_fb.c | 6 +++---
12
hw/misc/bcm2835_property.c | 4 ++--
13
3 files changed, 27 insertions(+), 5 deletions(-)
15
14
16
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
15
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/imx_fec.c
17
--- a/include/hw/display/bcm2835_fb.h
19
+++ b/hw/net/imx_fec.c
18
+++ b/include/hw/display/bcm2835_fb.h
20
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
size += 2;
20
21
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
22
23
+/**
24
+ * bcm2835_fb_get_pitch: return number of bytes per line of the framebuffer
25
+ * @config: configuration info for the framebuffer
26
+ *
27
+ * Return the number of bytes per line of the framebuffer, ie the number
28
+ * that must be added to a pixel address to get the address of the pixel
29
+ * directly below it on screen.
30
+ */
31
+static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
32
+{
33
+ return config->xres * (config->bpp >> 3);
34
+}
35
+
36
+/**
37
+ * bcm2835_fb_get_size: return total size of framebuffer in bytes
38
+ * @config: configuration info for the framebuffer
39
+ */
40
+static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
41
+{
42
+ return config->yres * bcm2835_fb_get_pitch(config);
43
+}
44
+
45
#endif
46
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/display/bcm2835_fb.c
49
+++ b/hw/display/bcm2835_fb.c
50
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
51
return;
22
}
52
}
23
53
24
- /* Huge frames are truncted. */
54
- src_width = s->config.xres * (s->config.bpp >> 3);
25
+ /* Huge frames are truncated. */
55
+ src_width = bcm2835_fb_get_pitch(&s->config);
26
if (size > s->regs[ENET_FTRL]) {
56
dest_width = s->config.xres;
27
size = s->regs[ENET_FTRL];
57
28
flags |= ENET_BD_TR | ENET_BD_LG;
58
switch (surface_bits_per_pixel(surface)) {
59
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
60
61
/* TODO - Manage properly virtual resolution */
62
63
- pitch = s->config.xres * (s->config.bpp >> 3);
64
- size = s->config.yres * pitch;
65
+ pitch = bcm2835_fb_get_pitch(&s->config);
66
+ size = bcm2835_fb_get_size(&s->config);
67
68
stl_le_phys(&s->dma_as, value + 16, pitch);
69
stl_le_phys(&s->dma_as, value + 32, s->config.base);
70
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/misc/bcm2835_property.c
73
+++ b/hw/misc/bcm2835_property.c
74
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
75
case 0x00040001: /* Allocate buffer */
76
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
77
stl_le_phys(&s->dma_as, value + 16,
78
- fbconfig.xres * fbconfig.yres * fbconfig.bpp / 8);
79
+ bcm2835_fb_get_size(&fbconfig));
80
resplen = 8;
81
break;
82
case 0x00048001: /* Release buffer */
83
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
84
break;
85
case 0x00040008: /* Get pitch */
86
stl_le_phys(&s->dma_as, value + 12,
87
- fbconfig.xres * fbconfig.bpp / 8);
88
+ bcm2835_fb_get_pitch(&fbconfig));
89
resplen = 4;
90
break;
91
case 0x00040009: /* Get virtual offset */
29
--
92
--
30
2.7.4
93
2.18.0
31
94
32
95
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
The raspi framebuffir in bcm2835_fb supports the definition
2
of a virtual "viewport", which is smaller than the full
3
physical framebuffer size and at an adjustable offset within
4
it. Only the viewport area is sent to the screen. This allows
5
the guest to do things like double buffering, or scrolling
6
by adjusting the viewport origin. Currently QEMU doesn't
7
implement this at all.
2
8
3
More recent version of the IP block support more than one Tx DMA ring,
9
Add support for this feature:
4
so add the code implementing that feature.
10
* the property mailbox code needs to distinguish the
11
virtual width/height from the physical width/height
12
* the framebuffer code needs to do something with the
13
virtual width/height/origin information
5
14
6
Cc: Peter Maydell <peter.maydell@linaro.org>
15
Note that the wiki documentation on the semantics of the
7
Cc: Jason Wang <jasowang@redhat.com>
16
virtual and physical height and width has it the wrong way
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
around -- the virtual size is the size of the allocated
9
Cc: qemu-devel@nongnu.org
18
buffer, and the physical size is the size of the display,
10
Cc: qemu-arm@nongnu.org
19
so the virtual size is always the same as or larger than
11
Cc: yurovsky@gmail.com
20
the physical.
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
13
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
22
If the viewport size is set smaller than the physical
23
screen size, we ignore the viewport settings completely
24
and just display the physical screen area.
25
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20180814144436.679-7-peter.maydell@linaro.org
15
---
29
---
16
include/hw/net/imx_fec.h | 18 ++++++-
30
include/hw/display/bcm2835_fb.h | 6 ++++--
17
hw/net/imx_fec.c | 133 ++++++++++++++++++++++++++++++++++++++++-------
31
hw/display/bcm2835_fb.c | 28 ++++++++++++++++++++++------
18
2 files changed, 130 insertions(+), 21 deletions(-)
32
hw/misc/bcm2835_property.c | 21 +++++++++++++++------
33
3 files changed, 41 insertions(+), 14 deletions(-)
19
34
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
35
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
37
--- a/include/hw/display/bcm2835_fb.h
23
+++ b/include/hw/net/imx_fec.h
38
+++ b/include/hw/display/bcm2835_fb.h
24
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
25
#define ENET_TFWR 81
40
*/
26
#define ENET_FRBR 83
41
static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
27
#define ENET_FRSR 84
42
{
28
+#define ENET_TDSR1 89
43
- return config->xres * (config->bpp >> 3);
29
+#define ENET_TDSR2 92
44
+ uint32_t xres = MAX(config->xres, config->xres_virtual);
30
#define ENET_RDSR 96
45
+ return xres * (config->bpp >> 3);
31
#define ENET_TDSR 97
46
}
32
#define ENET_MRBR 98
47
33
@@ -XXX,XX +XXX,XX @@
48
/**
34
#define ENET_FTRL 108
49
@@ -XXX,XX +XXX,XX @@ static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
35
#define ENET_TACC 112
50
*/
36
#define ENET_RACC 113
51
static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
37
+#define ENET_TDAR1 121
52
{
38
+#define ENET_TDAR2 123
53
- return config->yres * bcm2835_fb_get_pitch(config);
39
#define ENET_MIIGSK_CFGR 192
54
+ uint32_t yres = MAX(config->yres, config->yres_virtual);
40
#define ENET_MIIGSK_ENR 194
55
+ return yres * bcm2835_fb_get_pitch(config);
41
#define ENET_ATCR 256
56
}
42
@@ -XXX,XX +XXX,XX @@
57
43
#define ENET_INT_WAKEUP (1 << 17)
58
#endif
44
#define ENET_INT_TS_AVAIL (1 << 16)
59
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
45
#define ENET_INT_TS_TIMER (1 << 15)
46
+#define ENET_INT_TXF2 (1 << 7)
47
+#define ENET_INT_TXB2 (1 << 6)
48
+#define ENET_INT_TXF1 (1 << 3)
49
+#define ENET_INT_TXB1 (1 << 2)
50
51
#define ENET_INT_MAC (ENET_INT_HB | ENET_INT_BABR | ENET_INT_BABT | \
52
ENET_INT_GRA | ENET_INT_TXF | ENET_INT_TXB | \
53
ENET_INT_RXF | ENET_INT_RXB | ENET_INT_MII | \
54
ENET_INT_EBERR | ENET_INT_LC | ENET_INT_RL | \
55
ENET_INT_UN | ENET_INT_PLR | ENET_INT_WAKEUP | \
56
- ENET_INT_TS_AVAIL)
57
+ ENET_INT_TS_AVAIL | ENET_INT_TXF1 | \
58
+ ENET_INT_TXB1 | ENET_INT_TXF2 | ENET_INT_TXB2)
59
60
/* RDAR */
61
#define ENET_RDAR_RDAR (1 << 24)
62
@@ -XXX,XX +XXX,XX @@ typedef struct {
63
64
#define ENET_BD_BDU (1 << 31)
65
66
+#define ENET_TX_RING_NUM 3
67
+
68
+
69
typedef struct IMXFECState {
70
/*< private >*/
71
SysBusDevice parent_obj;
72
@@ -XXX,XX +XXX,XX @@ typedef struct IMXFECState {
73
74
uint32_t regs[ENET_MAX];
75
uint32_t rx_descriptor;
76
- uint32_t tx_descriptor;
77
+
78
+ uint32_t tx_descriptor[ENET_TX_RING_NUM];
79
+ uint32_t tx_ring_num;
80
81
uint32_t phy_status;
82
uint32_t phy_control;
83
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
84
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/net/imx_fec.c
61
--- a/hw/display/bcm2835_fb.c
86
+++ b/hw/net/imx_fec.c
62
+++ b/hw/display/bcm2835_fb.c
87
@@ -XXX,XX +XXX,XX @@ static const char *imx_eth_reg_name(IMXFECState *s, uint32_t index)
63
@@ -XXX,XX +XXX,XX @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
88
}
64
}
89
}
65
}
90
66
91
+/*
67
+static bool fb_use_offsets(BCM2835FBConfig *config)
92
+ * Versions of this device with more than one TX descriptor save the
93
+ * 2nd and 3rd descriptors in a subsection, to maintain migration
94
+ * compatibility with previous versions of the device that only
95
+ * supported a single descriptor.
96
+ */
97
+static bool imx_eth_is_multi_tx_ring(void *opaque)
98
+{
68
+{
99
+ IMXFECState *s = IMX_FEC(opaque);
69
+ /*
100
+
70
+ * Return true if we should use the viewport offsets.
101
+ return s->tx_ring_num > 1;
71
+ * Experimentally, the hardware seems to do this only if the
72
+ * viewport size is larger than the physical screen. (It doesn't
73
+ * prevent the guest setting this silly viewport setting, though...)
74
+ */
75
+ return config->xres_virtual > config->xres &&
76
+ config->yres_virtual > config->yres;
102
+}
77
+}
103
+
78
+
104
+static const VMStateDescription vmstate_imx_eth_txdescs = {
79
static void fb_update_display(void *opaque)
105
+ .name = "imx.fec/txdescs",
106
+ .version_id = 1,
107
+ .minimum_version_id = 1,
108
+ .needed = imx_eth_is_multi_tx_ring,
109
+ .fields = (VMStateField[]) {
110
+ VMSTATE_UINT32(tx_descriptor[1], IMXFECState),
111
+ VMSTATE_UINT32(tx_descriptor[2], IMXFECState),
112
+ VMSTATE_END_OF_LIST()
113
+ }
114
+};
115
+
116
static const VMStateDescription vmstate_imx_eth = {
117
.name = TYPE_IMX_FEC,
118
.version_id = 2,
119
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
120
.fields = (VMStateField[]) {
121
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
122
VMSTATE_UINT32(rx_descriptor, IMXFECState),
123
- VMSTATE_UINT32(tx_descriptor, IMXFECState),
124
-
125
+ VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
126
VMSTATE_UINT32(phy_status, IMXFECState),
127
VMSTATE_UINT32(phy_control, IMXFECState),
128
VMSTATE_UINT32(phy_advertise, IMXFECState),
129
VMSTATE_UINT32(phy_int, IMXFECState),
130
VMSTATE_UINT32(phy_int_mask, IMXFECState),
131
VMSTATE_END_OF_LIST()
132
- }
133
+ },
134
+ .subsections = (const VMStateDescription * []) {
135
+ &vmstate_imx_eth_txdescs,
136
+ NULL
137
+ },
138
};
139
140
#define PHY_INT_ENERGYON (1 << 7)
141
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
142
{
80
{
143
int frame_size = 0, descnt = 0;
81
BCM2835FBState *s = opaque;
144
uint8_t *ptr = s->frame;
82
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
145
- uint32_t addr = s->tx_descriptor;
83
int last = 0;
146
+ uint32_t addr = s->tx_descriptor[0];
84
int src_width = 0;
147
85
int dest_width = 0;
148
while (descnt++ < IMX_MAX_DESC) {
86
+ uint32_t xoff = 0, yoff = 0;
149
IMXFECBufDesc bd;
87
150
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
88
if (s->lock || !s->config.xres) {
151
}
89
return;
152
}
90
}
153
91
154
- s->tx_descriptor = addr;
92
src_width = bcm2835_fb_get_pitch(&s->config);
155
+ s->tx_descriptor[0] = addr;
93
+ if (fb_use_offsets(&s->config)) {
156
94
+ xoff = s->config.xoffset;
157
imx_eth_update(s);
95
+ yoff = s->config.yoffset;
158
}
159
160
-static void imx_enet_do_tx(IMXFECState *s)
161
+static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
162
{
163
int frame_size = 0, descnt = 0;
164
+
165
uint8_t *ptr = s->frame;
166
- uint32_t addr = s->tx_descriptor;
167
+ uint32_t addr, int_txb, int_txf, tdsr;
168
+ size_t ring;
169
+
170
+ switch (index) {
171
+ case ENET_TDAR:
172
+ ring = 0;
173
+ int_txb = ENET_INT_TXB;
174
+ int_txf = ENET_INT_TXF;
175
+ tdsr = ENET_TDSR;
176
+ break;
177
+ case ENET_TDAR1:
178
+ ring = 1;
179
+ int_txb = ENET_INT_TXB1;
180
+ int_txf = ENET_INT_TXF1;
181
+ tdsr = ENET_TDSR1;
182
+ break;
183
+ case ENET_TDAR2:
184
+ ring = 2;
185
+ int_txb = ENET_INT_TXB2;
186
+ int_txf = ENET_INT_TXF2;
187
+ tdsr = ENET_TDSR2;
188
+ break;
189
+ default:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "%s: bogus value for index %x\n",
192
+ __func__, index);
193
+ abort();
194
+ break;
195
+ }
96
+ }
196
+
97
+
197
+ addr = s->tx_descriptor[ring];
98
dest_width = s->config.xres;
198
99
199
while (descnt++ < IMX_MAX_DESC) {
100
switch (surface_bits_per_pixel(surface)) {
200
IMXENETBufDesc bd;
101
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
201
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
202
203
frame_size = 0;
204
if (bd.option & ENET_BD_TX_INT) {
205
- s->regs[ENET_EIR] |= ENET_INT_TXF;
206
+ s->regs[ENET_EIR] |= int_txf;
207
}
208
}
209
if (bd.option & ENET_BD_TX_INT) {
210
- s->regs[ENET_EIR] |= ENET_INT_TXB;
211
+ s->regs[ENET_EIR] |= int_txb;
212
}
213
bd.flags &= ~ENET_BD_R;
214
/* Write back the modified descriptor. */
215
imx_enet_write_bd(&bd, addr);
216
/* Advance to the next descriptor. */
217
if ((bd.flags & ENET_BD_W) != 0) {
218
- addr = s->regs[ENET_TDSR];
219
+ addr = s->regs[tdsr];
220
} else {
221
addr += sizeof(bd);
222
}
223
}
102
}
224
103
225
- s->tx_descriptor = addr;
104
if (s->invalidate) {
226
+ s->tx_descriptor[ring] = addr;
105
+ hwaddr base = s->config.base + xoff + yoff * src_width;
227
106
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
228
imx_eth_update(s);
107
- s->config.base,
229
}
108
+ base,
230
109
s->config.yres, src_width);
231
-static void imx_eth_do_tx(IMXFECState *s)
232
+static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
233
{
234
if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
235
- imx_enet_do_tx(s);
236
+ imx_enet_do_tx(s, index);
237
} else {
238
imx_fec_do_tx(s);
239
}
110
}
240
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
111
112
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
113
draw_line_src16, s, &first, &last);
114
115
if (first >= 0) {
116
- dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
117
+ dpy_gfx_update(s->con, 0, first, s->config.xres,
118
+ last - first + 1);
241
}
119
}
242
120
243
s->rx_descriptor = 0;
121
s->invalidate = false;
244
- s->tx_descriptor = 0;
122
@@ -XXX,XX +XXX,XX @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
245
+ memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
123
s->config.base = s->vcram_base | (value & 0xc0000000);
246
124
s->config.base += BCM2835_FB_OFFSET;
247
/* We also reset the PHY */
125
248
phy_reset(s);
126
- /* TODO - Manage properly virtual resolution */
249
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
127
-
250
unsigned size)
128
pitch = bcm2835_fb_get_pitch(&s->config);
251
{
129
size = bcm2835_fb_get_size(&s->config);
252
IMXFECState *s = IMX_FEC(opaque);
130
253
+ const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s);
131
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
254
uint32_t index = offset >> 2;
132
255
133
s->config = *newconfig;
256
FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
134
257
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
135
- /* TODO - Manage properly virtual resolution */
258
s->regs[index] = 0;
136
-
259
}
137
s->invalidate = true;
260
break;
138
qemu_console_resize(s->con, s->config.xres, s->config.yres);
261
- case ENET_TDAR:
139
s->lock = false;
262
+ case ENET_TDAR1: /* FALLTHROUGH */
140
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
263
+ case ENET_TDAR2: /* FALLTHROUGH */
141
index XXXXXXX..XXXXXXX 100644
264
+ if (unlikely(single_tx_ring)) {
142
--- a/hw/misc/bcm2835_property.c
265
+ qemu_log_mask(LOG_GUEST_ERROR,
143
+++ b/hw/misc/bcm2835_property.c
266
+ "[%s]%s: trying to access TDAR2 or TDAR1\n",
144
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
267
+ TYPE_IMX_FEC, __func__);
145
case 0x00040002: /* Blank screen */
268
+ return;
146
resplen = 4;
269
+ }
147
break;
270
+ case ENET_TDAR: /* FALLTHROUGH */
148
- case 0x00040003: /* Get display width/height */
271
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
149
- case 0x00040004:
272
s->regs[index] = ENET_TDAR_TDAR;
150
+ case 0x00040003: /* Get physical display width/height */
273
- imx_eth_do_tx(s);
151
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
274
+ imx_eth_do_tx(s, index);
152
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
275
}
153
resplen = 8;
276
s->regs[index] = 0;
154
break;
277
break;
155
- case 0x00044003: /* Test display width/height */
278
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
156
- case 0x00044004:
279
if ((s->regs[index] & ENET_ECR_ETHEREN) == 0) {
157
+ case 0x00040004: /* Get virtual display width/height */
280
s->regs[ENET_RDAR] = 0;
158
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
281
s->rx_descriptor = s->regs[ENET_RDSR];
159
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
282
- s->regs[ENET_TDAR] = 0;
160
resplen = 8;
283
- s->tx_descriptor = s->regs[ENET_TDSR];
161
break;
284
+ s->regs[ENET_TDAR] = 0;
162
- case 0x00048003: /* Set display width/height */
285
+ s->regs[ENET_TDAR1] = 0;
163
- case 0x00048004:
286
+ s->regs[ENET_TDAR2] = 0;
164
+ case 0x00044003: /* Test physical display width/height */
287
+ s->tx_descriptor[0] = s->regs[ENET_TDSR];
165
+ case 0x00044004: /* Test virtual display width/height */
288
+ s->tx_descriptor[1] = s->regs[ENET_TDSR1];
166
+ resplen = 8;
289
+ s->tx_descriptor[2] = s->regs[ENET_TDSR2];
167
+ break;
290
}
168
+ case 0x00048003: /* Set physical display width/height */
291
break;
169
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
292
case ENET_MMFR:
170
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
293
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
171
fbconfig_updated = true;
294
} else {
172
resplen = 8;
295
s->regs[index] = value & ~7;
173
break;
296
}
174
+ case 0x00048004: /* Set virtual display width/height */
297
- s->tx_descriptor = s->regs[index];
175
+ fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
298
+ s->tx_descriptor[0] = s->regs[index];
176
+ fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
299
+ break;
177
+ fbconfig_updated = true;
300
+ case ENET_TDSR1:
178
+ resplen = 8;
301
+ if (unlikely(single_tx_ring)) {
179
+ break;
302
+ qemu_log_mask(LOG_GUEST_ERROR,
180
case 0x00040005: /* Get depth */
303
+ "[%s]%s: trying to access TDSR1\n",
181
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
304
+ TYPE_IMX_FEC, __func__);
182
resplen = 4;
305
+ return;
306
+ }
307
+
308
+ s->regs[index] = value & ~7;
309
+ s->tx_descriptor[1] = s->regs[index];
310
+ break;
311
+ case ENET_TDSR2:
312
+ if (unlikely(single_tx_ring)) {
313
+ qemu_log_mask(LOG_GUEST_ERROR,
314
+ "[%s]%s: trying to access TDSR2\n",
315
+ TYPE_IMX_FEC, __func__);
316
+ return;
317
+ }
318
+
319
+ s->regs[index] = value & ~7;
320
+ s->tx_descriptor[2] = s->regs[index];
321
break;
322
case ENET_MRBR:
323
s->regs[index] = value & 0x00003ff0;
324
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
325
326
static Property imx_eth_properties[] = {
327
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
328
+ DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
329
DEFINE_PROP_END_OF_LIST(),
330
};
331
332
--
183
--
333
2.7.4
184
2.18.0
334
185
335
186
diff view generated by jsdifflib
New patch
1
1
Validate the config settings that the guest tries to set.
2
3
The wiki page documentation is not really accurate here:
4
generally rather than failing requests to set bad parameters,
5
the hardware will just clip them to something sensible.
6
7
Validate the most important parameters: sizes and
8
the viewport offsets. This prevents the framebuffer
9
code from trying to read out-of-range memory.
10
11
In the property handling code, we validate the new parameters every
12
time we encounter a tag that sets them. This means we validate the
13
config multiple times if the request includes multiple config-setting
14
tags, but the code would require significant restructuring to do a
15
validation only once but still return the clipped settings for
16
get-parameter tags and the buffer allocation tag.
17
18
Validation of settings made via the older bcm2835_fb_mbox_push()
19
function will be done in the next commit.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20180814144436.679-8-peter.maydell@linaro.org
24
---
25
include/hw/display/bcm2835_fb.h | 8 +++++
26
hw/display/bcm2835_fb.c | 48 +++++++++++++++++++++++++++--
27
hw/misc/bcm2835_property.c | 54 ++++++++++++++++-----------------
28
3 files changed, 81 insertions(+), 29 deletions(-)
29
30
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/display/bcm2835_fb.h
33
+++ b/include/hw/display/bcm2835_fb.h
34
@@ -XXX,XX +XXX,XX @@ static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
35
return yres * bcm2835_fb_get_pitch(config);
36
}
37
38
+/**
39
+ * bcm2835_fb_validate_config: check provided config
40
+ *
41
+ * Validates the configuration information provided by the guest and
42
+ * adjusts it if necessary.
43
+ */
44
+void bcm2835_fb_validate_config(BCM2835FBConfig *config);
45
+
46
#endif
47
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/display/bcm2835_fb.c
50
+++ b/hw/display/bcm2835_fb.c
51
@@ -XXX,XX +XXX,XX @@
52
#define DEFAULT_VCRAM_SIZE 0x4000000
53
#define BCM2835_FB_OFFSET 0x00100000
54
55
+/* Maximum permitted framebuffer size; experimentally determined on an rpi2 */
56
+#define XRES_MAX 3840
57
+#define YRES_MAX 2560
58
+/* Framebuffer size used if guest requests zero size */
59
+#define XRES_SMALL 592
60
+#define YRES_SMALL 488
61
+
62
static void fb_invalidate_display(void *opaque)
63
{
64
BCM2835FBState *s = BCM2835_FB(opaque);
65
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
66
s->invalidate = false;
67
}
68
69
+void bcm2835_fb_validate_config(BCM2835FBConfig *config)
70
+{
71
+ /*
72
+ * Validate the config, and clip any bogus values into range,
73
+ * as the hardware does. Note that fb_update_display() relies on
74
+ * this happening to prevent it from performing out-of-range
75
+ * accesses on redraw.
76
+ */
77
+ config->xres = MIN(config->xres, XRES_MAX);
78
+ config->xres_virtual = MIN(config->xres_virtual, XRES_MAX);
79
+ config->yres = MIN(config->yres, YRES_MAX);
80
+ config->yres_virtual = MIN(config->yres_virtual, YRES_MAX);
81
+
82
+ /*
83
+ * These are not minima: a 40x40 framebuffer will be accepted.
84
+ * They're only used as defaults if the guest asks for zero size.
85
+ */
86
+ if (config->xres == 0) {
87
+ config->xres = XRES_SMALL;
88
+ }
89
+ if (config->yres == 0) {
90
+ config->yres = YRES_SMALL;
91
+ }
92
+ if (config->xres_virtual == 0) {
93
+ config->xres_virtual = config->xres;
94
+ }
95
+ if (config->yres_virtual == 0) {
96
+ config->yres_virtual = config->yres;
97
+ }
98
+
99
+ if (fb_use_offsets(config)) {
100
+ /* Clip the offsets so the viewport is within the physical screen */
101
+ config->xoffset = MIN(config->xoffset,
102
+ config->xres_virtual - config->xres);
103
+ config->yoffset = MIN(config->yoffset,
104
+ config->yres_virtual - config->yres);
105
+ }
106
+}
107
+
108
static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
109
{
110
uint32_t pitch;
111
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
112
{
113
s->lock = true;
114
115
- /* TODO: input validation! */
116
-
117
s->config = *newconfig;
118
119
s->invalidate = true;
120
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/misc/bcm2835_property.c
123
+++ b/hw/misc/bcm2835_property.c
124
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
125
case 0x00040002: /* Blank screen */
126
resplen = 4;
127
break;
128
- case 0x00040003: /* Get physical display width/height */
129
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
130
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
131
- resplen = 8;
132
- break;
133
- case 0x00040004: /* Get virtual display width/height */
134
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
135
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
136
- resplen = 8;
137
- break;
138
case 0x00044003: /* Test physical display width/height */
139
case 0x00044004: /* Test virtual display width/height */
140
resplen = 8;
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
142
case 0x00048003: /* Set physical display width/height */
143
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
144
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
145
+ bcm2835_fb_validate_config(&fbconfig);
146
fbconfig_updated = true;
147
+ /* fall through */
148
+ case 0x00040003: /* Get physical display width/height */
149
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
150
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
151
resplen = 8;
152
break;
153
case 0x00048004: /* Set virtual display width/height */
154
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
155
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
156
+ bcm2835_fb_validate_config(&fbconfig);
157
fbconfig_updated = true;
158
+ /* fall through */
159
+ case 0x00040004: /* Get virtual display width/height */
160
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
161
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
162
resplen = 8;
163
break;
164
- case 0x00040005: /* Get depth */
165
- stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
166
- resplen = 4;
167
- break;
168
case 0x00044005: /* Test depth */
169
resplen = 4;
170
break;
171
case 0x00048005: /* Set depth */
172
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
173
+ bcm2835_fb_validate_config(&fbconfig);
174
fbconfig_updated = true;
175
- resplen = 4;
176
- break;
177
- case 0x00040006: /* Get pixel order */
178
- stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
179
+ /* fall through */
180
+ case 0x00040005: /* Get depth */
181
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
182
resplen = 4;
183
break;
184
case 0x00044006: /* Test pixel order */
185
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
186
break;
187
case 0x00048006: /* Set pixel order */
188
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
189
+ bcm2835_fb_validate_config(&fbconfig);
190
fbconfig_updated = true;
191
- resplen = 4;
192
- break;
193
- case 0x00040007: /* Get alpha */
194
- stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
195
+ /* fall through */
196
+ case 0x00040006: /* Get pixel order */
197
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
198
resplen = 4;
199
break;
200
case 0x00044007: /* Test pixel alpha */
201
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
202
break;
203
case 0x00048007: /* Set alpha */
204
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
205
+ bcm2835_fb_validate_config(&fbconfig);
206
fbconfig_updated = true;
207
+ /* fall through */
208
+ case 0x00040007: /* Get alpha */
209
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
210
resplen = 4;
211
break;
212
case 0x00040008: /* Get pitch */
213
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
214
bcm2835_fb_get_pitch(&fbconfig));
215
resplen = 4;
216
break;
217
- case 0x00040009: /* Get virtual offset */
218
- stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
219
- stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
220
- resplen = 8;
221
- break;
222
case 0x00044009: /* Test virtual offset */
223
resplen = 8;
224
break;
225
case 0x00048009: /* Set virtual offset */
226
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
227
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
228
+ bcm2835_fb_validate_config(&fbconfig);
229
fbconfig_updated = true;
230
+ /* fall through */
231
+ case 0x00040009: /* Get virtual offset */
232
+ stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
233
+ stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
234
resplen = 8;
235
break;
236
case 0x0004000a: /* Get/Test/Set overscan */
237
--
238
2.18.0
239
240
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Refactor bcm2835_fb_mbox_push() to work by calling
2
bcm2835_fb_validate_config() and bcm2835_fb_reconfigure(),
3
so that config set this way is also validated.
2
4
3
In current implementation, packet queue flushing logic seem to suffer
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
from a deadlock like scenario if a packet is received by the interface
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
before before Rx ring is initialized by Guest's driver. Consider the
7
Message-id: 20180814144436.679-9-peter.maydell@linaro.org
6
following sequence of events:
8
---
9
hw/display/bcm2835_fb.c | 63 ++++++++++++++++++++---------------------
10
1 file changed, 31 insertions(+), 32 deletions(-)
7
11
8
    1. A QEMU instance is started against a TAP device on Linux
12
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
9
     host, running Linux guest, e. g., something to the effect
10
     of:
11
12
     qemu-system-arm \
13
     -net nic,model=imx.fec,netdev=lan0 \
14
     netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
15
     ... rest of the arguments ...
16
17
    2. Once QEMU starts, but before guest reaches the point where
18
     FEC deriver is done initializing the HW, Guest, via TAP
19
     interface, receives a number of multicast MDNS packets from
20
     Host (not necessarily true for every OS, but it happens at
21
     least on Fedora 25)
22
23
    3. Recieving a packet in such a state results in
24
     imx_eth_can_receive() returning '0', which in turn causes
25
     tap_send() to disable corresponding event (tap.c:203)
26
27
    4. Once Guest's driver reaches the point where it is ready to
28
     recieve packets it prepares Rx ring descriptors and writes
29
     ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
30
     more descriptors are ready. And at this points emulation
31
     layer does this:
32
33
          s->regs[index] = ENET_RDAR_RDAR;
34
imx_eth_enable_rx(s);
35
36
     which, combined with:
37
38
          if (!s->regs[ENET_RDAR]) {
39
         qemu_flush_queued_packets(qemu_get_queue(s->nic));
40
         }
41
42
     results in Rx queue never being flushed and corresponding
43
     I/O event beign disabled.
44
45
To prevent the problem, change the code to always flush packet queue
46
when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.
47
48
Cc: Peter Maydell <peter.maydell@linaro.org>
49
Cc: Jason Wang <jasowang@redhat.com>
50
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
51
Cc: qemu-devel@nongnu.org
52
Cc: qemu-arm@nongnu.org
53
Cc: yurovsky@gmail.com
54
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
55
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
56
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
57
---
58
hw/net/imx_fec.c | 12 ++++++------
59
1 file changed, 6 insertions(+), 6 deletions(-)
60
61
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
62
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/net/imx_fec.c
14
--- a/hw/display/bcm2835_fb.c
64
+++ b/hw/net/imx_fec.c
15
+++ b/hw/display/bcm2835_fb.c
65
@@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s)
16
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_validate_config(BCM2835FBConfig *config)
66
}
17
}
67
}
18
}
68
19
69
-static void imx_eth_enable_rx(IMXFECState *s)
20
-static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
70
+static void imx_eth_enable_rx(IMXFECState *s, bool flush)
21
-{
22
- uint32_t pitch;
23
- uint32_t size;
24
-
25
- value &= ~0xf;
26
-
27
- s->lock = true;
28
-
29
- s->config.xres = ldl_le_phys(&s->dma_as, value);
30
- s->config.yres = ldl_le_phys(&s->dma_as, value + 4);
31
- s->config.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
32
- s->config.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
33
- s->config.bpp = ldl_le_phys(&s->dma_as, value + 20);
34
- s->config.xoffset = ldl_le_phys(&s->dma_as, value + 24);
35
- s->config.yoffset = ldl_le_phys(&s->dma_as, value + 28);
36
-
37
- s->config.base = s->vcram_base | (value & 0xc0000000);
38
- s->config.base += BCM2835_FB_OFFSET;
39
-
40
- pitch = bcm2835_fb_get_pitch(&s->config);
41
- size = bcm2835_fb_get_size(&s->config);
42
-
43
- stl_le_phys(&s->dma_as, value + 16, pitch);
44
- stl_le_phys(&s->dma_as, value + 32, s->config.base);
45
- stl_le_phys(&s->dma_as, value + 36, size);
46
-
47
- s->invalidate = true;
48
- qemu_console_resize(s->con, s->config.xres, s->config.yres);
49
- s->lock = false;
50
-}
51
-
52
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
71
{
53
{
72
IMXFECBufDesc bd;
54
s->lock = true;
73
bool rx_ring_full;
55
@@ -XXX,XX +XXX,XX @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
74
@@ -XXX,XX +XXX,XX @@ static void imx_eth_enable_rx(IMXFECState *s)
56
s->lock = false;
75
76
if (rx_ring_full) {
77
FEC_PRINTF("RX buffer full\n");
78
- } else if (!s->regs[ENET_RDAR]) {
79
+ } else if (flush) {
80
qemu_flush_queued_packets(qemu_get_queue(s->nic));
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
84
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
85
if (!s->regs[index]) {
86
s->regs[index] = ENET_RDAR_RDAR;
87
- imx_eth_enable_rx(s);
88
+ imx_eth_enable_rx(s, true);
89
}
90
} else {
91
s->regs[index] = 0;
92
@@ -XXX,XX +XXX,XX @@ static int imx_eth_can_receive(NetClientState *nc)
93
94
FEC_PRINTF("\n");
95
96
- return s->regs[ENET_RDAR] ? 1 : 0;
97
+ return !!s->regs[ENET_RDAR];
98
}
57
}
99
58
100
static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
59
+static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
101
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
60
+{
102
}
61
+ uint32_t pitch;
103
}
62
+ uint32_t size;
104
s->rx_descriptor = addr;
63
+ BCM2835FBConfig newconf;
105
- imx_eth_enable_rx(s);
64
+
106
+ imx_eth_enable_rx(s, false);
65
+ value &= ~0xf;
107
imx_eth_update(s);
66
+
108
return len;
67
+ newconf.xres = ldl_le_phys(&s->dma_as, value);
109
}
68
+ newconf.yres = ldl_le_phys(&s->dma_as, value + 4);
110
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
69
+ newconf.xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
111
}
70
+ newconf.yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
112
}
71
+ newconf.bpp = ldl_le_phys(&s->dma_as, value + 20);
113
s->rx_descriptor = addr;
72
+ newconf.xoffset = ldl_le_phys(&s->dma_as, value + 24);
114
- imx_eth_enable_rx(s);
73
+ newconf.yoffset = ldl_le_phys(&s->dma_as, value + 28);
115
+ imx_eth_enable_rx(s, false);
74
+
116
imx_eth_update(s);
75
+ newconf.base = s->vcram_base | (value & 0xc0000000);
117
return len;
76
+ newconf.base += BCM2835_FB_OFFSET;
118
}
77
+
78
+ bcm2835_fb_validate_config(&newconf);
79
+
80
+ pitch = bcm2835_fb_get_pitch(&newconf);
81
+ size = bcm2835_fb_get_size(&newconf);
82
+
83
+ stl_le_phys(&s->dma_as, value + 16, pitch);
84
+ stl_le_phys(&s->dma_as, value + 32, newconf.base);
85
+ stl_le_phys(&s->dma_as, value + 36, size);
86
+
87
+ bcm2835_fb_reconfigure(s, &newconf);
88
+}
89
+
90
static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size)
91
{
92
BCM2835FBState *s = opaque;
119
--
93
--
120
2.7.4
94
2.18.0
121
95
122
96
diff view generated by jsdifflib
1
The GICv3 specification says that reserved register addresses
1
Fix MPS2 SCC config register values for the mps2-an511
2
should RAZ/WI. This means we need to return MEMTX_OK, not MEMTX_ERROR,
2
and mps2-an385 boards:
3
because now that we support generating external aborts the
3
* the SCC_AID bits [23:20] specify the FPGA build target board revision,
4
latter will cause an abort on new board models.
4
and the SCC_CFG4 register specifies the actual board revision, so
5
these should have matching values. Claim to be board revision C,
6
consistently -- we had the revision in the wrong part of SCC_AID.
7
* SCC_ID bits [15:4] should be the board number in hex, not decimal
5
8
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1513183941-24300-2-git-send-email-peter.maydell@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
11
Message-id: 20180823175225.22612-1-peter.maydell@linaro.org
10
---
12
---
11
hw/intc/arm_gicv3_dist.c | 13 +++++++++++++
13
hw/arm/mps2.c | 6 +++---
12
hw/intc/arm_gicv3_its_common.c | 8 +++-----
14
1 file changed, 3 insertions(+), 3 deletions(-)
13
hw/intc/arm_gicv3_redist.c | 13 +++++++++++++
14
3 files changed, 29 insertions(+), 5 deletions(-)
15
15
16
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
16
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/arm_gicv3_dist.c
18
--- a/hw/arm/mps2.c
19
+++ b/hw/intc/arm_gicv3_dist.c
19
+++ b/hw/arm/mps2.c
20
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
20
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
21
"%s: invalid guest read at offset " TARGET_FMT_plx
21
sccdev = DEVICE(&mms->scc);
22
"size %u\n", __func__, offset, size);
22
qdev_set_parent_bus(sccdev, sysbus_get_default());
23
trace_gicv3_dist_badread(offset, size, attrs.secure);
23
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
24
+ /* The spec requires that reserved registers are RAZ/WI;
24
- qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
25
+ * so use MEMTX_ERROR returns from leaf functions as a way to
25
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
26
+ * trigger the guest-error logging but don't return it to
26
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
27
+ * the caller, or we'll cause a spurious guest data abort.
27
object_property_set_bool(OBJECT(&mms->scc), true, "realized",
28
+ */
28
&error_fatal);
29
+ r = MEMTX_OK;
29
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
30
+ *data = 0;
30
mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
31
} else {
31
mmc->fpga_type = FPGA_AN385;
32
trace_gicv3_dist_read(offset, *data, size, attrs.secure);
32
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
33
}
33
- mmc->scc_id = 0x41040000 | (385 << 4);
34
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
34
+ mmc->scc_id = 0x41043850;
35
"%s: invalid guest write at offset " TARGET_FMT_plx
36
"size %u\n", __func__, offset, size);
37
trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
38
+ /* The spec requires that reserved registers are RAZ/WI;
39
+ * so use MEMTX_ERROR returns from leaf functions as a way to
40
+ * trigger the guest-error logging but don't return it to
41
+ * the caller, or we'll cause a spurious guest data abort.
42
+ */
43
+ r = MEMTX_OK;
44
} else {
45
trace_gicv3_dist_write(offset, data, size, attrs.secure);
46
}
47
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/intc/arm_gicv3_its_common.c
50
+++ b/hw/intc/arm_gicv3_its_common.c
51
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
52
MemTxAttrs attrs)
53
{
54
qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
55
- return MEMTX_ERROR;
56
+ *data = 0;
57
+ return MEMTX_OK;
58
}
35
}
59
36
60
static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
37
static void mps2_an511_class_init(ObjectClass *oc, void *data)
61
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
38
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
62
if (ret <= 0) {
39
mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
63
qemu_log_mask(LOG_GUEST_ERROR,
40
mmc->fpga_type = FPGA_AN511;
64
"ITS: Error sending MSI: %s\n", strerror(-ret));
41
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
65
- return MEMTX_DECODE_ERROR;
42
- mmc->scc_id = 0x4104000 | (511 << 4);
66
}
43
+ mmc->scc_id = 0x41045110;
67
-
68
- return MEMTX_OK;
69
} else {
70
qemu_log_mask(LOG_GUEST_ERROR,
71
"ITS write at bad offset 0x%"PRIx64"\n", offset);
72
- return MEMTX_DECODE_ERROR;
73
}
74
+ return MEMTX_OK;
75
}
44
}
76
45
77
static const MemoryRegionOps gicv3_its_trans_ops = {
46
static const TypeInfo mps2_info = {
78
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/intc/arm_gicv3_redist.c
81
+++ b/hw/intc/arm_gicv3_redist.c
82
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
83
"size %u\n", __func__, offset, size);
84
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
85
size, attrs.secure);
86
+ /* The spec requires that reserved registers are RAZ/WI;
87
+ * so use MEMTX_ERROR returns from leaf functions as a way to
88
+ * trigger the guest-error logging but don't return it to
89
+ * the caller, or we'll cause a spurious guest data abort.
90
+ */
91
+ r = MEMTX_OK;
92
+ *data = 0;
93
} else {
94
trace_gicv3_redist_read(gicv3_redist_affid(cs), offset, *data,
95
size, attrs.secure);
96
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
97
"size %u\n", __func__, offset, size);
98
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
99
size, attrs.secure);
100
+ /* The spec requires that reserved registers are RAZ/WI;
101
+ * so use MEMTX_ERROR returns from leaf functions as a way to
102
+ * trigger the guest-error logging but don't return it to
103
+ * the caller, or we'll cause a spurious guest data abort.
104
+ */
105
+ r = MEMTX_OK;
106
} else {
107
trace_gicv3_redist_write(gicv3_redist_affid(cs), offset, data,
108
size, attrs.secure);
109
--
47
--
110
2.7.4
48
2.18.0
111
49
112
50
diff view generated by jsdifflib