1
target-arm queue. The big thing here is the landing of the 3-phase
1
First pullreq for 6.0: mostly my v8.1M work, plus some other
2
reset patches...
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
3
4
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit 204aa60b37c23a89e690d418f49787d274303ca7:
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
7
9
8
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jan-29-2020' into staging (2020-01-30 14:18:45 +0000)
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
9
11
10
are available in the Git repository at:
12
are available in the Git repository at:
11
13
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200130
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
13
15
14
for you to fetch changes up to dea101a1ae9968c9fec6ab0291489dad7c49f36f:
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
15
17
16
target/arm/cpu: Add the kvm-no-adjvtime CPU property (2020-01-30 16:02:06 +0000)
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
21
* target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
22
* aspeed: some minor bugfixes
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
23
* aspeed: add eMMC controller model for AST2600 SoC
25
* Various minor code cleanups
24
* hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
25
* New 3-phase reset API for device models
27
* Implement more pieces of ARMv8.1M support
26
* hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
27
* Arm KVM: stop/restart the guest counter when the VM is stopped and started
28
28
29
----------------------------------------------------------------
29
----------------------------------------------------------------
30
Andrew Jeffery (2):
30
Alex Chen (4):
31
hw/sd: Configure number of slots exposed by the ASPEED SDHCI model
31
i.MX25: Fix bad printf format specifiers
32
hw/arm: ast2600: Wire up the eMMC controller
32
i.MX31: Fix bad printf format specifiers
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
33
35
34
Andrew Jones (6):
36
Havard Skinnemoen (1):
35
target/arm/kvm: trivial: Clean up header documentation
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
36
hw/arm/virt: Add missing 5.0 options call to 4.2 options
37
target/arm/kvm64: kvm64 cpus have timer registers
38
tests/arm-cpu-features: Check feature default values
39
target/arm/kvm: Implement virtual time adjustment
40
target/arm/cpu: Add the kvm-no-adjvtime CPU property
41
38
42
Cédric Le Goater (2):
39
Kunkun Jiang (1):
43
ftgmac100: check RX and TX buffer alignment
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
44
hw/arm/aspeed: add a 'execute-in-place' property to boot directly from CE0
45
41
46
Damien Hedde (11):
42
Marcin Juszkiewicz (1):
47
add device_legacy_reset function to prepare for reset api change
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
48
hw/core/qdev: add trace events to help with resettable transition
49
hw/core: create Resettable QOM interface
50
hw/core: add Resettable support to BusClass and DeviceClass
51
hw/core/resettable: add support for changing parent
52
hw/core/qdev: handle parent bus change regarding resettable
53
hw/core/qdev: update hotplug reset regarding resettable
54
hw/core: deprecate old reset functions and introduce new ones
55
docs/devel/reset.rst: add doc about Resettable interface
56
vl: replace deprecated qbus_reset_all registration
57
hw/s390x/ipl: replace deprecated qdev_reset_all registration
58
44
59
Joel Stanley (1):
45
Peter Maydell (25):
60
misc/pca9552: Add qom set and get
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
47
target/arm: Implement v8.1M PXN extension
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
49
target/arm: Implement VSCCLRM insn
50
target/arm: Implement CLRM instruction
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
52
target/arm: Refactor M-profile VMSR/VMRS handling
53
target/arm: Move general-use constant expanders up in translate.c
54
target/arm: Implement VLDR/VSTR system register
55
target/arm: Implement M-profile FPSCR_nzcvqc
56
target/arm: Use new FPCR_NZCV_MASK constant
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
58
target/arm: Implement FPCXT_S fp system register
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
61
71
62
Peter Maydell (2):
72
Vikram Garhwal (4):
63
hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
64
target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
65
77
66
Philippe Mathieu-Daudé (1):
78
meson.build | 1 +
67
hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
79
hw/arm/smmuv3-internal.h | 2 +-
80
hw/net/can/trace.h | 1 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
68
118
69
Zenghui Yu (1):
70
hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
71
72
hw/core/Makefile.objs | 1 +
73
tests/Makefile.include | 1 +
74
include/hw/arm/aspeed.h | 2 +
75
include/hw/arm/aspeed_soc.h | 2 +
76
include/hw/arm/virt.h | 1 +
77
include/hw/qdev-core.h | 58 +++++++-
78
include/hw/resettable.h | 247 +++++++++++++++++++++++++++++++++
79
include/hw/sd/aspeed_sdhci.h | 1 +
80
target/arm/cpu.h | 7 +
81
target/arm/kvm_arm.h | 95 ++++++++++---
82
hw/arm/aspeed.c | 72 ++++++++--
83
hw/arm/aspeed_ast2600.c | 31 ++++-
84
hw/arm/aspeed_soc.c | 2 +
85
hw/arm/raspi.c | 2 -
86
hw/arm/virt.c | 9 ++
87
hw/audio/intel-hda.c | 2 +-
88
hw/core/bus.c | 102 ++++++++++++++
89
hw/core/or-irq.c | 2 +-
90
hw/core/qdev.c | 160 ++++++++++++++++++++--
91
hw/core/resettable.c | 301 +++++++++++++++++++++++++++++++++++++++++
92
hw/hyperv/hyperv.c | 2 +-
93
hw/i386/microvm.c | 2 +-
94
hw/i386/pc.c | 2 +-
95
hw/ide/microdrive.c | 8 +-
96
hw/intc/arm_gicv3_kvm.c | 11 +-
97
hw/intc/spapr_xive.c | 2 +-
98
hw/misc/pca9552.c | 90 ++++++++++++
99
hw/net/ftgmac100.c | 13 ++
100
hw/ppc/pnv_psi.c | 4 +-
101
hw/ppc/spapr_pci.c | 2 +-
102
hw/ppc/spapr_vio.c | 2 +-
103
hw/s390x/ipl.c | 10 +-
104
hw/s390x/s390-pci-inst.c | 2 +-
105
hw/scsi/vmw_pvscsi.c | 2 +-
106
hw/sd/aspeed_sdhci.c | 11 +-
107
hw/sd/omap_mmc.c | 2 +-
108
hw/sd/pl181.c | 2 +-
109
target/arm/arm-semi.c | 9 ++
110
target/arm/cpu.c | 2 +
111
target/arm/cpu64.c | 1 +
112
target/arm/kvm.c | 120 ++++++++++++++++
113
target/arm/kvm32.c | 3 +
114
target/arm/kvm64.c | 4 +
115
target/arm/machine.c | 7 +
116
target/arm/monitor.c | 1 +
117
tests/qtest/arm-cpu-features.c | 41 ++++--
118
vl.c | 10 +-
119
docs/arm-cpu-features.rst | 37 ++++-
120
docs/devel/index.rst | 1 +
121
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++
122
hw/core/trace-events | 27 ++++
123
51 files changed, 1727 insertions(+), 90 deletions(-)
124
create mode 100644 include/hw/resettable.h
125
create mode 100644 hw/core/resettable.c
126
create mode 100644 docs/devel/reset.rst
127
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
2
2
3
Add the missing GENERIC_TIMER feature to kvm64 cpus.
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
Descriptor is 5 bits([4:0]).
4
5
5
We don't currently use these registers when KVM is enabled, but it's
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
6
probably best we add the feature flag for consistency and potential
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
7
future use. There's also precedent, as we add the PMU feature flag to
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
8
KVM enabled guests, even though we don't use those registers either.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
10
Acked-by: Eric Auger <eric.auger@redhat.com>
10
This change was originally posted as a hunk of a different, never
11
merged patch from Bijan Mottahedeh.
12
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200120101023.16030-4-drjones@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
target/arm/kvm64.c | 1 +
13
hw/arm/smmuv3-internal.h | 2 +-
19
1 file changed, 1 insertion(+)
14
1 file changed, 1 insertion(+), 1 deletion(-)
20
15
21
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/kvm64.c
18
--- a/hw/arm/smmuv3-internal.h
24
+++ b/target/arm/kvm64.c
19
+++ b/hw/arm/smmuv3-internal.h
25
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
26
set_feature(&features, ARM_FEATURE_NEON);
21
return hi << 32 | lo;
27
set_feature(&features, ARM_FEATURE_AARCH64);
22
}
28
set_feature(&features, ARM_FEATURE_PMU);
23
29
+ set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
30
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
31
ahcf->features = features;
26
32
27
#endif
33
--
28
--
34
2.20.1
29
2.20.1
35
30
36
31
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
This commit defines an interface allowing multi-phase reset. This aims
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
to solve a problem of the actual single-phase reset (built in
4
implementation. Bus connection and socketCAN connection for each CAN module
5
DeviceClass and BusClass): reset behavior is dependent on the order
5
can be set through command lines.
6
in which reset handlers are called. In particular doing external
7
side-effect (like setting an qemu_irq) is problematic because receiving
8
object may not be reset yet.
9
6
10
The Resettable interface divides the reset in 3 well defined phases.
7
Example for using single CAN:
11
To reset an object tree, all 1st phases are executed then all 2nd then
8
-object can-bus,id=canbus0 \
12
all 3rd. See the comments in include/hw/resettable.h for a more complete
9
-machine xlnx-zcu102.canbus0=canbus0 \
13
description. The interface defines 3 phases to let the future
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
14
possibility of holding an object into reset for some time.
15
11
16
The qdev/qbus reset in DeviceClass and BusClass will be modified in
12
Example for connecting both CAN to same virtual CAN on host machine:
17
following commits to use this interface. A mechanism is provided
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
18
to allow executing a transitional reset handler in place of the 2nd
14
-machine xlnx-zcu102.canbus0=canbus0 \
19
phase which is executed in children-then-parent order inside a tree.
15
-machine xlnx-zcu102.canbus1=canbus1 \
20
This will allow to transition devices and buses smoothly while
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
21
keeping the exact current qdev/qbus reset behavior for now.
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
22
18
23
Documentation will be added in a following commit.
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
24
21
25
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
29
Message-id: 20200123132823.1117486-4-damien.hedde@greensocs.com
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
26
---
32
hw/core/Makefile.objs | 1 +
27
meson.build | 1 +
33
include/hw/resettable.h | 211 +++++++++++++++++++++++++++++++++++
28
hw/net/can/trace.h | 1 +
34
hw/core/resettable.c | 238 ++++++++++++++++++++++++++++++++++++++++
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
35
hw/core/trace-events | 17 +++
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
36
4 files changed, 467 insertions(+)
31
hw/Kconfig | 1 +
37
create mode 100644 include/hw/resettable.h
32
hw/net/can/meson.build | 1 +
38
create mode 100644 hw/core/resettable.c
33
hw/net/can/trace-events | 9 +
34
7 files changed, 1252 insertions(+)
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
39
39
40
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
40
diff --git a/meson.build b/meson.build
41
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/core/Makefile.objs
42
--- a/meson.build
43
+++ b/hw/core/Makefile.objs
43
+++ b/meson.build
44
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@ if have_system
45
common-obj-y += qdev.o qdev-properties.o
45
'hw/misc',
46
common-obj-y += bus.o
46
'hw/misc/macio',
47
common-obj-y += cpu.o
47
'hw/net',
48
+common-obj-y += resettable.o
48
+ 'hw/net/can',
49
common-obj-y += hotplug.o
49
'hw/nvram',
50
common-obj-y += vmstate-if.o
50
'hw/pci',
51
# irq.o needed for qdev GPIO handling:
51
'hw/pci-host',
52
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
53
new file mode 100644
53
new file mode 100644
54
index XXXXXXX..XXXXXXX
54
index XXXXXXX..XXXXXXX
55
--- /dev/null
55
--- /dev/null
56
+++ b/include/hw/resettable.h
56
+++ b/hw/net/can/trace.h
57
@@ -XXX,XX +XXX,XX @@
57
@@ -0,0 +1 @@
58
+/*
58
+#include "trace/trace-hw_net_can.h"
59
+ * Resettable interface header.
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
60
+ *
61
+ * Copyright (c) 2019 GreenSocs SAS
62
+ *
63
+ * Authors:
64
+ * Damien Hedde
65
+ *
66
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
67
+ * See the COPYING file in the top-level directory.
68
+ */
69
+
70
+#ifndef HW_RESETTABLE_H
71
+#define HW_RESETTABLE_H
72
+
73
+#include "qom/object.h"
74
+
75
+#define TYPE_RESETTABLE_INTERFACE "resettable"
76
+
77
+#define RESETTABLE_CLASS(class) \
78
+ OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE)
79
+
80
+#define RESETTABLE_GET_CLASS(obj) \
81
+ OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE)
82
+
83
+typedef struct ResettableState ResettableState;
84
+
85
+/**
86
+ * ResetType:
87
+ * Types of reset.
88
+ *
89
+ * + Cold: reset resulting from a power cycle of the object.
90
+ *
91
+ * TODO: Support has to be added to handle more types. In particular,
92
+ * ResettableState structure needs to be expanded.
93
+ */
94
+typedef enum ResetType {
95
+ RESET_TYPE_COLD,
96
+} ResetType;
97
+
98
+/*
99
+ * ResettableClass:
100
+ * Interface for resettable objects.
101
+ *
102
+ * See docs/devel/reset.rst for more detailed information about how QEMU models
103
+ * reset. This whole API must only be used when holding the iothread mutex.
104
+ *
105
+ * All objects which can be reset must implement this interface;
106
+ * it is usually provided by a base class such as DeviceClass or BusClass.
107
+ * Every Resettable object must maintain some state tracking the
108
+ * progress of a reset operation by providing a ResettableState structure.
109
+ * The functions defined in this module take care of updating the
110
+ * state of the reset.
111
+ * The base class implementation of the interface provides this
112
+ * state and implements the associated method: get_state.
113
+ *
114
+ * Concrete object implementations (typically specific devices
115
+ * such as a UART model) should provide the functions
116
+ * for the phases.enter, phases.hold and phases.exit methods, which
117
+ * they can set in their class init function, either directly or
118
+ * by calling resettable_class_set_parent_phases().
119
+ * The phase methods are guaranteed to only only ever be called once
120
+ * for any reset event, in the order 'enter', 'hold', 'exit'.
121
+ * An object will always move quickly from 'enter' to 'hold'
122
+ * but might remain in 'hold' for an arbitrary period of time
123
+ * before eventually reset is deasserted and the 'exit' phase is called.
124
+ * Object implementations should be prepared for functions handling
125
+ * inbound connections from other devices (such as qemu_irq handler
126
+ * functions) to be called at any point during reset after their
127
+ * 'enter' method has been called.
128
+ *
129
+ * Users of a resettable object should not call these methods
130
+ * directly, but instead use the function resettable_reset().
131
+ *
132
+ * @phases.enter: This phase is called when the object enters reset. It
133
+ * should reset local state of the object, but it must not do anything that
134
+ * has a side-effect on other objects, such as raising or lowering a qemu_irq
135
+ * line or reading or writing guest memory. It takes the reset's type as
136
+ * argument.
137
+ *
138
+ * @phases.hold: This phase is called for entry into reset, once every object
139
+ * in the system which is being reset has had its @phases.enter method called.
140
+ * At this point devices can do actions that affect other objects.
141
+ *
142
+ * @phases.exit: This phase is called when the object leaves the reset state.
143
+ * Actions affecting other objects are permitted.
144
+ *
145
+ * @get_state: Mandatory method which must return a pointer to a
146
+ * ResettableState.
147
+ *
148
+ * @get_transitional_function: transitional method to handle Resettable objects
149
+ * not yet fully moved to this interface. It will be removed as soon as it is
150
+ * not needed anymore. This method is optional and may return a pointer to a
151
+ * function to be used instead of the phases. If the method exists and returns
152
+ * a non-NULL function pointer then that function is executed as a replacement
153
+ * of the 'hold' phase method taking the object as argument. The two other phase
154
+ * methods are not executed.
155
+ *
156
+ * @child_foreach: Executes a given callback on every Resettable child. Child
157
+ * in this context means a child in the qbus tree, so the children of a qbus
158
+ * are the devices on it, and the children of a device are all the buses it
159
+ * owns. This is not the same as the QOM object hierarchy. The function takes
160
+ * additional opaque and ResetType arguments which must be passed unmodified to
161
+ * the callback.
162
+ */
163
+typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
164
+typedef void (*ResettableHoldPhase)(Object *obj);
165
+typedef void (*ResettableExitPhase)(Object *obj);
166
+typedef ResettableState * (*ResettableGetState)(Object *obj);
167
+typedef void (*ResettableTrFunction)(Object *obj);
168
+typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
169
+typedef void (*ResettableChildCallback)(Object *, void *opaque,
170
+ ResetType type);
171
+typedef void (*ResettableChildForeach)(Object *obj,
172
+ ResettableChildCallback cb,
173
+ void *opaque, ResetType type);
174
+typedef struct ResettablePhases {
175
+ ResettableEnterPhase enter;
176
+ ResettableHoldPhase hold;
177
+ ResettableExitPhase exit;
178
+} ResettablePhases;
179
+typedef struct ResettableClass {
180
+ InterfaceClass parent_class;
181
+
182
+ /* Phase methods */
183
+ ResettablePhases phases;
184
+
185
+ /* State access method */
186
+ ResettableGetState get_state;
187
+
188
+ /* Transitional method for legacy reset compatibility */
189
+ ResettableGetTrFunction get_transitional_function;
190
+
191
+ /* Hierarchy handling method */
192
+ ResettableChildForeach child_foreach;
193
+} ResettableClass;
194
+
195
+/**
196
+ * ResettableState:
197
+ * Structure holding reset related state. The fields should not be accessed
198
+ * directly; the definition is here to allow further inclusion into other
199
+ * objects.
200
+ *
201
+ * @count: Number of reset level the object is into. It is incremented when
202
+ * the reset operation starts and decremented when it finishes.
203
+ * @hold_phase_pending: flag which indicates that we need to invoke the 'hold'
204
+ * phase handler for this object.
205
+ * @exit_phase_in_progress: true if we are currently in the exit phase
206
+ */
207
+struct ResettableState {
208
+ unsigned count;
209
+ bool hold_phase_pending;
210
+ bool exit_phase_in_progress;
211
+};
212
+
213
+/**
214
+ * resettable_reset:
215
+ * Trigger a reset on an object @obj of type @type. @obj must implement
216
+ * Resettable interface.
217
+ *
218
+ * Calling this function is equivalent to calling @resettable_assert_reset()
219
+ * then @resettable_release_reset().
220
+ */
221
+void resettable_reset(Object *obj, ResetType type);
222
+
223
+/**
224
+ * resettable_assert_reset:
225
+ * Put an object @obj into reset. @obj must implement Resettable interface.
226
+ *
227
+ * @resettable_release_reset() must eventually be called after this call.
228
+ * There must be one call to @resettable_release_reset() per call of
229
+ * @resettable_assert_reset(), with the same type argument.
230
+ *
231
+ * NOTE: Until support for migration is added, the @resettable_release_reset()
232
+ * must not be delayed. It must occur just after @resettable_assert_reset() so
233
+ * that migration cannot be triggered in between. Prefer using
234
+ * @resettable_reset() for now.
235
+ */
236
+void resettable_assert_reset(Object *obj, ResetType type);
237
+
238
+/**
239
+ * resettable_release_reset:
240
+ * Release the object @obj from reset. @obj must implement Resettable interface.
241
+ *
242
+ * See @resettable_assert_reset() description for details.
243
+ */
244
+void resettable_release_reset(Object *obj, ResetType type);
245
+
246
+/**
247
+ * resettable_is_in_reset:
248
+ * Return true if @obj is under reset.
249
+ *
250
+ * @obj must implement Resettable interface.
251
+ */
252
+bool resettable_is_in_reset(Object *obj);
253
+
254
+/**
255
+ * resettable_class_set_parent_phases:
256
+ *
257
+ * Save @rc current reset phases into @parent_phases and override @rc phases
258
+ * by the given new methods (@enter, @hold and @exit).
259
+ * Each phase is overridden only if the new one is not NULL allowing to
260
+ * override a subset of phases.
261
+ */
262
+void resettable_class_set_parent_phases(ResettableClass *rc,
263
+ ResettableEnterPhase enter,
264
+ ResettableHoldPhase hold,
265
+ ResettableExitPhase exit,
266
+ ResettablePhases *parent_phases);
267
+
268
+#endif
269
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
270
new file mode 100644
60
new file mode 100644
271
index XXXXXXX..XXXXXXX
61
index XXXXXXX..XXXXXXX
272
--- /dev/null
62
--- /dev/null
273
+++ b/hw/core/resettable.c
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
274
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
275
+/*
65
+/*
276
+ * Resettable interface.
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
277
+ *
67
+ *
278
+ * Copyright (c) 2019 GreenSocs SAS
68
+ * Copyright (c) 2020 Xilinx Inc.
279
+ *
69
+ *
280
+ * Authors:
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
281
+ * Damien Hedde
282
+ *
71
+ *
283
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
284
+ * See the COPYING file in the top-level directory.
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
285
+ */
92
+ */
286
+
93
+
94
+#ifndef XLNX_ZYNQMP_CAN_H
95
+#define XLNX_ZYNQMP_CAN_H
96
+
97
+#include "hw/register.h"
98
+#include "net/can_emu.h"
99
+#include "net/can_host.h"
100
+#include "qemu/fifo32.h"
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
142
+#endif
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
144
new file mode 100644
145
index XXXXXXX..XXXXXXX
146
--- /dev/null
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
148
@@ -XXX,XX +XXX,XX @@
149
+/*
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
151
+ * This implementation is based on the following datasheet:
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
153
+ *
154
+ * Copyright (c) 2020 Xilinx Inc.
155
+ *
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
157
+ *
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
178
+ */
179
+
287
+#include "qemu/osdep.h"
180
+#include "qemu/osdep.h"
288
+#include "qemu/module.h"
181
+#include "hw/sysbus.h"
289
+#include "hw/resettable.h"
182
+#include "hw/register.h"
183
+#include "hw/irq.h"
184
+#include "qapi/error.h"
185
+#include "qemu/bitops.h"
186
+#include "qemu/log.h"
187
+#include "qemu/cutils.h"
188
+#include "sysemu/sysemu.h"
189
+#include "migration/vmstate.h"
190
+#include "hw/qdev-properties.h"
191
+#include "net/can_emu.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
290
+#include "trace.h"
196
+#include "trace.h"
291
+
197
+
292
+/**
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
293
+ * resettable_phase_enter/hold/exit:
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
294
+ * Function executing a phase recursively in a resettable object and its
200
+#endif
295
+ * children.
201
+
296
+ */
202
+#define MAX_DLC 8
297
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type);
203
+#undef ERROR
298
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type);
204
+
299
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
300
+
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
301
+/**
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
302
+ * enter_phase_in_progress:
208
+REG32(MODE_SELECT_REGISTER, 0x4)
303
+ * True if we are currently in reset enter phase.
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
304
+ *
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
305
+ * Note: This flag is only used to guarantee (using asserts) that the reset
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
306
+ * API is used correctly. We can use a global variable because we rely on the
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
307
+ * iothread mutex to ensure only one reset operation is in a progress at a
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
308
+ * given time.
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
309
+ */
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
310
+static bool enter_phase_in_progress;
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
311
+
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
312
+void resettable_reset(Object *obj, ResetType type)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
313
+{
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
314
+ trace_resettable_reset(obj, type);
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
315
+ resettable_assert_reset(obj, type);
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
316
+ resettable_release_reset(obj, type);
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
317
+}
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
318
+
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
319
+void resettable_assert_reset(Object *obj, ResetType type)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
320
+{
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
321
+ /* TODO: change this assert when adding support for other reset types */
227
+REG32(STATUS_REGISTER, 0x18)
322
+ assert(type == RESET_TYPE_COLD);
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
323
+ trace_resettable_reset_assert_begin(obj, type);
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
324
+ assert(!enter_phase_in_progress);
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
325
+
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
326
+ enter_phase_in_progress = true;
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
327
+ resettable_phase_enter(obj, NULL, type);
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
328
+ enter_phase_in_progress = false;
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
329
+
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
330
+ resettable_phase_hold(obj, NULL, type);
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
331
+
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
332
+ trace_resettable_reset_assert_end(obj);
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
333
+}
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
334
+
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
335
+void resettable_release_reset(Object *obj, ResetType type)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
336
+{
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
337
+ /* TODO: change this assert when adding support for other reset types */
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
338
+ assert(type == RESET_TYPE_COLD);
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
339
+ trace_resettable_reset_release_begin(obj, type);
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
340
+ assert(!enter_phase_in_progress);
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
341
+
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
342
+ resettable_phase_exit(obj, NULL, type);
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
343
+
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
344
+ trace_resettable_reset_release_end(obj);
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
345
+}
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
346
+
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
347
+bool resettable_is_in_reset(Object *obj)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
348
+{
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
349
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
350
+ ResettableState *s = rc->get_state(obj);
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
351
+
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
352
+ return s->count > 0;
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
353
+}
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
354
+
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
355
+/**
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
356
+ * resettable_child_foreach:
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
357
+ * helper to avoid checking the existence of the method.
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
358
+ */
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
359
+static void resettable_child_foreach(ResettableClass *rc, Object *obj,
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
360
+ ResettableChildCallback cb,
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
361
+ void *opaque, ResetType type)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
362
+{
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
363
+ if (rc->child_foreach) {
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
364
+ rc->child_foreach(obj, cb, opaque, type);
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
365
+ }
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
366
+}
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
367
+
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
368
+/**
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
369
+ * resettable_get_tr_func:
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
370
+ * helper to fetch transitional reset callback if any.
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
371
+ */
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
372
+static ResettableTrFunction resettable_get_tr_func(ResettableClass *rc,
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
373
+ Object *obj)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
374
+{
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
375
+ ResettableTrFunction tr_func = NULL;
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
376
+ if (rc->get_transitional_function) {
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
377
+ tr_func = rc->get_transitional_function(obj);
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
378
+ }
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
379
+ return tr_func;
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
380
+}
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
381
+
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
382
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
383
+{
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
384
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
290
+REG32(WIR, 0x2c)
385
+ ResettableState *s = rc->get_state(obj);
291
+ FIELD(WIR, EW, 8, 8)
386
+ const char *obj_typename = object_get_typename(obj);
292
+ FIELD(WIR, FW, 0, 8)
387
+ bool action_needed = false;
293
+REG32(TXFIFO_ID, 0x30)
388
+
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
389
+ /* exit phase has to finish properly before entering back in reset */
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
390
+ assert(!s->exit_phase_in_progress);
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
391
+
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
392
+ trace_resettable_phase_enter_begin(obj, obj_typename, s->count, type);
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
393
+
299
+REG32(TXFIFO_DLC, 0x34)
394
+ /* Only take action if we really enter reset for the 1st time. */
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
635
+ }
636
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
395
+ /*
690
+ /*
396
+ * TODO: if adding more ResetType support, some additional checks
691
+ * Multiple mode set check. This is done to make sure user doesn't set
397
+ * are probably needed here.
692
+ * multiple modes.
398
+ */
693
+ */
399
+ if (s->count++ == 0) {
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
400
+ action_needed = true;
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
401
+ }
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
402
+ /*
785
+ /*
403
+ * We limit the count to an arbitrary "big" value. The value is big
786
+ * Messages that pass any of the acceptance filters will be stored in
404
+ * enough not to be triggered normally.
787
+ * the RX FIFO.
405
+ * The assert will stop an infinite loop if there is a cycle in the
406
+ * reset tree. The loop goes through resettable_foreach_child below
407
+ * which at some point will call us again.
408
+ */
788
+ */
409
+ assert(s->count <= 50);
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
410
+
1121
+
411
+ /*
1122
+ /*
412
+ * handle the children even if action_needed is at false so that
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
413
+ * child counts are incremented too
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
414
+ */
1127
+ */
415
+ resettable_child_foreach(rc, obj, resettable_phase_enter, NULL, type);
1128
+ fifo32_reset(&s->rx_fifo);
416
+
1129
+ fifo32_reset(&s->tx_fifo);
417
+ /* execute enter phase for the object if needed */
1130
+ fifo32_reset(&s->txhpb_fifo);
418
+ if (action_needed) {
1131
+}
419
+ trace_resettable_phase_enter_exec(obj, obj_typename, type,
1132
+
420
+ !!rc->phases.enter);
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
421
+ if (rc->phases.enter && !resettable_get_tr_func(rc, obj)) {
1134
+{
422
+ rc->phases.enter(obj, type);
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
423
+ }
1221
+ }
424
+ s->hold_phase_pending = true;
1222
+ }
425
+ }
1223
+
426
+ trace_resettable_phase_enter_end(obj, obj_typename, s->count);
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
427
+}
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
428
+
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
429
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type)
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
430
+{
1228
+
431
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
1229
+ /* Allocate a new timer. */
432
+ ResettableState *s = rc->get_state(obj);
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
433
+ const char *obj_typename = object_get_typename(obj);
1231
+ PTIMER_POLICY_DEFAULT);
434
+
1232
+
435
+ /* exit phase has to finish properly before entering back in reset */
1233
+ ptimer_transaction_begin(s->can_timer);
436
+ assert(!s->exit_phase_in_progress);
1234
+
437
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
438
+ trace_resettable_phase_hold_begin(obj, obj_typename, s->count, type);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
439
+
1237
+ ptimer_run(s->can_timer, 0);
440
+ /* handle children first */
1238
+ ptimer_transaction_commit(s->can_timer);
441
+ resettable_child_foreach(rc, obj, resettable_phase_hold, NULL, type);
1239
+}
442
+
1240
+
443
+ /* exec hold phase */
1241
+static void xlnx_zynqmp_can_init(Object *obj)
444
+ if (s->hold_phase_pending) {
1242
+{
445
+ s->hold_phase_pending = false;
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
446
+ ResettableTrFunction tr_func = resettable_get_tr_func(rc, obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
447
+ trace_resettable_phase_hold_exec(obj, obj_typename, !!rc->phases.hold);
1245
+
448
+ if (tr_func) {
1246
+ RegisterInfoArray *reg_array;
449
+ trace_resettable_transitional_function(obj, obj_typename);
1247
+
450
+ tr_func(obj);
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
451
+ } else if (rc->phases.hold) {
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
452
+ rc->phases.hold(obj);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
453
+ }
1251
+ ARRAY_SIZE(can_regs_info),
454
+ }
1252
+ s->reg_info, s->regs,
455
+ trace_resettable_phase_hold_end(obj, obj_typename, s->count);
1253
+ &can_ops,
456
+}
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
457
+
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
458
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
1256
+
459
+{
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
460
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
461
+ ResettableState *s = rc->get_state(obj);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
462
+ const char *obj_typename = object_get_typename(obj);
1260
+}
463
+
1261
+
464
+ assert(!s->exit_phase_in_progress);
1262
+static const VMStateDescription vmstate_can = {
465
+ trace_resettable_phase_exit_begin(obj, obj_typename, s->count, type);
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
466
+
1264
+ .version_id = 1,
467
+ /* exit_phase_in_progress ensures this phase is 'atomic' */
1265
+ .minimum_version_id = 1,
468
+ s->exit_phase_in_progress = true;
1266
+ .fields = (VMStateField[]) {
469
+ resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type);
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
470
+
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
471
+ assert(s->count > 0);
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
472
+ if (s->count == 1) {
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
473
+ trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
474
+ if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
1272
+ VMSTATE_END_OF_LIST(),
475
+ rc->phases.exit(obj);
1273
+ }
476
+ }
477
+ s->count = 0;
478
+ }
479
+ s->exit_phase_in_progress = false;
480
+ trace_resettable_phase_exit_end(obj, obj_typename, s->count);
481
+}
482
+
483
+void resettable_class_set_parent_phases(ResettableClass *rc,
484
+ ResettableEnterPhase enter,
485
+ ResettableHoldPhase hold,
486
+ ResettableExitPhase exit,
487
+ ResettablePhases *parent_phases)
488
+{
489
+ *parent_phases = rc->phases;
490
+ if (enter) {
491
+ rc->phases.enter = enter;
492
+ }
493
+ if (hold) {
494
+ rc->phases.hold = hold;
495
+ }
496
+ if (exit) {
497
+ rc->phases.exit = exit;
498
+ }
499
+}
500
+
501
+static const TypeInfo resettable_interface_info = {
502
+ .name = TYPE_RESETTABLE_INTERFACE,
503
+ .parent = TYPE_INTERFACE,
504
+ .class_size = sizeof(ResettableClass),
505
+};
1274
+};
506
+
1275
+
507
+static void reset_register_types(void)
1276
+static Property xlnx_zynqmp_can_properties[] = {
508
+{
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
509
+ type_register_static(&resettable_interface_info);
1278
+ CAN_DEFAULT_CLOCK),
510
+}
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
511
+
1280
+ CanBusState *),
512
+type_init(reset_register_types)
1281
+ DEFINE_PROP_END_OF_LIST(),
513
diff --git a/hw/core/trace-events b/hw/core/trace-events
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
514
index XXXXXXX..XXXXXXX 100644
1311
index XXXXXXX..XXXXXXX 100644
515
--- a/hw/core/trace-events
1312
--- a/hw/Kconfig
516
+++ b/hw/core/trace-events
1313
+++ b/hw/Kconfig
517
@@ -XXX,XX +XXX,XX @@ qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
518
qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
1315
config XLNX_ZYNQMP
519
qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
1316
bool
520
qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
1317
select REGISTER
521
+
1318
+ select CAN_BUS
522
+# resettable.c
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
523
+resettable_reset(void *obj, int cold) "obj=%p cold=%d"
1320
index XXXXXXX..XXXXXXX 100644
524
+resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
1321
--- a/hw/net/can/meson.build
525
+resettable_reset_assert_end(void *obj) "obj=%p"
1322
+++ b/hw/net/can/meson.build
526
+resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
527
+resettable_reset_release_end(void *obj) "obj=%p"
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
528
+resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
529
+resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
530
+resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
531
+resettable_phase_hold_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
532
+resettable_phase_hold_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
1329
new file mode 100644
533
+resettable_phase_hold_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
1330
index XXXXXXX..XXXXXXX
534
+resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
1331
--- /dev/null
535
+resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
1332
+++ b/hw/net/can/trace-events
536
+resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
1333
@@ -XXX,XX +XXX,XX @@
537
+resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
538
--
1343
--
539
2.20.1
1344
2.20.1
540
1345
541
1346
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
kvm-no-adjvtime is a KVM specific CPU property and a first of its
3
Connect CAN0 and CAN1 on the ZynqMP.
4
kind. To accommodate it we also add kvm_arm_add_vcpu_properties()
5
and a KVM specific CPU properties description to the CPU features
6
document.
7
4
8
Signed-off-by: Andrew Jones <drjones@redhat.com>
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
Message-id: 20200120101023.16030-7-drjones@redhat.com
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
include/hw/arm/virt.h | 1 +
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
14
target/arm/kvm_arm.h | 11 ++++++++++
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
15
hw/arm/virt.c | 8 ++++++++
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
16
target/arm/cpu.c | 2 ++
14
3 files changed, 62 insertions(+)
17
target/arm/cpu64.c | 1 +
18
target/arm/kvm.c | 28 +++++++++++++++++++++++++
19
target/arm/monitor.c | 1 +
20
tests/qtest/arm-cpu-features.c | 4 ++++
21
docs/arm-cpu-features.rst | 37 +++++++++++++++++++++++++++++++++-
22
9 files changed, 92 insertions(+), 1 deletion(-)
23
15
24
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/virt.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
27
+++ b/include/hw/arm/virt.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
@@ -XXX,XX +XXX,XX @@
29
bool smbios_old_sys_ver;
21
#include "hw/intc/arm_gic.h"
30
bool no_highmem_ecam;
22
#include "hw/net/cadence_gem.h"
31
bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
23
#include "hw/char/cadence_uart.h"
32
+ bool kvm_no_adjvtime;
24
+#include "hw/net/xlnx-zynqmp-can.h"
33
} VirtMachineClass;
25
#include "hw/ide/ahci.h"
34
26
#include "hw/sd/sdhci.h"
35
typedef struct {
27
#include "hw/ssi/xilinx_spips.h"
36
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
37
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/kvm_arm.h
65
--- a/hw/arm/xlnx-zcu102.c
39
+++ b/target/arm/kvm_arm.h
66
+++ b/hw/arm/xlnx-zcu102.c
40
@@ -XXX,XX +XXX,XX @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
67
@@ -XXX,XX +XXX,XX @@
41
*/
68
#include "sysemu/qtest.h"
42
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
69
#include "sysemu/device_tree.h"
43
70
#include "qom/object.h"
44
+/**
71
+#include "net/can_emu.h"
45
+ * kvm_arm_add_vcpu_properties:
72
46
+ * @obj: The CPU object to add the properties to
73
struct XlnxZCU102 {
47
+ *
74
MachineState parent_obj;
48
+ * Add all KVM specific CPU properties to the CPU object. These
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
49
+ * are the CPU properties with "kvm-" prefixed names.
76
bool secure;
50
+ */
77
bool virt;
51
+void kvm_arm_add_vcpu_properties(Object *obj);
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
52
+
80
+
53
/**
81
struct arm_boot_info binfo;
54
* kvm_arm_aarch32_supported:
82
};
55
* @cs: CPUState
83
56
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
57
cpu->host_cpu_probe_failed = true;
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
58
}
86
&error_fatal);
59
87
60
+static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
61
+
90
+
62
static inline bool kvm_arm_aarch32_supported(CPUState *cs)
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
63
{
92
+ OBJECT(s->canbus[i]), &error_fatal);
64
return false;
93
+ g_free(bus_name);
65
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/virt.c
68
+++ b/hw/arm/virt.c
69
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
70
}
71
}
72
73
+ if (vmc->kvm_no_adjvtime &&
74
+ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
75
+ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL);
76
+ }
77
+
78
if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
79
object_property_set_bool(cpuobj, false, "pmu", NULL);
80
}
81
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
82
83
static void virt_machine_4_2_options(MachineClass *mc)
84
{
85
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
86
+
87
virt_machine_5_0_options(mc);
88
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
89
+ vmc->kvm_no_adjvtime = true;
90
}
91
DEFINE_VIRT_MACHINE(4, 2)
92
93
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/cpu.c
96
+++ b/target/arm/cpu.c
97
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
98
99
if (kvm_enabled()) {
100
kvm_arm_set_cpu_features_from_host(cpu);
101
+ kvm_arm_add_vcpu_properties(obj);
102
} else {
103
cortex_a15_initfn(obj);
104
105
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
106
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
107
aarch64_add_sve_properties(obj);
108
}
109
+ kvm_arm_add_vcpu_properties(obj);
110
arm_cpu_post_init(obj);
111
}
112
113
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/cpu64.c
116
+++ b/target/arm/cpu64.c
117
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
118
119
if (kvm_enabled()) {
120
kvm_arm_set_cpu_features_from_host(cpu);
121
+ kvm_arm_add_vcpu_properties(obj);
122
} else {
123
uint64_t t;
124
uint32_t u;
125
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/kvm.c
128
+++ b/target/arm/kvm.c
129
@@ -XXX,XX +XXX,XX @@
130
#include "qemu/timer.h"
131
#include "qemu/error-report.h"
132
#include "qemu/main-loop.h"
133
+#include "qom/object.h"
134
+#include "qapi/error.h"
135
#include "sysemu/sysemu.h"
136
#include "sysemu/kvm.h"
137
#include "sysemu/kvm_int.h"
138
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
139
env->features = arm_host_cpu_features.features;
140
}
141
142
+static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
143
+{
144
+ return !ARM_CPU(obj)->kvm_adjvtime;
145
+}
146
+
147
+static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
148
+{
149
+ ARM_CPU(obj)->kvm_adjvtime = !value;
150
+}
151
+
152
+/* KVM VCPU properties should be prefixed with "kvm-". */
153
+void kvm_arm_add_vcpu_properties(Object *obj)
154
+{
155
+ if (!kvm_enabled()) {
156
+ return;
157
+ }
94
+ }
158
+
95
+
159
+ ARM_CPU(obj)->kvm_adjvtime = true;
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
160
+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
97
161
+ kvm_no_adjvtime_set, &error_abort);
98
/* Create and plug in the SD cards */
162
+ object_property_set_description(obj, "kvm-no-adjvtime",
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
163
+ "Set on to disable the adjustment of "
100
s->secure = false;
164
+ "the virtual counter. VM stopped time "
101
/* Default to virt (EL2) being disabled */
165
+ "will be counted.", &error_abort);
102
s->virt = false;
166
+}
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
167
+
107
+
168
bool kvm_arm_pmu_supported(CPUState *cpu)
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
169
{
109
+ (Object **)&s->canbus[1],
170
return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);
110
+ object_property_allow_set_link,
171
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
111
+ 0);
112
}
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
172
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/monitor.c
117
--- a/hw/arm/xlnx-zynqmp.c
174
+++ b/target/arm/monitor.c
118
+++ b/hw/arm/xlnx-zynqmp.c
175
@@ -XXX,XX +XXX,XX @@ static const char *cpu_model_advertised_features[] = {
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
176
"sve128", "sve256", "sve384", "sve512",
120
21, 22,
177
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
178
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
179
+ "kvm-no-adjvtime",
180
NULL
181
};
121
};
182
122
183
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
184
index XXXXXXX..XXXXXXX 100644
124
+ 0xFF060000, 0xFF070000,
185
--- a/tests/qtest/arm-cpu-features.c
125
+};
186
+++ b/tests/qtest/arm-cpu-features.c
187
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
188
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
189
assert_has_not_feature(qts, "cortex-a15", "aarch64");
190
191
+ assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
192
+
126
+
193
if (g_str_equal(qtest_get_arch(), "aarch64")) {
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
194
assert_has_feature_enabled(qts, "max", "aarch64");
128
+ 23, 24,
195
assert_has_feature_enabled(qts, "max", "sve");
129
+};
196
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
130
+
197
return;
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
198
}
136
}
199
137
200
+ assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
201
+
142
+
202
if (g_str_equal(qtest_get_arch(), "aarch64")) {
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
203
bool kvm_supports_sve;
144
204
char max_name[8], name[8];
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
205
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
206
index XXXXXXX..XXXXXXX 100644
147
gic_spi[uart_intr[i]]);
207
--- a/docs/arm-cpu-features.rst
148
}
208
+++ b/docs/arm-cpu-features.rst
149
209
@@ -XXX,XX +XXX,XX @@ supporting the feature or only supporting the feature under certain
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
210
configurations. For example, the `aarch64` CPU feature, which, when
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
211
disabled, enables the optional AArch32 CPU feature, is only supported
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
212
when using the KVM accelerator and when running on a host CPU type that
213
-supports the feature.
214
+supports the feature. While `aarch64` currently only works with KVM,
215
+it could work with TCG. CPU features that are specific to KVM are
216
+prefixed with "kvm-" and are described in "KVM VCPU Features".
217
218
CPU Feature Probing
219
===================
220
@@ -XXX,XX +XXX,XX @@ disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
221
properties have special semantics (see "SVE CPU Property Parsing
222
Semantics").
223
224
+KVM VCPU Features
225
+=================
226
+
153
+
227
+KVM VCPU features are CPU features that are specific to KVM, such as
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
228
+paravirt features or features that enable CPU virtualization extensions.
155
+ OBJECT(s->canbus[i]), &error_fatal);
229
+The features' CPU properties are only available when KVM is enabled and
230
+are named with the prefix "kvm-". KVM VCPU features may be probed,
231
+enabled, and disabled in the same way as other CPU features. Below is
232
+the list of KVM VCPU features and their descriptions.
233
+
156
+
234
+ kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
235
+ means that by default the virtual time
158
+ if (err) {
236
+ adjustment is enabled (vtime is *not not*
159
+ error_propagate(errp, err);
237
+ adjusted).
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
238
+
166
+
239
+ When virtual time adjustment is enabled each
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
240
+ time the VM transitions back to running state
168
&error_abort);
241
+ the VCPU's virtual counter is updated to ensure
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
242
+ stopped time is not counted. This avoids time
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
243
+ jumps surprising guest OSes and applications,
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
244
+ as long as they use the virtual counter for
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
245
+ timekeeping. However it has the side effect of
173
MemoryRegion *),
246
+ the virtual and physical counters diverging.
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
247
+ All timekeeping based on the virtual counter
175
+ CanBusState *),
248
+ will appear to lag behind any timekeeping that
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
249
+ does not subtract VM stopped time. The guest
177
+ CanBusState *),
250
+ may resynchronize its virtual counter with
178
DEFINE_PROP_END_OF_LIST()
251
+ other time sources as needed.
179
};
252
+
253
+ Enable kvm-no-adjvtime to disable virtual time
254
+ adjustment, also restoring the legacy (pre-5.0)
255
+ behavior.
256
+
257
SVE CPU Properties
258
==================
259
180
260
--
181
--
261
2.20.1
182
2.20.1
262
183
263
184
diff view generated by jsdifflib
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
If LPIs are disabled, KVM will just ignore the GICR_PENDBASER.PTZ bit when
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
restoring GICR_CTLR. Setting PTZ here makes littlt sense in "reduce GIC
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
initialization time".
5
Tests filtering of incoming CAN messages.
6
6
7
And what's worse, PTZ is generally programmed by guest to indicate to the
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Redistributor whether the LPI Pending table is zero when enabling LPIs.
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
If migration is triggered when the PTZ has just been cleared by guest (and
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
before enabling LPIs), we will see PTZ==1 on the destination side, which
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
11
is not as expected. Let's just drop this hackish userspace behavior.
12
13
Also take this chance to refine the comment a bit.
14
15
Fixes: 367b9f527bec ("hw/intc/arm_gicv3_kvm: Implement get/put functions")
16
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
17
Message-id: 20200119133051.642-1-yuzenghui@huawei.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
12
---
21
hw/intc/arm_gicv3_kvm.c | 11 ++++-------
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
22
1 file changed, 4 insertions(+), 7 deletions(-)
14
tests/qtest/meson.build | 1 +
23
15
2 files changed, 361 insertions(+)
24
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
26
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
28
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
132
+ const uint32_t *buf_tx)
133
+{
134
+ uint32_t int_status;
135
+
136
+ /* Write the TX register data for CAN. */
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
141
+
142
+ /* Read the interrupt on CAN for tx. */
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
144
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
146
+
147
+ /* Clear the interrupt for tx. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
149
+}
150
+
151
+/*
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
155
+ */
156
+static void test_can_bus(void)
157
+{
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
160
+ uint32_t status = 0;
161
+ uint8_t can_timestamp = 1;
162
+
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
164
+ " -object can-bus,id=canbus0"
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
167
+ );
168
+
169
+ /* Configure the CAN0 and CAN1. */
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
174
+
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
178
+
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
181
+
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
183
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
186
+
187
+ qtest_quit(qts);
188
+}
189
+
190
+/*
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
193
+ */
194
+static void test_can_loopback(void)
195
+{
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
198
+ uint32_t status = 0;
199
+
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
201
+ " -object can-bus,id=canbus0"
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
204
+ );
205
+
206
+ /* Configure the CAN0 in loopback mode. */
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
210
+
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
235
+}
236
+
237
+/*
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
239
+ * test message will pass through filter 2.
240
+ */
241
+static void test_can_filter(void)
242
+{
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
245
+ uint32_t status = 0;
246
+ uint8_t can_timestamp = 1;
247
+
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
249
+ " -object can-bus,id=canbus0"
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
25
index XXXXXXX..XXXXXXX 100644
385
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_kvm.c
386
--- a/tests/qtest/meson.build
27
+++ b/hw/intc/arm_gicv3_kvm.c
387
+++ b/tests/qtest/meson.build
28
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
29
kvm_gicd_access(s, GICD_CTLR, &reg, true);
389
['arm-cpu-features',
30
390
'numa-test',
31
if (redist_typer & GICR_TYPER_PLPIS) {
391
'boot-serial-test',
32
- /* Set base addresses before LPIs are enabled by GICR_CTLR write */
392
+ 'xlnx-can-test',
33
+ /*
393
'migration-test']
34
+ * Restore base addresses before LPIs are potentially enabled by
394
35
+ * GICR_CTLR write
395
qtests_s390x = \
36
+ */
37
for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
38
GICv3CPUState *c = &s->cpu[ncpu];
39
40
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
41
kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
42
43
reg64 = c->gicr_pendbaser;
44
- if (!(c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
45
- /* Setting PTZ is advised if LPIs are disabled, to reduce
46
- * GIC initialization time.
47
- */
48
- reg64 |= GICR_PENDBASER_PTZ;
49
- }
50
regl = (uint32_t)reg64;
51
kvm_gicr_access(s, GICR_PENDBASER, ncpu, &regl, true);
52
regh = (uint32_t)(reg64 >> 32);
53
--
396
--
54
2.20.1
397
2.20.1
55
398
56
399
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
If we know what the default value should be then we can test for
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
that as well as the feature existence.
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200120101023.16030-5-drjones@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
tests/qtest/arm-cpu-features.c | 37 +++++++++++++++++++++++++---------
9
MAINTAINERS | 8 ++++++++
12
1 file changed, 28 insertions(+), 9 deletions(-)
10
1 file changed, 8 insertions(+)
13
11
14
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
12
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qtest/arm-cpu-features.c
14
--- a/MAINTAINERS
17
+++ b/tests/qtest/arm-cpu-features.c
15
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ static bool resp_get_feature(QDict *resp, const char *feature)
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
19
qobject_unref(_resp); \
17
20
})
18
Devices
21
19
-------
22
+#define assert_feature(qts, cpu_type, feature, expected_value) \
20
+Xilinx CAN
23
+({ \
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
24
+ QDict *_resp, *_props; \
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
25
+ \
23
+S: Maintained
26
+ _resp = do_query_no_props(qts, cpu_type); \
24
+F: hw/net/can/xlnx-*
27
+ g_assert(_resp); \
25
+F: include/hw/net/xlnx-*
28
+ g_assert(resp_has_props(_resp)); \
26
+F: tests/qtest/xlnx-can-test*
29
+ _props = resp_get_props(_resp); \
30
+ g_assert(qdict_get(_props, feature)); \
31
+ g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
32
+ qobject_unref(_resp); \
33
+})
34
+
27
+
35
+#define assert_has_feature_enabled(qts, cpu_type, feature) \
28
EDU
36
+ assert_feature(qts, cpu_type, feature, true)
29
M: Jiri Slaby <jslaby@suse.cz>
37
+
30
S: Maintained
38
+#define assert_has_feature_disabled(qts, cpu_type, feature) \
39
+ assert_feature(qts, cpu_type, feature, false)
40
+
41
static void assert_type_full(QTestState *qts)
42
{
43
const char *error;
44
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
45
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
46
47
/* Test expected feature presence/absence for some cpu types */
48
- assert_has_feature(qts, "max", "pmu");
49
- assert_has_feature(qts, "cortex-a15", "pmu");
50
+ assert_has_feature_enabled(qts, "max", "pmu");
51
+ assert_has_feature_enabled(qts, "cortex-a15", "pmu");
52
assert_has_not_feature(qts, "cortex-a15", "aarch64");
53
54
if (g_str_equal(qtest_get_arch(), "aarch64")) {
55
- assert_has_feature(qts, "max", "aarch64");
56
- assert_has_feature(qts, "max", "sve");
57
- assert_has_feature(qts, "max", "sve128");
58
- assert_has_feature(qts, "cortex-a57", "pmu");
59
- assert_has_feature(qts, "cortex-a57", "aarch64");
60
+ assert_has_feature_enabled(qts, "max", "aarch64");
61
+ assert_has_feature_enabled(qts, "max", "sve");
62
+ assert_has_feature_enabled(qts, "max", "sve128");
63
+ assert_has_feature_enabled(qts, "cortex-a57", "pmu");
64
+ assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
65
66
sve_tests_default(qts, "max");
67
68
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
69
QDict *resp;
70
char *error;
71
72
- assert_has_feature(qts, "host", "aarch64");
73
- assert_has_feature(qts, "host", "pmu");
74
+ assert_has_feature_enabled(qts, "host", "aarch64");
75
+ assert_has_feature_enabled(qts, "host", "pmu");
76
77
assert_error(qts, "cortex-a15",
78
"We cannot guarantee the CPU type 'cortex-a15' works "
79
--
31
--
80
2.20.1
32
2.20.1
81
33
82
34
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
The AST2600 includes a second cut-down version of the SD/MMC controller
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
4
found in the AST2500, named the eMMC controller. It's cut down in the
4
it for QEMU as well. A53 was already enabled there.
5
sense that it only supports one slot rather than two, but it brings the
6
total number of slots supported by the AST2600 to three.
7
5
8
The existing code assumed that the SD controller always provided two
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
9
slots. Rework the SDHCI object to expose the number of slots as a
10
property to be set by the SoC configuration.
11
7
12
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
15
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20200114103433.30534-2-clg@kaod.org
17
[PMM: fixed up to use device_class_set_props()]
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
13
---
20
include/hw/sd/aspeed_sdhci.h | 1 +
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
21
hw/arm/aspeed.c | 2 +-
15
1 file changed, 20 insertions(+), 3 deletions(-)
22
hw/arm/aspeed_ast2600.c | 2 ++
23
hw/arm/aspeed_soc.c | 2 ++
24
hw/sd/aspeed_sdhci.c | 11 +++++++++--
25
5 files changed, 15 insertions(+), 3 deletions(-)
26
16
27
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/sd/aspeed_sdhci.h
19
--- a/hw/arm/sbsa-ref.c
30
+++ b/include/hw/sd/aspeed_sdhci.h
20
+++ b/hw/arm/sbsa-ref.c
31
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSDHCIState {
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
32
SysBusDevice parent;
22
[SBSA_GWDT] = 16,
33
34
SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
35
+ uint8_t num_slots;
36
37
MemoryRegion iomem;
38
qemu_irq irq;
39
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/aspeed.c
42
+++ b/hw/arm/aspeed.c
43
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
44
amc->i2c_init(bmc);
45
}
46
47
- for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
48
+ for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
49
SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
50
DriveInfo *dinfo = drive_get_next(IF_SD);
51
BlockBackend *blk;
52
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/aspeed_ast2600.c
55
+++ b/hw/arm/aspeed_ast2600.c
56
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
57
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
58
TYPE_ASPEED_SDHCI);
59
60
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
61
+
62
/* Init sd card slot class here so that they're under the correct parent */
63
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
64
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
65
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/aspeed_soc.c
68
+++ b/hw/arm/aspeed_soc.c
69
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
70
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
71
TYPE_ASPEED_SDHCI);
72
73
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
74
+
75
/* Init sd card slot class here so that they're under the correct parent */
76
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
77
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
78
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/sd/aspeed_sdhci.c
81
+++ b/hw/sd/aspeed_sdhci.c
82
@@ -XXX,XX +XXX,XX @@
83
#include "qapi/error.h"
84
#include "hw/irq.h"
85
#include "migration/vmstate.h"
86
+#include "hw/qdev-properties.h"
87
88
#define ASPEED_SDHCI_INFO 0x00
89
#define ASPEED_SDHCI_INFO_RESET 0x00030000
90
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp)
91
92
/* Create input irqs for the slots */
93
qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
94
- sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
95
+ sdhci, NULL, sdhci->num_slots);
96
97
sysbus_init_irq(sbd, &sdhci->irq);
98
memory_region_init_io(&sdhci->iomem, OBJECT(sdhci), &aspeed_sdhci_ops,
99
sdhci, TYPE_ASPEED_SDHCI, 0x1000);
100
sysbus_init_mmio(sbd, &sdhci->iomem);
101
102
- for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
103
+ for (int i = 0; i < sdhci->num_slots; ++i) {
104
Object *sdhci_slot = OBJECT(&sdhci->slots[i]);
105
SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]);
106
107
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_sdhci = {
108
},
109
};
23
};
110
24
111
+static Property aspeed_sdhci_properties[] = {
25
+static const char * const valid_cpus[] = {
112
+ DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
113
+ DEFINE_PROP_END_OF_LIST(),
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
114
+};
29
+};
115
+
30
+
116
static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
31
+static bool cpu_type_valid(const char *cpu)
32
+{
33
+ int i;
34
+
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+}
42
+
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
117
{
44
{
118
DeviceClass *dc = DEVICE_CLASS(classp);
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
119
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
120
dc->realize = aspeed_sdhci_realize;
47
const CPUArchIdList *possible_cpus;
121
dc->reset = aspeed_sdhci_reset;
48
int n, sbsa_max_cpus;
122
dc->vmsd = &vmstate_aspeed_sdhci;
49
123
+ device_class_set_props(dc, aspeed_sdhci_properties);
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
124
}
51
- error_report("sbsa-ref: CPU type other than the built-in "
125
52
- "cortex-a57 not supported");
126
static TypeInfo aspeed_sdhci_info = {
53
+ if (!cpu_type_valid(machine->cpu_type)) {
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
55
exit(1);
56
}
57
127
--
58
--
128
2.20.1
59
2.20.1
129
60
130
61
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Initialise another SDHCI model instance for the AST2600's eMMC
3
Dump the collected random data after a randomness test failure.
4
controller and use the SDHCI's num_slots value introduced previously to
5
determine whether we should create an SD card instance for the new slot.
6
4
7
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
5
Note that this relies on the test having called
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
assertion failure.
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
11
Message-id: 20200114103433.30534-3-clg@kaod.org
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
[ clg : - removed ternary operator from sdhci_attach_drive()
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
- renamed SDHCI objects with a '-controller' prefix ]
11
[PMM: minor commit message tweak]
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
13
---
17
include/hw/arm/aspeed_soc.h | 2 ++
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
18
hw/arm/aspeed.c | 26 +++++++++++++++++---------
15
1 file changed, 12 insertions(+)
19
hw/arm/aspeed_ast2600.c | 29 ++++++++++++++++++++++++++---
20
3 files changed, 45 insertions(+), 12 deletions(-)
21
16
22
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/aspeed_soc.h
19
--- a/tests/qtest/npcm7xx_rng-test.c
25
+++ b/include/hw/arm/aspeed_soc.h
20
+++ b/tests/qtest/npcm7xx_rng-test.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
21
@@ -XXX,XX +XXX,XX @@
27
AspeedGPIOState gpio;
22
28
AspeedGPIOState gpio_1_8v;
23
#include "libqtest-single.h"
29
AspeedSDHCIState sdhci;
24
#include "qemu/bitops.h"
30
+ AspeedSDHCIState emmc;
25
+#include "qemu-common.h"
31
} AspeedSoCState;
26
32
27
#define RNG_BASE_ADDR 0xf000b000
33
#define TYPE_ASPEED_SOC "aspeed-soc"
28
34
@@ -XXX,XX +XXX,XX @@ enum {
29
@@ -XXX,XX +XXX,XX @@
35
ASPEED_MII4,
30
/* Number of bits to collect for randomness tests. */
36
ASPEED_SDRAM,
31
#define TEST_INPUT_BITS (128)
37
ASPEED_XDMA,
32
38
+ ASPEED_EMMC,
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
39
};
40
41
#endif /* ASPEED_SOC_H */
42
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/aspeed.c
45
+++ b/hw/arm/aspeed.c
46
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
47
}
48
}
49
50
+static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
51
+{
34
+{
52
+ DeviceState *card;
35
+ if (g_test_failed()) {
53
+
36
+ qemu_hexdump(stderr, "", buf, size);
54
+ card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
37
+ }
55
+ TYPE_SD_CARD);
56
+ if (dinfo) {
57
+ qdev_prop_set_drive(card, "drive", blk_by_legacy_dinfo(dinfo),
58
+ &error_fatal);
59
+ }
60
+ object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
61
+}
38
+}
62
+
39
+
63
static void aspeed_machine_init(MachineState *machine)
40
static void rng_writeb(unsigned int offset, uint8_t value)
64
{
41
{
65
AspeedBoardState *bmc;
42
writeb(RNG_BASE_ADDR + offset, value);
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
67
}
44
}
68
45
69
for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
70
- SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
47
+ dump_buf_if_failed(buf, sizeof(buf));
71
- DriveInfo *dinfo = drive_get_next(IF_SD);
48
}
72
- BlockBackend *blk;
49
73
- DeviceState *card;
50
/*
74
+ sdhci_attach_drive(&bmc->soc.sdhci.slots[i], drive_get_next(IF_SD));
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
75
+ }
76
77
- blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
78
- card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
79
- TYPE_SD_CARD);
80
- qdev_prop_set_drive(card, "drive", blk, &error_fatal);
81
- object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
82
+ if (bmc->soc.emmc.num_slots) {
83
+ sdhci_attach_drive(&bmc->soc.emmc.slots[0], drive_get_next(IF_SD));
84
}
52
}
85
53
86
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
87
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
88
index XXXXXXX..XXXXXXX 100644
56
}
89
--- a/hw/arm/aspeed_ast2600.c
57
90
+++ b/hw/arm/aspeed_ast2600.c
58
/*
91
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
92
[ASPEED_ADC] = 0x1E6E9000,
93
[ASPEED_VIDEO] = 0x1E700000,
94
[ASPEED_SDHCI] = 0x1E740000,
95
+ [ASPEED_EMMC] = 0x1E750000,
96
[ASPEED_GPIO] = 0x1E780000,
97
[ASPEED_GPIO_1_8V] = 0x1E780800,
98
[ASPEED_RTC] = 0x1E781000,
99
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
100
101
#define ASPEED_SOC_AST2600_MAX_IRQ 128
102
103
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
104
static const int aspeed_soc_ast2600_irqmap[] = {
105
[ASPEED_UART1] = 47,
106
[ASPEED_UART2] = 48,
107
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2600_irqmap[] = {
108
[ASPEED_ADC] = 78,
109
[ASPEED_XDMA] = 6,
110
[ASPEED_SDHCI] = 43,
111
+ [ASPEED_EMMC] = 15,
112
[ASPEED_GPIO] = 40,
113
[ASPEED_GPIO_1_8V] = 11,
114
[ASPEED_RTC] = 13,
115
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
116
sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v),
117
sizeof(s->gpio_1_8v), typename);
118
119
- sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
120
- TYPE_ASPEED_SDHCI);
121
+ sysbus_init_child_obj(obj, "sd-controller", OBJECT(&s->sdhci),
122
+ sizeof(s->sdhci), TYPE_ASPEED_SDHCI);
123
124
object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
125
126
/* Init sd card slot class here so that they're under the correct parent */
127
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
128
- sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
129
+ sysbus_init_child_obj(obj, "sd-controller.sdhci[*]",
130
+ OBJECT(&s->sdhci.slots[i]),
131
sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
132
}
60
}
133
+
61
134
+ sysbus_init_child_obj(obj, "emmc-controller", OBJECT(&s->emmc),
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
135
+ sizeof(s->emmc), TYPE_ASPEED_SDHCI);
63
+ dump_buf_if_failed(buf, sizeof(buf));
136
+
137
+ object_property_set_int(OBJECT(&s->emmc), 1, "num-slots", &error_abort);
138
+
139
+ sysbus_init_child_obj(obj, "emmc-controller.sdhci",
140
+ OBJECT(&s->emmc.slots[0]), sizeof(s->emmc.slots[0]),
141
+ TYPE_SYSBUS_SDHCI);
142
}
64
}
143
65
144
/*
66
/*
145
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
146
sc->memmap[ASPEED_SDHCI]);
68
}
147
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
69
148
aspeed_soc_get_irq(s, ASPEED_SDHCI));
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
149
+
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
150
+ /* eMMC */
151
+ object_property_set_bool(OBJECT(&s->emmc), true, "realized", &err);
152
+ if (err) {
153
+ error_propagate(errp, err);
154
+ return;
155
+ }
156
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emmc), 0, sc->memmap[ASPEED_EMMC]);
157
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
158
+ aspeed_soc_get_irq(s, ASPEED_EMMC));
159
}
72
}
160
73
161
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
74
int main(int argc, char **argv)
162
--
75
--
163
2.20.1
76
2.20.1
164
77
165
78
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
3
We should use printf format specifier "%u" instead of "%d" for
4
Message-id: 20200120101023.16030-3-drjones@redhat.com
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
hw/arm/virt.c | 1 +
12
hw/misc/imx25_ccm.c | 12 ++++++------
9
1 file changed, 1 insertion(+)
13
1 file changed, 6 insertions(+), 6 deletions(-)
10
14
11
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/virt.c
17
--- a/hw/misc/imx25_ccm.c
14
+++ b/hw/arm/virt.c
18
+++ b/hw/misc/imx25_ccm.c
15
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
16
20
case IMX25_CCM_LPIMR1_REG:
17
static void virt_machine_4_2_options(MachineClass *mc)
21
return "lpimr1";
18
{
22
default:
19
+ virt_machine_5_0_options(mc);
23
- sprintf(unknown, "[%d ?]", reg);
20
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
24
+ sprintf(unknown, "[%u ?]", reg);
25
return unknown;
26
}
21
}
27
}
22
DEFINE_VIRT_MACHINE(4, 2)
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
30
}
31
32
- DPRINTF("freq = %d\n", freq);
33
+ DPRINTF("freq = %u\n", freq);
34
35
return freq;
36
}
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
38
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
40
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
72
}
23
--
73
--
24
2.20.1
74
2.20.1
25
75
26
76
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
3
We should use printf format specifier "%u" instead of "%d" for
4
Message-id: 20200120101023.16030-2-drjones@redhat.com
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/kvm_arm.h | 46 ++++++++++++++++++++++++++------------------
12
hw/misc/imx31_ccm.c | 14 +++++++-------
9
1 file changed, 27 insertions(+), 19 deletions(-)
13
hw/misc/imx_ccm.c | 4 ++--
14
2 files changed, 9 insertions(+), 9 deletions(-)
10
15
11
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/kvm_arm.h
18
--- a/hw/misc/imx31_ccm.c
14
+++ b/target/arm/kvm_arm.h
19
+++ b/hw/misc/imx31_ccm.c
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
16
int kvm_arm_vcpu_init(CPUState *cs);
21
case IMX31_CCM_PDR2_REG:
17
22
return "PDR2";
18
/**
23
default:
19
- * kvm_arm_vcpu_finalize
24
- sprintf(unknown, "[%d ?]", reg);
20
+ * kvm_arm_vcpu_finalize:
25
+ sprintf(unknown, "[%u ?]", reg);
21
* @cs: CPUState
26
return unknown;
22
- * @feature: int
27
}
23
+ * @feature: feature to finalize
28
}
24
*
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
25
* Finalizes the configuration of the specified VCPU feature by
30
freq = CKIH_FREQ;
26
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
31
}
27
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
32
28
int kvm_arm_init_cpreg_list(ARMCPU *cpu);
33
- DPRINTF("freq = %d\n", freq);
29
34
+ DPRINTF("freq = %u\n", freq);
30
/**
35
31
- * kvm_arm_reg_syncs_via_cpreg_list
36
return freq;
32
- * regidx: KVM register index
37
}
33
+ * kvm_arm_reg_syncs_via_cpreg_list:
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
34
+ * @regidx: KVM register index
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
35
*
40
imx31_ccm_get_pll_ref_clk(dev));
36
* Return true if this KVM register should be synchronized via the
41
37
* cpreg list of arbitrary system registers, false if it is synchronized
42
- DPRINTF("freq = %d\n", freq);
38
@@ -XXX,XX +XXX,XX @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu);
43
+ DPRINTF("freq = %u\n", freq);
39
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
44
40
45
return freq;
41
/**
46
}
42
- * kvm_arm_cpreg_level
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
43
- * regidx: KVM register index
48
freq = imx31_ccm_get_mpll_clk(dev);
44
+ * kvm_arm_cpreg_level:
49
}
45
+ * @regidx: KVM register index
50
46
*
51
- DPRINTF("freq = %d\n", freq);
47
* Return the level of this coprocessor/system register. Return value is
52
+ DPRINTF("freq = %u\n", freq);
48
* either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE.
53
49
@@ -XXX,XX +XXX,XX @@ void kvm_arm_init_serror_injection(CPUState *cs);
54
return freq;
50
* @cpu: ARMCPU
55
}
51
*
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
52
* Get VCPU related state from kvm.
57
freq = imx31_ccm_get_mcu_main_clk(dev)
53
+ *
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
54
+ * Returns: 0 if success else < 0 error code
59
55
*/
60
- DPRINTF("freq = %d\n", freq);
56
int kvm_get_vcpu_events(ARMCPU *cpu);
61
+ DPRINTF("freq = %u\n", freq);
57
62
58
@@ -XXX,XX +XXX,XX @@ int kvm_get_vcpu_events(ARMCPU *cpu);
63
return freq;
59
* @cpu: ARMCPU
64
}
60
*
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
61
* Put VCPU related state to kvm.
66
freq = imx31_ccm_get_hclk_clk(dev)
62
+ *
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
63
+ * Returns: 0 if success else < 0 error code
68
64
*/
69
- DPRINTF("freq = %d\n", freq);
65
int kvm_put_vcpu_events(ARMCPU *cpu);
70
+ DPRINTF("freq = %u\n", freq);
66
71
67
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUFeatures {
72
return freq;
68
73
}
69
/**
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
70
* kvm_arm_get_host_cpu_features:
75
break;
71
- * @ahcc: ARMHostCPUClass to fill in
76
}
72
+ * @ahcf: ARMHostCPUClass to fill in
77
73
*
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
74
* Probe the capabilities of the host kernel's preferred CPU and fill
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
75
* in the ARMHostCPUClass struct accordingly.
80
76
+ *
81
return freq;
77
+ * Returns true on success and false otherwise.
82
}
78
*/
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
79
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
84
index XXXXXXX..XXXXXXX 100644
80
85
--- a/hw/misc/imx_ccm.c
81
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
86
+++ b/hw/misc/imx_ccm.c
82
bool kvm_arm_aarch32_supported(CPUState *cs);
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
83
88
freq = klass->get_clock_frequency(dev, clock);
84
/**
89
}
85
- * bool kvm_arm_pmu_supported:
90
86
+ * kvm_arm_pmu_supported:
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
87
* @cs: CPUState
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
88
*
93
89
* Returns: true if the KVM VCPU can enable its PMU
94
return freq;
90
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cs);
95
}
91
bool kvm_arm_pmu_supported(CPUState *cs);
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
92
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
93
/**
98
(mfd * pd)) << 10;
94
- * bool kvm_arm_sve_supported:
99
95
+ * kvm_arm_sve_supported:
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
96
* @cs: CPUState
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
97
*
102
freq);
98
* Returns true if the KVM VCPU can enable SVE and false otherwise.
103
99
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(CPUState *cs);
104
return freq;
100
bool kvm_arm_sve_supported(CPUState *cs);
101
102
/**
103
- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
104
- * IPA address space supported by KVM
105
- *
106
+ * kvm_arm_get_max_vm_ipa_size:
107
* @ms: Machine state handle
108
+ *
109
+ * Returns the number of bits in the IPA address space supported by KVM
110
*/
111
int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
112
113
/**
114
- * kvm_arm_sync_mpstate_to_kvm
115
+ * kvm_arm_sync_mpstate_to_kvm:
116
* @cpu: ARMCPU
117
*
118
* If supported set the KVM MP_STATE based on QEMU's model.
119
+ *
120
+ * Returns 0 on success and -1 on failure.
121
*/
122
int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
123
124
/**
125
- * kvm_arm_sync_mpstate_to_qemu
126
+ * kvm_arm_sync_mpstate_to_qemu:
127
* @cpu: ARMCPU
128
*
129
* If supported get the MP_STATE from KVM and store in QEMU's model.
130
+ *
131
+ * Returns 0 on success and aborts on failure.
132
*/
133
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
134
135
@@ -XXX,XX +XXX,XX @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
136
137
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
138
{
139
- /* This should never actually be called in the "not KVM" case,
140
+ /*
141
+ * This should never actually be called in the "not KVM" case,
142
* but set up the fields to indicate an error anyway.
143
*/
144
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
145
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
146
*
147
* Return: TRUE if any hardware breakpoints in use.
148
*/
149
-
150
bool kvm_arm_hw_debug_active(CPUState *cs);
151
152
/**
153
* kvm_arm_copy_hw_debug_data:
154
- *
155
* @ptr: kvm_guest_debug_arch structure
156
*
157
* Copy the architecture specific debug registers into the
158
* kvm_guest_debug ioctl structure.
159
*/
160
struct kvm_guest_debug_arch;
161
-
162
void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr);
163
164
/**
165
- * its_class_name
166
+ * its_class_name:
167
*
168
* Return the ITS class name to use depending on whether KVM acceleration
169
* and KVM CAP_SIGNAL_MSI are supported
170
--
105
--
171
2.20.1
106
2.20.1
172
107
173
108
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Provide a temporary device_legacy_reset function doing what
3
We should use printf format specifier "%u" instead of "%d" for
4
device_reset does to prepare for the transition with Resettable
4
argument of type "unsigned int".
5
API.
6
5
7
All occurrence of device_reset in the code tree are also replaced
6
Reported-by: Euler Robot <euler.robot@huawei.com>
8
by device_legacy_reset.
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
9
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
10
The new resettable API has different prototype and semantics
11
(resetting child buses as well as the specified device). Subsequent
12
commits will make the changeover for each call site individually; once
13
that is complete device_legacy_reset() will be removed.
14
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Acked-by: David Gibson <david@gibson.dropbear.id.au>
19
Acked-by: Cornelia Huck <cohuck@redhat.com>
20
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20200123132823.1117486-2-damien.hedde@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
11
---
25
include/hw/qdev-core.h | 4 ++--
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
26
hw/audio/intel-hda.c | 2 +-
13
hw/misc/imx6_src.c | 2 +-
27
hw/core/qdev.c | 6 +++---
14
2 files changed, 11 insertions(+), 11 deletions(-)
28
hw/hyperv/hyperv.c | 2 +-
29
hw/i386/microvm.c | 2 +-
30
hw/i386/pc.c | 2 +-
31
hw/ide/microdrive.c | 8 ++++----
32
hw/intc/spapr_xive.c | 2 +-
33
hw/ppc/pnv_psi.c | 4 ++--
34
hw/ppc/spapr_pci.c | 2 +-
35
hw/ppc/spapr_vio.c | 2 +-
36
hw/s390x/s390-pci-inst.c | 2 +-
37
hw/scsi/vmw_pvscsi.c | 2 +-
38
hw/sd/omap_mmc.c | 2 +-
39
hw/sd/pl181.c | 2 +-
40
15 files changed, 22 insertions(+), 22 deletions(-)
41
15
42
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
43
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/qdev-core.h
18
--- a/hw/misc/imx6_ccm.c
45
+++ b/include/hw/qdev-core.h
19
+++ b/hw/misc/imx6_ccm.c
46
@@ -XXX,XX +XXX,XX @@ char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
47
void qdev_machine_init(void);
21
case CCM_CMEOR:
48
22
return "CMEOR";
49
/**
23
default:
50
- * @device_reset
24
- sprintf(unknown, "%d ?", reg);
51
+ * device_legacy_reset:
25
+ sprintf(unknown, "%u ?", reg);
52
*
26
return unknown;
53
* Reset a single device (by calling the reset method).
54
*/
55
-void device_reset(DeviceState *dev);
56
+void device_legacy_reset(DeviceState *dev);
57
58
void device_class_set_props(DeviceClass *dc, Property *props);
59
60
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/audio/intel-hda.c
63
+++ b/hw/audio/intel-hda.c
64
@@ -XXX,XX +XXX,XX @@ static void intel_hda_reset(DeviceState *dev)
65
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
66
DeviceState *qdev = kid->child;
67
cdev = HDA_CODEC_DEVICE(qdev);
68
- device_reset(DEVICE(cdev));
69
+ device_legacy_reset(DEVICE(cdev));
70
d->state_sts |= (1 << cdev->cad);
71
}
72
intel_hda_update_irq(d);
73
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/core/qdev.c
76
+++ b/hw/core/qdev.c
77
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
78
79
static int qdev_reset_one(DeviceState *dev, void *opaque)
80
{
81
- device_reset(dev);
82
+ device_legacy_reset(dev);
83
84
return 0;
85
}
86
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
87
}
88
}
89
if (dev->hotplugged) {
90
- device_reset(dev);
91
+ device_legacy_reset(dev);
92
}
93
dev->pending_deleted_event = false;
94
95
@@ -XXX,XX +XXX,XX @@ void device_class_set_parent_unrealize(DeviceClass *dc,
96
dc->unrealize = dev_unrealize;
97
}
98
99
-void device_reset(DeviceState *dev)
100
+void device_legacy_reset(DeviceState *dev)
101
{
102
DeviceClass *klass = DEVICE_GET_CLASS(dev);
103
104
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/hyperv/hyperv.c
107
+++ b/hw/hyperv/hyperv.c
108
@@ -XXX,XX +XXX,XX @@ void hyperv_synic_reset(CPUState *cs)
109
SynICState *synic = get_synic(cs);
110
111
if (synic) {
112
- device_reset(DEVICE(synic));
113
+ device_legacy_reset(DEVICE(synic));
114
}
27
}
115
}
28
}
116
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
117
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
30
case USB_ANALOG_DIGPROG:
118
index XXXXXXX..XXXXXXX 100644
31
return "USB_ANALOG_DIGPROG";
119
--- a/hw/i386/microvm.c
32
default:
120
+++ b/hw/i386/microvm.c
33
- sprintf(unknown, "%d ?", reg);
121
@@ -XXX,XX +XXX,XX @@ static void microvm_machine_reset(MachineState *machine)
34
+ sprintf(unknown, "%u ?", reg);
122
cpu = X86_CPU(cs);
35
return unknown;
123
124
if (cpu->apic_state) {
125
- device_reset(cpu->apic_state);
126
+ device_legacy_reset(cpu->apic_state);
127
}
128
}
36
}
129
}
37
}
130
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
39
freq *= 20;
40
}
41
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
48
freq = imx6_analog_get_pll2_clk(dev) * 18
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
131
index XXXXXXX..XXXXXXX 100644
111
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/i386/pc.c
112
--- a/hw/misc/imx6_src.c
133
+++ b/hw/i386/pc.c
113
+++ b/hw/misc/imx6_src.c
134
@@ -XXX,XX +XXX,XX @@ static void pc_machine_reset(MachineState *machine)
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
135
cpu = X86_CPU(cs);
115
case SRC_GPR10:
136
116
return "SRC_GPR10";
137
if (cpu->apic_state) {
117
default:
138
- device_reset(cpu->apic_state);
118
- sprintf(unknown, "%d ?", reg);
139
+ device_legacy_reset(cpu->apic_state);
119
+ sprintf(unknown, "%u ?", reg);
140
}
120
return unknown;
141
}
121
}
142
}
122
}
143
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/ide/microdrive.c
146
+++ b/hw/ide/microdrive.c
147
@@ -XXX,XX +XXX,XX @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
148
case 0x00:    /* Configuration Option Register */
149
s->opt = value & 0xcf;
150
if (value & OPT_SRESET) {
151
- device_reset(DEVICE(s));
152
+ device_legacy_reset(DEVICE(s));
153
}
154
md_interrupt_update(s);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
157
case 0xe:    /* Device Control */
158
s->ctrl = value;
159
if (value & CTRL_SRST) {
160
- device_reset(DEVICE(s));
161
+ device_legacy_reset(DEVICE(s));
162
}
163
md_interrupt_update(s);
164
break;
165
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_attach(PCMCIACardState *card)
166
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
167
md->io_base = 0x0;
168
169
- device_reset(DEVICE(md));
170
+ device_legacy_reset(DEVICE(md));
171
md_interrupt_update(md);
172
173
return 0;
174
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_detach(PCMCIACardState *card)
175
{
176
MicroDriveState *md = MICRODRIVE(card);
177
178
- device_reset(DEVICE(md));
179
+ device_legacy_reset(DEVICE(md));
180
return 0;
181
}
182
183
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/hw/intc/spapr_xive.c
186
+++ b/hw/intc/spapr_xive.c
187
@@ -XXX,XX +XXX,XX @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
188
return H_PARAMETER;
189
}
190
191
- device_reset(DEVICE(xive));
192
+ device_legacy_reset(DEVICE(xive));
193
194
if (kvm_irqchip_in_kernel()) {
195
Error *local_err = NULL;
196
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/ppc/pnv_psi.c
199
+++ b/hw/ppc/pnv_psi.c
200
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_reset(DeviceState *dev)
201
202
static void pnv_psi_reset_handler(void *dev)
203
{
204
- device_reset(DEVICE(dev));
205
+ device_legacy_reset(DEVICE(dev));
206
}
207
208
static void pnv_psi_realize(DeviceState *dev, Error **errp)
209
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
210
break;
211
case PSIHB9_INTERRUPT_CONTROL:
212
if (val & PSIHB9_IRQ_RESET) {
213
- device_reset(DEVICE(&psi9->source));
214
+ device_legacy_reset(DEVICE(&psi9->source));
215
}
216
psi->regs[reg] = val;
217
break;
218
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/ppc/spapr_pci.c
221
+++ b/hw/ppc/spapr_pci.c
222
@@ -XXX,XX +XXX,XX @@ static int spapr_phb_children_reset(Object *child, void *opaque)
223
DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
224
225
if (dev) {
226
- device_reset(dev);
227
+ device_legacy_reset(dev);
228
}
229
230
return 0;
231
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
232
index XXXXXXX..XXXXXXX 100644
233
--- a/hw/ppc/spapr_vio.c
234
+++ b/hw/ppc/spapr_vio.c
235
@@ -XXX,XX +XXX,XX @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
236
static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
237
{
238
if (dev->tcet) {
239
- device_reset(DEVICE(dev->tcet));
240
+ device_legacy_reset(DEVICE(dev->tcet));
241
}
242
free_crq(dev);
243
}
244
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/hw/s390x/s390-pci-inst.c
247
+++ b/hw/s390x/s390-pci-inst.c
248
@@ -XXX,XX +XXX,XX @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
249
stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
250
goto out;
251
}
252
- device_reset(DEVICE(pbdev));
253
+ device_legacy_reset(DEVICE(pbdev));
254
pbdev->fh &= ~FH_MASK_ENABLE;
255
pbdev->state = ZPCI_FS_DISABLED;
256
stl_p(&ressetpci->fh, pbdev->fh);
257
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/hw/scsi/vmw_pvscsi.c
260
+++ b/hw/scsi/vmw_pvscsi.c
261
@@ -XXX,XX +XXX,XX @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
262
263
if (sdev != NULL) {
264
s->resetting++;
265
- device_reset(&sdev->qdev);
266
+ device_legacy_reset(&sdev->qdev);
267
s->resetting--;
268
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
269
}
270
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
271
index XXXXXXX..XXXXXXX 100644
272
--- a/hw/sd/omap_mmc.c
273
+++ b/hw/sd/omap_mmc.c
274
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
275
* into any bus, and we must reset it manually. When omap_mmc is
276
* QOMified this must move into the QOM reset function.
277
*/
278
- device_reset(DEVICE(host->card));
279
+ device_legacy_reset(DEVICE(host->card));
280
}
281
282
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
283
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
284
index XXXXXXX..XXXXXXX 100644
285
--- a/hw/sd/pl181.c
286
+++ b/hw/sd/pl181.c
287
@@ -XXX,XX +XXX,XX @@ static void pl181_reset(DeviceState *d)
288
/* Since we're still using the legacy SD API the card is not plugged
289
* into any bus, and we must reset it manually.
290
*/
291
- device_reset(DEVICE(s->card));
292
+ device_legacy_reset(DEVICE(s->card));
293
}
294
295
static void pl181_init(Object *obj)
296
--
123
--
297
2.20.1
124
2.20.1
298
125
299
126
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
In qdev_set_parent_bus(), when changing the parent bus of a
3
We should use printf format specifier "%u" instead of "%d" for
4
realized device, if the source and destination buses are not in the
4
argument of type "unsigned int".
5
same reset state, some adaptations are required. This patch adds
6
needed call to resettable_change_parent() to make sure a device reset
7
state stays coherent with its parent bus.
8
5
9
The addition is a no-op if:
6
Reported-by: Euler Robot <euler.robot@huawei.com>
10
1. the device being parented is not realized.
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
11
2. the device is realized, but both buses are not under reset.
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
12
13
Case 2 means that as long as qdev_set_parent_bus() is called
14
during the machine realization procedure (which is before the
15
machine reset so nothing is in reset), it is a no op.
16
17
There are 52 call sites of qdev_set_parent_bus(). All but one fall
18
into the no-op case:
19
+ 29 trivial calls related to virtio (in hw/{s390x,display,virtio}/
20
{vhost,virtio}-xxx.c) to set a vdev(or vgpu) composing device
21
parent bus just before realizing the same vdev(vgpu).
22
+ hw/core/qdev.c: when creating a device in qdev_try_create()
23
+ hw/core/sysbus.c: when initializing a device in the sysbus
24
+ hw/i386/amd_iommu.c: before realizing AMDVIState/pci
25
+ hw/isa/piix4.c: before realizing PIIX4State/rtc
26
+ hw/misc/auxbus.c: when creating an AUXBus
27
+ hw/misc/auxbus.c: when creating an AUXBus child
28
+ hw/misc/macio/macio.c: when initializing a MACIOState child
29
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/pmu
30
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/cuda
31
+ hw/net/virtio-net.c: Used for migration when using the failover
32
mechanism to migration a vfio-pci/net. It is
33
a no-op because at this point the device is
34
already on the bus.
35
+ hw/pci-host/designware.c: before realizing DesignwarePCIEHost/root
36
+ hw/pci-host/gpex.c: before realizing GPEXHost/root
37
+ hw/pci-host/prep.c: when initialiazing PREPPCIState/pci_dev
38
+ hw/pci-host/q35.c: before realizing Q35PCIHost/mch
39
+ hw/pci-host/versatile.c: when initializing PCIVPBState/pci_dev
40
+ hw/pci-host/xilinx-pcie.c: before realizing XilinxPCIEHost/root
41
+ hw/s390x/event-facility.c: when creating SCLPEventFacility/
42
TYPE_SCLP_QUIESCE
43
+ hw/s390x/event-facility.c: ditto with SCLPEventFacility/
44
TYPE_SCLP_CPU_HOTPLUG
45
+ hw/s390x/sclp.c: Not trivial because it is called on a SLCPDevice
46
just after realizing it. Ok because at this point the destination
47
bus (sysbus) is not in reset; the realize step is before the
48
machine reset.
49
+ hw/sd/core.c: Not OK. Used in sdbus_reparent_card(). See below.
50
+ hw/ssi/ssi.c: Used to put spi slave on spi bus and connect the cs
51
line in ssi_auto_connect_slave(). Ok because this function is only
52
used in realize step in hw/ssi/aspeed_smc.ci, hw/ssi/imx_spi.c,
53
hw/ssi/mss-spi.c, hw/ssi/xilinx_spi.c and hw/ssi/xilinx_spips.c.
54
+ hw/xen/xen-legacy-backend.c: when creating a XenLegacyDevice device
55
+ qdev-monitor.c: in device hotplug creation procedure before realize
56
57
Note that this commit alone will have no effect, right now there is no
58
use of resettable API to reset anything. So a bus will never be tagged
59
as in-reset by this same API.
60
61
The one place where side-effect will occurs is in hw/sd/core.c in
62
sdbus_reparent_card(). This function is only used in the raspi machines,
63
including during the sysbus reset procedure. This case will be
64
carrefully handled when doing the multiple phase reset transition.
65
66
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
67
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
68
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
69
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
70
Message-id: 20200123132823.1117486-7-damien.hedde@greensocs.com
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
72
---
11
---
73
hw/core/qdev.c | 16 +++++++++++-----
12
hw/misc/imx6ul_ccm.c | 4 ++--
74
1 file changed, 11 insertions(+), 5 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
75
14
76
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
77
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/core/qdev.c
17
--- a/hw/misc/imx6ul_ccm.c
79
+++ b/hw/core/qdev.c
18
+++ b/hw/misc/imx6ul_ccm.c
80
@@ -XXX,XX +XXX,XX @@ static void bus_add_child(BusState *bus, DeviceState *child)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
81
20
case CCM_CMEOR:
82
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
21
return "CMEOR";
83
{
22
default:
84
- bool replugging = dev->parent_bus != NULL;
23
- sprintf(unknown, "%d ?", reg);
85
+ BusState *old_parent_bus = dev->parent_bus;
24
+ sprintf(unknown, "%u ?", reg);
86
25
return unknown;
87
- if (replugging) {
88
+ if (old_parent_bus) {
89
trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
90
- dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
91
+ old_parent_bus, object_get_typename(OBJECT(old_parent_bus)),
92
OBJECT(bus), object_get_typename(OBJECT(bus)));
93
/*
94
* Keep a reference to the device while it's not plugged into
95
* any bus, to avoid it potentially evaporating when it is
96
* dereffed in bus_remove_child().
97
+ * Also keep the ref of the parent bus until the end, so that
98
+ * we can safely call resettable_change_parent() below.
99
*/
100
object_ref(OBJECT(dev));
101
bus_remove_child(dev->parent_bus, dev);
102
- object_unref(OBJECT(dev->parent_bus));
103
}
26
}
104
dev->parent_bus = bus;
27
}
105
object_ref(OBJECT(bus));
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
106
bus_add_child(bus, dev);
29
case USB_ANALOG_DIGPROG:
107
- if (replugging) {
30
return "USB_ANALOG_DIGPROG";
108
+ if (dev->realized) {
31
default:
109
+ resettable_change_parent(OBJECT(dev), OBJECT(bus),
32
- sprintf(unknown, "%d ?", reg);
110
+ OBJECT(old_parent_bus));
33
+ sprintf(unknown, "%u ?", reg);
111
+ }
34
return unknown;
112
+ if (old_parent_bus) {
113
+ object_unref(OBJECT(old_parent_bus));
114
object_unref(OBJECT(dev));
115
}
35
}
116
}
36
}
117
--
37
--
118
2.20.1
38
2.20.1
119
39
120
40
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
2
Private Peripheral Bus range, which includes all of the memory mapped
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
2
9
3
This commit make use of the resettable API to reset the device being
10
The architecture is clear that within the SCS unimplemented registers
4
hotplugged when it is realized. Also it ensures it is put in a reset
11
should be RES0 for privileged accesses and generate BusFault for
5
state coherent with the parent it is plugged into.
12
unprivileged accesses, and we currently implement this.
6
13
7
Note that there is a difference in the reset. Instead of resetting
14
It is less clear about how to handle accesses to unimplemented
8
only the hotplugged device, we reset also its subtree (switch to
15
regions of the wider PPB. Unprivileged accesses should definitely
9
resettable API). This is not expected to be a problem because
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
10
sub-buses are just realized too. If a hotplugged device has any
17
not given as a general rule. However, the register definitions of
11
sub-buses it is logical to reset them too at this point.
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
12
23
13
The recently added should_be_hidden and PCI's partially_hotplugged
24
Expand the container MemoryRegion that the NVIC exposes so that
14
mechanisms do not interfere with realize operation:
25
it covers the whole PPB space. This means:
15
+ In the should_be_hidden use case, device creation is
26
* moving the address that the ARMV7M device maps it to down by
16
delayed.
27
0xe000 bytes
17
+ The partially_hotplugged mechanism prevents a device to be
28
* moving the off and the offsets within the container of all the
18
unplugged and unrealized from qdev POV and unrealized.
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
19
33
20
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
23
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24
Message-id: 20200123132823.1117486-8-damien.hedde@greensocs.com
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
37
---
27
include/hw/resettable.h | 11 +++++++++++
38
include/hw/intc/armv7m_nvic.h | 1 +
28
hw/core/qdev.c | 15 ++++++++++++++-
39
hw/arm/armv7m.c | 2 +-
29
2 files changed, 25 insertions(+), 1 deletion(-)
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
30
42
31
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
32
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/resettable.h
45
--- a/include/hw/intc/armv7m_nvic.h
34
+++ b/include/hw/resettable.h
46
+++ b/include/hw/intc/armv7m_nvic.h
35
@@ -XXX,XX +XXX,XX @@ struct ResettableState {
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
36
bool exit_phase_in_progress;
48
MemoryRegion systickmem;
49
MemoryRegion systick_ns_mem;
50
MemoryRegion container;
51
+ MemoryRegion defaultmem;
52
53
uint32_t num_irq;
54
qemu_irq excpout;
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/armv7m.c
58
+++ b/hw/arm/armv7m.c
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
60
sysbus_connect_irq(sbd, 0,
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
62
63
- memory_region_add_subregion(&s->container, 0xe000e000,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
65
sysbus_mmio_get_region(sbd, 0));
66
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
.endianness = DEVICE_NATIVE_ENDIAN,
37
};
74
};
38
75
39
+/**
76
+/*
40
+ * resettable_state_clear:
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
41
+ * Clear the state. It puts the state to the initial (zeroed) state required
78
+ * accesses, and fault for non-privileged accesses.
42
+ * to reuse an object. Typically used in realize step of base classes
43
+ * implementing the interface.
44
+ */
79
+ */
45
+static inline void resettable_state_clear(ResettableState *state)
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
46
+{
83
+{
47
+ memset(state, 0, sizeof(ResettableState));
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
85
+ (uint32_t)addr);
86
+ if (attrs.user) {
87
+ return MEMTX_ERROR;
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
48
+}
91
+}
49
+
92
+
50
/**
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
51
* resettable_reset:
94
+ uint64_t value, unsigned size,
52
* Trigger a reset on an object @obj of type @type. @obj must implement
95
+ MemTxAttrs attrs)
53
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
96
+{
54
index XXXXXXX..XXXXXXX 100644
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
55
--- a/hw/core/qdev.c
98
+ (uint32_t)addr);
56
+++ b/hw/core/qdev.c
99
+ if (attrs.user) {
57
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
100
+ return MEMTX_ERROR;
58
}
101
+ }
59
}
102
+ return MEMTX_OK;
60
103
+}
61
+ /*
62
+ * Clear the reset state, in case the object was previously unrealized
63
+ * with a dirty state.
64
+ */
65
+ resettable_state_clear(&dev->reset);
66
+
104
+
67
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
105
+static const MemoryRegionOps ppb_default_ops = {
68
object_property_set_bool(OBJECT(bus), true, "realized",
106
+ .read_with_attrs = ppb_default_read,
69
&local_err);
107
+ .write_with_attrs = ppb_default_write,
70
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
71
}
109
+ .valid.min_access_size = 1,
72
}
110
+ .valid.max_access_size = 8,
73
if (dev->hotplugged) {
111
+};
74
- device_legacy_reset(dev);
112
+
75
+ /*
113
static int nvic_post_load(void *opaque, int version_id)
76
+ * Reset the device, as well as its subtree which, at this point,
114
{
77
+ * should be realized too.
115
NVICState *s = opaque;
78
+ */
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
79
+ resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
80
+ resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
118
{
81
+ NULL);
119
NVICState *s = NVIC(dev);
82
+ resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
120
- int regionlen;
83
}
121
84
dev->pending_deleted_event = false;
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
126
}
127
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
129
+ /*
130
+ * This device provides a single sysbus memory region which
131
+ * represents the whole of the "System PPB" space. This is the
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
133
+ * the System Control Space (system registers), the systick timer,
134
+ * and for CPUs with the Security extension an NS banked version
135
+ * of all of these.
136
+ *
137
+ * The default behaviour for unimplemented registers/ranges
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
140
+ * access.
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
85
194
86
--
195
--
87
2.20.1
196
2.20.1
88
197
89
198
diff view generated by jsdifflib
New patch
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
1
4
5
This is another feature which is just in the generic "in v8.1M" set
6
and has no ID register field indicating its presence.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 7 ++++++-
13
1 file changed, 6 insertions(+), 1 deletion(-)
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 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
20
} else {
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
23
+ bool pxn = false;
24
+
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
27
+ }
28
29
if (m_is_system_region(env, address)) {
30
/* System space is always execute never */
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
32
}
33
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
35
- if (*prot && !xn) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
37
*prot |= PAGE_EXEC;
38
}
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
The num-lines property of the TYPE_OR_GATE device sets the number
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
of input lines it has. An assert() in or_irq_realize() restricts
2
via the has_el3 CPU object property, which we create if the CPU
3
this to the maximum supported by the implementation. However we
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
got the condition in the assert wrong: it should be using <=,
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
because num-lines == MAX_OR_LINES is permitted, and means that
5
the ID_PFR1 and ID_AA64PFR0 registers.
6
all entries from 0 to MAX_OR_LINES-1 in the s->levels[] array
7
are used.
8
6
9
We didn't notice this previously because no user has so far
7
This codepath was incorrectly being taken for M-profile CPUs, which
10
needed that many input lines.
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
11
11
12
Reported-by: Guenter Roeck <linux@roeck-us.net>
12
Restrict the handling of the feature flag to A/R-profile cores.
13
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
16
Message-id: 20200120142235.10432-1-peter.maydell@linaro.org
17
---
17
---
18
hw/core/or-irq.c | 2 +-
18
target/arm/cpu.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
19
1 file changed, 1 insertion(+), 1 deletion(-)
20
20
21
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/core/or-irq.c
23
--- a/target/arm/cpu.c
24
+++ b/hw/core/or-irq.c
24
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ static void or_irq_realize(DeviceState *dev, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
26
{
26
}
27
qemu_or_irq *s = OR_IRQ(dev);
27
}
28
28
29
- assert(s->num_lines < MAX_OR_LINES);
29
- if (!cpu->has_el3) {
30
+ assert(s->num_lines <= MAX_OR_LINES);
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
32
* feature.
33
}
33
*/
34
--
34
--
35
2.20.1
35
2.20.1
36
36
37
37
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
2
2
registers if there is an active floating point context.
3
The overhead for the OpenBMC firmware images using the a custom U-Boot
3
This requires support in write_neon_element32() for the MO_32
4
is around 2 seconds, which is fine, but with a U-Boot from mainline,
4
element size, so add it.
5
it takes an extra 50 seconds or so to reach Linux. A quick survey on
5
6
the number of reads performed on the flash memory region gives the
6
Because we want to use arm_gen_condlabel(), we need to move
7
following figures :
7
the definition of that function up in translate.c so it is
8
8
before the #include of translate-vfp.c.inc.
9
OpenBMC U-Boot 922478 (~ 3.5 MBytes)
9
10
Mainline U-Boot 20569977 (~ 80 MBytes)
11
12
QEMU must be trashing the TCG TBs and reloading text very often. Some
13
addresses are read more than 250.000 times. Until we find a solution
14
to improve boot time, execution from MMIO is not activated by default.
15
16
Setting this option also breaks migration compatibility.
17
18
Signed-off-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20200114103433.30534-5-clg@kaod.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
23
---
13
---
24
include/hw/arm/aspeed.h | 2 ++
14
target/arm/cpu.h | 9 ++++
25
hw/arm/aspeed.c | 44 ++++++++++++++++++++++++++++++++++++-----
15
target/arm/m-nocp.decode | 8 +++-
26
2 files changed, 41 insertions(+), 5 deletions(-)
16
target/arm/translate.c | 21 +++++----
27
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
28
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
18
4 files changed, 111 insertions(+), 11 deletions(-)
29
index XXXXXXX..XXXXXXX 100644
19
30
--- a/include/hw/arm/aspeed.h
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
+++ b/include/hw/arm/aspeed.h
21
index XXXXXXX..XXXXXXX 100644
32
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardState AspeedBoardState;
22
--- a/target/arm/cpu.h
33
23
+++ b/target/arm/cpu.h
34
typedef struct AspeedMachine {
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
35
MachineState parent_obj;
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
36
+
26
}
37
+ bool mmio_exec;
27
38
} AspeedMachine;
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
39
40
#define ASPEED_MACHINE_CLASS(klass) \
41
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/aspeed.c
44
+++ b/hw/arm/aspeed.c
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
46
* SoC and 128MB for the AST2500 SoC, which is twice as big as
47
* needed by the flash modules of the Aspeed machines.
48
*/
49
- memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
50
- fl->size, &error_abort);
51
- memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
52
- boot_rom);
53
- write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
54
+ if (ASPEED_MACHINE(machine)->mmio_exec) {
55
+ memory_region_init_alias(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
56
+ &fl->mmio, 0, fl->size);
57
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
58
+ boot_rom);
59
+ } else {
60
+ memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
61
+ fl->size, &error_abort);
62
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
63
+ boot_rom);
64
+ write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
65
+ }
66
}
67
68
aspeed_board_binfo.ram_size = ram_size;
69
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
70
/* Bus 11: TODO ucd90160@64 */
71
}
72
73
+static bool aspeed_get_mmio_exec(Object *obj, Error **errp)
74
+{
29
+{
75
+ return ASPEED_MACHINE(obj)->mmio_exec;
30
+ /*
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
76
+}
35
+}
77
+
36
+
78
+static void aspeed_set_mmio_exec(Object *obj, bool value, Error **errp)
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
38
{
39
/* Sadly this is encoded differently for A-profile and M-profile */
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
71
72
+/* Generate a label used for skipping this instruction */
73
+static void arm_gen_condlabel(DisasContext *s)
79
+{
74
+{
80
+ ASPEED_MACHINE(obj)->mmio_exec = value;
75
+ if (!s->condjmp) {
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
81
+}
79
+}
82
+
80
+
83
+static void aspeed_machine_instance_init(Object *obj)
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
97
98
-/* Generate a label used for skipping this instruction */
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
115
return true;
116
}
117
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
84
+{
119
+{
85
+ ASPEED_MACHINE(obj)->mmio_exec = false;
120
+ int btmreg, topreg;
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
128
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
131
+ unallocated_encoding(s);
132
+ return true;
133
+ }
134
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
86
+}
200
+}
87
+
201
+
88
+static void aspeed_machine_class_props_init(ObjectClass *oc)
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
89
+{
203
{
90
+ object_class_property_add_bool(oc, "execute-in-place",
204
/*
91
+ aspeed_get_mmio_exec,
92
+ aspeed_set_mmio_exec, &error_abort);
93
+ object_class_property_set_description(oc, "execute-in-place",
94
+ "boot directly from CE0 flash device", &error_abort);
95
+}
96
+
97
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
98
{
99
MachineClass *mc = MACHINE_CLASS(oc);
100
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
101
mc->no_floppy = 1;
102
mc->no_cdrom = 1;
103
mc->no_parallel = 1;
104
+
105
+ aspeed_machine_class_props_init(oc);
106
}
107
108
static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
109
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
110
.name = TYPE_ASPEED_MACHINE,
111
.parent = TYPE_MACHINE,
112
.instance_size = sizeof(AspeedMachine),
113
+ .instance_init = aspeed_machine_instance_init,
114
.class_size = sizeof(AspeedMachineClass),
115
.class_init = aspeed_machine_class_init,
116
.abstract = true,
117
--
205
--
118
2.20.1
206
2.20.1
119
207
120
208
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
2
the general-purpose registers and APSR. Implement this.
2
3
3
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
4
The encoding is a subset of the LDMIA T2 encoding, using what would
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
be Rn=0b1111 (which UNDEFs for LDMIA).
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200123132823.1117486-10-damien.hedde@greensocs.com
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
docs/devel/index.rst | 1 +
11
target/arm/t32.decode | 6 +++++-
10
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++++++
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
11
2 files changed, 290 insertions(+)
13
2 files changed, 43 insertions(+), 1 deletion(-)
12
create mode 100644 docs/devel/reset.rst
13
14
14
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/devel/index.rst
17
--- a/target/arm/t32.decode
17
+++ b/docs/devel/index.rst
18
+++ b/target/arm/t32.decode
18
@@ -XXX,XX +XXX,XX @@ Contents:
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
19
tcg
20
20
tcg-plugins
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
21
bitops
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
22
+ reset
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
23
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
24
+{
24
new file mode 100644
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
25
index XXXXXXX..XXXXXXX
26
+ CLRM 1110 1000 1001 1111 list:16
26
--- /dev/null
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
27
+++ b/docs/devel/reset.rst
28
+}
28
@@ -XXX,XX +XXX,XX @@
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
30
31
&rfe !extern rn w pu
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
37
return do_ldm(s, a, 1);
38
}
39
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
41
+{
42
+ int i;
43
+ TCGv_i32 zero;
29
+
44
+
30
+=======================================
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
31
+Reset in QEMU: the Resettable interface
46
+ return false;
32
+=======================================
33
+
34
+The reset of qemu objects is handled using the resettable interface declared
35
+in ``include/hw/resettable.h``.
36
+
37
+This interface allows objects to be grouped (on a tree basis); so that the
38
+whole group can be reset consistently. Each individual member object does not
39
+have to care about others; in particular, problems of order (which object is
40
+reset first) are addressed.
41
+
42
+As of now DeviceClass and BusClass implement this interface.
43
+
44
+
45
+Triggering reset
46
+----------------
47
+
48
+This section documents the APIs which "users" of a resettable object should use
49
+to control it. All resettable control functions must be called while holding
50
+the iothread lock.
51
+
52
+You can apply a reset to an object using ``resettable_assert_reset()``. You need
53
+to call ``resettable_release_reset()`` to release the object from reset. To
54
+instantly reset an object, without keeping it in reset state, just call
55
+``resettable_reset()``. These functions take two parameters: a pointer to the
56
+object to reset and a reset type.
57
+
58
+Several types of reset will be supported. For now only cold reset is defined;
59
+others may be added later. The Resettable interface handles reset types with an
60
+enum:
61
+
62
+``RESET_TYPE_COLD``
63
+ Cold reset is supported by every resettable object. In QEMU, it means we reset
64
+ to the initial state corresponding to the start of QEMU; this might differ
65
+ from what is a real hardware cold reset. It differs from other resets (like
66
+ warm or bus resets) which may keep certain parts untouched.
67
+
68
+Calling ``resettable_reset()`` is equivalent to calling
69
+``resettable_assert_reset()`` then ``resettable_release_reset()``. It is
70
+possible to interleave multiple calls to these three functions. There may
71
+be several reset sources/controllers of a given object. The interface handles
72
+everything and the different reset controllers do not need to know anything
73
+about each others. The object will leave reset state only when each other
74
+controllers end their reset operation. This point is handled internally by
75
+maintaining a count of in-progress resets; it is crucial to call
76
+``resettable_release_reset()`` one time and only one time per
77
+``resettable_assert_reset()`` call.
78
+
79
+For now migration of a device or bus in reset is not supported. Care must be
80
+taken not to delay ``resettable_release_reset()`` after its
81
+``resettable_assert_reset()`` counterpart.
82
+
83
+Note that, since resettable is an interface, the API takes a simple Object as
84
+parameter. Still, it is a programming error to call a resettable function on a
85
+non-resettable object and it will trigger a run time assert error. Since most
86
+calls to resettable interface are done through base class functions, such an
87
+error is not likely to happen.
88
+
89
+For Devices and Buses, the following helper functions exist:
90
+
91
+- ``device_cold_reset()``
92
+- ``bus_cold_reset()``
93
+
94
+These are simple wrappers around resettable_reset() function; they only cast the
95
+Device or Bus into an Object and pass the cold reset type. When possible
96
+prefer to use these functions instead of ``resettable_reset()``.
97
+
98
+Device and bus functions co-exist because there can be semantic differences
99
+between resetting a bus and resetting the controller bridge which owns it.
100
+For example, consider a SCSI controller. Resetting the controller puts all
101
+its registers back to what reset state was as well as reset everything on the
102
+SCSI bus, whereas resetting just the SCSI bus only resets everything that's on
103
+it but not the controller.
104
+
105
+
106
+Multi-phase mechanism
107
+---------------------
108
+
109
+This section documents the internals of the resettable interface.
110
+
111
+The resettable interface uses a multi-phase system to relieve objects and
112
+machines from reset ordering problems. To address this, the reset operation
113
+of an object is split into three well defined phases.
114
+
115
+When resetting several objects (for example the whole machine at simulation
116
+startup), all first phases of all objects are executed, then all second phases
117
+and then all third phases.
118
+
119
+The three phases are:
120
+
121
+1. The **enter** phase is executed when the object enters reset. It resets only
122
+ local state of the object; it must not do anything that has a side-effect
123
+ on other objects, such as raising or lowering a qemu_irq line or reading or
124
+ writing guest memory.
125
+
126
+2. The **hold** phase is executed for entry into reset, once every object in the
127
+ group which is being reset has had its *enter* phase executed. At this point
128
+ devices can do actions that affect other objects.
129
+
130
+3. The **exit** phase is executed when the object leaves the reset state.
131
+ Actions affecting other objects are permitted.
132
+
133
+As said in previous section, the interface maintains a count of reset. This
134
+count is used to ensure phases are executed only when required. *enter* and
135
+*hold* phases are executed only when asserting reset for the first time
136
+(if an object is already in reset state when calling
137
+``resettable_assert_reset()`` or ``resettable_reset()``, they are not
138
+executed).
139
+The *exit* phase is executed only when the last reset operation ends. Therefore
140
+the object does not need to care how many of reset controllers it has and how
141
+many of them have started a reset.
142
+
143
+
144
+Handling reset in a resettable object
145
+-------------------------------------
146
+
147
+This section documents the APIs that an implementation of a resettable object
148
+must provide and what functions it has access to. It is intended for people
149
+who want to implement or convert a class which has the resettable interface;
150
+for example when specializing an existing device or bus.
151
+
152
+Methods to implement
153
+....................
154
+
155
+Three methods should be defined or left empty. Each method corresponds to a
156
+phase of the reset; they are name ``phases.enter()``, ``phases.hold()`` and
157
+``phases.exit()``. They all take the object as parameter. The *enter* method
158
+also take the reset type as second parameter.
159
+
160
+When extending an existing class, these methods may need to be extended too.
161
+The ``resettable_class_set_parent_phases()`` class function may be used to
162
+backup parent class methods.
163
+
164
+Here follows an example to implement reset for a Device which sets an IO while
165
+in reset.
166
+
167
+::
168
+
169
+ static void mydev_reset_enter(Object *obj, ResetType type)
170
+ {
171
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
172
+ MyDevState *mydev = MYDEV(obj);
173
+ /* call parent class enter phase */
174
+ if (myclass->parent_phases.enter) {
175
+ myclass->parent_phases.enter(obj, type);
176
+ }
177
+ /* initialize local state only */
178
+ mydev->var = 0;
179
+ }
47
+ }
180
+
48
+
181
+ static void mydev_reset_hold(Object *obj)
49
+ if (extract32(a->list, 13, 1)) {
182
+ {
50
+ return false;
183
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
184
+ MyDevState *mydev = MYDEV(obj);
185
+ /* call parent class hold phase */
186
+ if (myclass->parent_phases.hold) {
187
+ myclass->parent_phases.hold(obj);
188
+ }
189
+ /* set an IO */
190
+ qemu_set_irq(mydev->irq, 1);
191
+ }
51
+ }
192
+
52
+
193
+ static void mydev_reset_exit(Object *obj)
53
+ if (!a->list) {
194
+ {
54
+ /* UNPREDICTABLE; we choose to UNDEF */
195
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
55
+ return false;
196
+ MyDevState *mydev = MYDEV(obj);
197
+ /* call parent class exit phase */
198
+ if (myclass->parent_phases.exit) {
199
+ myclass->parent_phases.exit(obj);
200
+ }
201
+ /* clear an IO */
202
+ qemu_set_irq(mydev->irq, 0);
203
+ }
56
+ }
204
+
57
+
205
+ typedef struct MyDevClass {
58
+ zero = tcg_const_i32(0);
206
+ MyParentClass parent_class;
59
+ for (i = 0; i < 15; i++) {
207
+ /* to store eventual parent reset methods */
60
+ if (extract32(a->list, i, 1)) {
208
+ ResettablePhases parent_phases;
61
+ /* Clear R[i] */
209
+ } MyDevClass;
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
63
+ }
64
+ }
65
+ if (extract32(a->list, 15, 1)) {
66
+ /*
67
+ * Clear APSR (by calling the MSR helper with the same argument
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
69
+ */
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
72
+ tcg_temp_free_i32(maskreg);
73
+ }
74
+ tcg_temp_free_i32(zero);
75
+ return true;
76
+}
210
+
77
+
211
+ static void mydev_class_init(ObjectClass *class, void *data)
78
/*
212
+ {
79
* Branch, branch with link
213
+ MyDevClass *myclass = MYDEV_CLASS(class);
80
*/
214
+ ResettableClass *rc = RESETTABLE_CLASS(class);
215
+ resettable_class_set_parent_reset_phases(rc,
216
+ mydev_reset_enter,
217
+ mydev_reset_hold,
218
+ mydev_reset_exit,
219
+ &myclass->parent_phases);
220
+ }
221
+
222
+In the above example, we override all three phases. It is possible to override
223
+only some of them by passing NULL instead of a function pointer to
224
+``resettable_class_set_parent_reset_phases()``. For example, the following will
225
+only override the *enter* phase and leave *hold* and *exit* untouched::
226
+
227
+ resettable_class_set_parent_reset_phases(rc, mydev_reset_enter,
228
+ NULL, NULL,
229
+ &myclass->parent_phases);
230
+
231
+This is equivalent to providing a trivial implementation of the hold and exit
232
+phases which does nothing but call the parent class's implementation of the
233
+phase.
234
+
235
+Polling the reset state
236
+.......................
237
+
238
+Resettable interface provides the ``resettable_is_in_reset()`` function.
239
+This function returns true if the object parameter is currently under reset.
240
+
241
+An object is under reset from the beginning of the *init* phase to the end of
242
+the *exit* phase. During all three phases, the function will return that the
243
+object is in reset.
244
+
245
+This function may be used if the object behavior has to be adapted
246
+while in reset state. For example if a device has an irq input,
247
+it will probably need to ignore it while in reset; then it can for
248
+example check the reset state at the beginning of the irq callback.
249
+
250
+Note that until migration of the reset state is supported, an object
251
+should not be left in reset. So apart from being currently executing
252
+one of the reset phases, the only cases when this function will return
253
+true is if an external interaction (like changing an io) is made during
254
+*hold* or *exit* phase of another object in the same reset group.
255
+
256
+Helpers ``device_is_in_reset()`` and ``bus_is_in_reset()`` are also provided
257
+for devices and buses and should be preferred.
258
+
259
+
260
+Base class handling of reset
261
+----------------------------
262
+
263
+This section documents parts of the reset mechanism that you only need to know
264
+about if you are extending it to work with a new base class other than
265
+DeviceClass or BusClass, or maintaining the existing code in those classes. Most
266
+people can ignore it.
267
+
268
+Methods to implement
269
+....................
270
+
271
+There are two other methods that need to exist in a class implementing the
272
+interface: ``get_state()`` and ``child_foreach()``.
273
+
274
+``get_state()`` is simple. *resettable* is an interface and, as a consequence,
275
+does not have any class state structure. But in order to factorize the code, we
276
+need one. This method must return a pointer to ``ResettableState`` structure.
277
+The structure must be allocated by the base class; preferably it should be
278
+located inside the object instance structure.
279
+
280
+``child_foreach()`` is more complex. It should execute the given callback on
281
+every reset child of the given resettable object. All children must be
282
+resettable too. Additional parameters (a reset type and an opaque pointer) must
283
+be passed to the callback too.
284
+
285
+In ``DeviceClass`` and ``BusClass`` the ``ResettableState`` is located
286
+``DeviceState`` and ``BusState`` structure. ``child_foreach()`` is implemented
287
+to follow the bus hierarchy; for a bus, it calls the function on every child
288
+device; for a device, it calls the function on every bus child. When we reset
289
+the main system bus, we reset the whole machine bus tree.
290
+
291
+Changing a resettable parent
292
+............................
293
+
294
+One thing which should be taken care of by the base class is handling reset
295
+hierarchy changes.
296
+
297
+The reset hierarchy is supposed to be static and built during machine creation.
298
+But there are actually some exceptions. To cope with this, the resettable API
299
+provides ``resettable_change_parent()``. This function allows to set, update or
300
+remove the parent of a resettable object after machine creation is done. As
301
+parameters, it takes the object being moved, the old parent if any and the new
302
+parent if any.
303
+
304
+This function can be used at any time when not in a reset operation. During
305
+a reset operation it must be used only in *hold* phase. Using it in *enter* or
306
+*exit* phase is an error.
307
+Also it should not be used during machine creation, although it is harmless to
308
+do so: the function is a no-op as long as old and new parent are NULL or not
309
+in reset.
310
+
311
+There is currently 2 cases where this function is used:
312
+
313
+1. *device hotplug*; it means a new device is introduced on a live bus.
314
+
315
+2. *hot bus change*; it means an existing live device is added, moved or
316
+ removed in the bus hierarchy. At the moment, it occurs only in the raspi
317
+ machines for changing the sdbus used by sd card.
318
--
81
--
319
2.20.1
82
2.20.1
320
83
321
84
diff view generated by jsdifflib
New patch
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
20
*/
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
22
+ if (a->reg != ARM_VFP_FPSCR) {
23
+ return false;
24
+ }
25
+ if (a->rt == 15 && !a->l) {
26
return false;
27
}
28
}
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
2
2
(access to the FP system registers), because all it needs to support
3
When a VM is stopped (such as when it's paused) guest virtual time
3
is the FPSCR. In v8.1M things become significantly more complicated
4
should stop counting. Otherwise, when the VM is resumed it will
4
in two ways:
5
experience time jumps and its kernel may report soft lockups. Not
5
6
counting virtual time while the VM is stopped has the side effect
6
* there are several new FP system registers; some have side effects
7
of making the guest's time appear to lag when compared with real
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
time, and even with time derived from the physical counter. For
8
vfp_access_check() and the "only if FPU implemented" check
9
this reason, this change, which is enabled by default, comes with
9
10
a KVM CPU feature allowing it to be disabled, restoring legacy
10
* all sysregs are now accessible both by VMRS/VMSR (which
11
behavior.
11
reads/writes a general purpose register) and also by VLDR/VSTR
12
12
(which reads/writes them directly to memory)
13
This patch only provides the implementation of the virtual time
13
14
adjustment. A subsequent patch will provide the CPU property
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
allowing the change to be enabled and disabled.
15
16
16
* keep the M-profile code entirely separate from the A-profile code
17
Reported-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com>
17
18
Signed-off-by: Andrew Jones <drjones@redhat.com>
18
* abstract out the "read or write the general purpose register" part
19
Message-id: 20200120101023.16030-6-drjones@redhat.com
19
of the code into a loadfn or storefn function pointer, so we can
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
reuse it for VLDR/VSTR.
21
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
22
---
25
---
23
target/arm/cpu.h | 7 ++++
26
target/arm/cpu.h | 3 +
24
target/arm/kvm_arm.h | 38 ++++++++++++++++++
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
25
target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
28
2 files changed, 171 insertions(+), 14 deletions(-)
26
target/arm/kvm32.c | 3 ++
27
target/arm/kvm64.c | 3 ++
28
target/arm/machine.c | 7 ++++
29
6 files changed, 150 insertions(+)
30
29
31
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
32
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu.h
32
--- a/target/arm/cpu.h
34
+++ b/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
35
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
36
/* KVM init features for this CPU */
35
#define ARM_VFP_FPINST 9
37
uint32_t kvm_init_features[7];
36
#define ARM_VFP_FPINST2 10
38
37
39
+ /* KVM CPU state */
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
40
+
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
41
+ /* KVM virtual time adjustment */
40
+
42
+ bool kvm_adjvtime;
41
/* iwMMXt coprocessor control registers. */
43
+ bool kvm_vtime_dirty;
42
#define ARM_IWMMXT_wCID 0
44
+ uint64_t kvm_vtime;
43
#define ARM_IWMMXT_wCon 1
45
+
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
46
/* Uniprocessor system with MP extensions */
47
bool mp_is_up;
48
49
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
50
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/kvm_arm.h
46
--- a/target/arm/translate-vfp.c.inc
52
+++ b/target/arm/kvm_arm.h
47
+++ b/target/arm/translate-vfp.c.inc
53
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level);
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
54
*/
49
return true;
55
bool write_kvmstate_to_list(ARMCPU *cpu);
50
}
56
51
57
+/**
52
+/*
58
+ * kvm_arm_cpu_pre_save:
53
+ * M-profile provides two different sets of instructions that can
59
+ * @cpu: ARMCPU
54
+ * access floating point system registers: VMSR/VMRS (which move
60
+ *
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
61
+ * Called after write_kvmstate_to_list() from cpu_pre_save() to update
56
+ * move directly to/from memory). In some cases there are also side
62
+ * the cpreg list with KVM CPU state.
57
+ * effects which must happen after any write to memory (which could
58
+ * cause an exception). So we implement the common logic for the
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
63
+ */
63
+ */
64
+void kvm_arm_cpu_pre_save(ARMCPU *cpu);
64
+
65
+
65
+/*
66
+/**
66
+ * Emit code to store the sysreg to its final destination; frees the
67
+ * kvm_arm_cpu_post_load:
67
+ * TCG temp 'value' it is passed.
68
+ * @cpu: ARMCPU
69
+ *
70
+ * Called from cpu_post_load() to update KVM CPU state from the cpreg list.
71
+ */
68
+ */
72
+void kvm_arm_cpu_post_load(ARMCPU *cpu);
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
73
+
70
+/*
74
/**
71
+ * Emit code to load the value to be copied to the sysreg; returns
75
* kvm_arm_reset_vcpu:
72
+ * a new TCG temporary
76
* @cpu: ARMCPU
77
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
78
*/
79
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
80
81
+/**
82
+ * kvm_arm_get_virtual_time:
83
+ * @cs: CPUState
84
+ *
85
+ * Gets the VCPU's virtual counter and stores it in the KVM CPU state.
86
+ */
73
+ */
87
+void kvm_arm_get_virtual_time(CPUState *cs);
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
88
+
75
+
89
+/**
76
+/* Common decode/access checks for fp sysreg read/write */
90
+ * kvm_arm_put_virtual_time:
77
+typedef enum FPSysRegCheckResult {
91
+ * @cs: CPUState
78
+ FPSysRegCheckFailed, /* caller should return false */
92
+ *
79
+ FPSysRegCheckDone, /* caller should return true */
93
+ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state.
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
94
+ */
81
+} FPSysRegCheckResult;
95
+void kvm_arm_put_virtual_time(CPUState *cs);
82
+
96
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
97
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state);
84
+{
98
+
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
99
int kvm_arm_vgic_probe(void);
86
+ return FPSysRegCheckFailed;
100
87
+ }
101
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
88
+
102
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
89
+ switch (regno) {
103
static inline void kvm_arm_pmu_init(CPUState *cs) {}
90
+ case ARM_VFP_FPSCR:
104
91
+ case QEMU_VFP_FPSCR_NZCV:
105
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {}
92
+ break;
106
+
93
+ default:
107
+static inline void kvm_arm_get_virtual_time(CPUState *cs) {}
94
+ return FPSysRegCheckFailed;
108
+static inline void kvm_arm_put_virtual_time(CPUState *cs) {}
95
+ }
109
#endif
96
+
110
97
+ if (!vfp_access_check(s)) {
111
static inline const char *gic_class_name(void)
98
+ return FPSysRegCheckDone;
112
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
99
+ }
113
index XXXXXXX..XXXXXXX 100644
100
+
114
--- a/target/arm/kvm.c
101
+ return FPSysRegCheckContinue;
115
+++ b/target/arm/kvm.c
102
+}
116
@@ -XXX,XX +XXX,XX @@ static int compare_u64(const void *a, const void *b)
103
+
117
return 0;
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
118
}
105
+
119
106
+ fp_sysreg_loadfn *loadfn,
120
+/*
107
+ void *opaque)
121
+ * cpreg_values are sorted in ascending order by KVM register ID
108
+{
122
+ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find
109
+ /* Do a write to an M-profile floating point system register */
123
+ * the storage for a KVM register by ID with a binary search.
110
+ TCGv_i32 tmp;
124
+ */
111
+
125
+static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
112
+ switch (fp_sysreg_checks(s, regno)) {
126
+{
113
+ case FPSysRegCheckFailed:
127
+ uint64_t *res;
114
+ return false;
128
+
115
+ case FPSysRegCheckDone:
129
+ res = bsearch(&regidx, cpu->cpreg_indexes, cpu->cpreg_array_len,
116
+ return true;
130
+ sizeof(uint64_t), compare_u64);
117
+ case FPSysRegCheckContinue:
131
+ assert(res);
118
+ break;
132
+
119
+ }
133
+ return &cpu->cpreg_values[res - cpu->cpreg_indexes];
120
+
134
+}
121
+ switch (regno) {
135
+
122
+ case ARM_VFP_FPSCR:
136
/* Initialize the ARMCPU cpreg list according to the kernel's
123
+ tmp = loadfn(s, opaque);
137
* definition of what CPU registers it knows about (and throw away
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
138
* the previous TCG-created cpreg list).
125
+ tcg_temp_free_i32(tmp);
139
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
126
+ gen_lookup_tb(s);
140
return ok;
127
+ break;
141
}
128
+ default:
142
129
+ g_assert_not_reached();
143
+void kvm_arm_cpu_pre_save(ARMCPU *cpu)
130
+ }
144
+{
131
+ return true;
145
+ /* KVM virtual time adjustment */
132
+}
146
+ if (cpu->kvm_vtime_dirty) {
133
+
147
+ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime;
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
148
+ }
135
+ fp_sysreg_storefn *storefn,
149
+}
136
+ void *opaque)
150
+
137
+{
151
+void kvm_arm_cpu_post_load(ARMCPU *cpu)
138
+ /* Do a read from an M-profile floating point system register */
152
+{
139
+ TCGv_i32 tmp;
153
+ /* KVM virtual time adjustment */
140
+
154
+ if (cpu->kvm_adjvtime) {
141
+ switch (fp_sysreg_checks(s, regno)) {
155
+ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
142
+ case FPSysRegCheckFailed:
156
+ cpu->kvm_vtime_dirty = true;
143
+ return false;
157
+ }
144
+ case FPSysRegCheckDone:
158
+}
145
+ return true;
159
+
146
+ case FPSysRegCheckContinue:
160
void kvm_arm_reset_vcpu(ARMCPU *cpu)
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
164
+ break;
165
+ default:
166
+ g_assert_not_reached();
167
+ }
168
+ return true;
169
+}
170
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
172
+{
173
+ arg_VMSR_VMRS *a = opaque;
174
+
175
+ if (a->rt == 15) {
176
+ /* Set the 4 flag bits in the CPSR */
177
+ gen_set_nzcv(value);
178
+ tcg_temp_free_i32(value);
179
+ } else {
180
+ store_reg(s, a->rt, value);
181
+ }
182
+}
183
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
185
+{
186
+ arg_VMSR_VMRS *a = opaque;
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
192
+{
193
+ /*
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
197
+ * we only care about the top 4 bits of FPSCR there.
198
+ */
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
161
{
217
{
162
int ret;
218
TCGv_i32 tmp;
163
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
219
bool ignore_vfp_enabled = false;
164
return 0;
220
165
}
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
166
222
- return false;
167
+void kvm_arm_get_virtual_time(CPUState *cs)
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
168
+{
224
+ return gen_M_VMSR_VMRS(s, a);
169
+ ARMCPU *cpu = ARM_CPU(cs);
170
+ struct kvm_one_reg reg = {
171
+ .id = KVM_REG_ARM_TIMER_CNT,
172
+ .addr = (uintptr_t)&cpu->kvm_vtime,
173
+ };
174
+ int ret;
175
+
176
+ if (cpu->kvm_vtime_dirty) {
177
+ return;
178
+ }
179
+
180
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
181
+ if (ret) {
182
+ error_report("Failed to get KVM_REG_ARM_TIMER_CNT");
183
+ abort();
184
+ }
185
+
186
+ cpu->kvm_vtime_dirty = true;
187
+}
188
+
189
+void kvm_arm_put_virtual_time(CPUState *cs)
190
+{
191
+ ARMCPU *cpu = ARM_CPU(cs);
192
+ struct kvm_one_reg reg = {
193
+ .id = KVM_REG_ARM_TIMER_CNT,
194
+ .addr = (uintptr_t)&cpu->kvm_vtime,
195
+ };
196
+ int ret;
197
+
198
+ if (!cpu->kvm_vtime_dirty) {
199
+ return;
200
+ }
201
+
202
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
203
+ if (ret) {
204
+ error_report("Failed to set KVM_REG_ARM_TIMER_CNT");
205
+ abort();
206
+ }
207
+
208
+ cpu->kvm_vtime_dirty = false;
209
+}
210
+
211
int kvm_put_vcpu_events(ARMCPU *cpu)
212
{
213
CPUARMState *env = &cpu->env;
214
@@ -XXX,XX +XXX,XX @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
215
return MEMTXATTRS_UNSPECIFIED;
216
}
217
218
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state)
219
+{
220
+ CPUState *cs = opaque;
221
+ ARMCPU *cpu = ARM_CPU(cs);
222
+
223
+ if (running) {
224
+ if (cpu->kvm_adjvtime) {
225
+ kvm_arm_put_virtual_time(cs);
226
+ }
227
+ } else {
228
+ if (cpu->kvm_adjvtime) {
229
+ kvm_arm_get_virtual_time(cs);
230
+ }
231
+ }
232
+}
233
234
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
235
{
236
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/target/arm/kvm32.c
239
+++ b/target/arm/kvm32.c
240
@@ -XXX,XX +XXX,XX @@
241
#include "qemu-common.h"
242
#include "cpu.h"
243
#include "qemu/timer.h"
244
+#include "sysemu/runstate.h"
245
#include "sysemu/kvm.h"
246
#include "kvm_arm.h"
247
#include "internals.h"
248
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
249
return -EINVAL;
250
}
225
}
251
226
252
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
253
+
228
- /*
254
/* Determine init features for this CPU */
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
255
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
256
if (cpu->start_powered_off) {
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
257
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
232
- */
258
index XXXXXXX..XXXXXXX 100644
233
- if (a->reg != ARM_VFP_FPSCR) {
259
--- a/target/arm/kvm64.c
234
- return false;
260
+++ b/target/arm/kvm64.c
235
- }
261
@@ -XXX,XX +XXX,XX @@
236
- if (a->rt == 15 && !a->l) {
262
#include "qemu/host-utils.h"
237
- return false;
263
#include "qemu/main-loop.h"
238
- }
264
#include "exec/gdbstub.h"
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
265
+#include "sysemu/runstate.h"
240
+ return false;
266
#include "sysemu/kvm.h"
267
#include "sysemu/kvm_int.h"
268
#include "kvm_arm.h"
269
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
270
return -EINVAL;
271
}
241
}
272
242
273
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
243
switch (a->reg) {
274
+
275
/* Determine init features for this CPU */
276
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
277
if (cpu->start_powered_off) {
278
diff --git a/target/arm/machine.c b/target/arm/machine.c
279
index XXXXXXX..XXXXXXX 100644
280
--- a/target/arm/machine.c
281
+++ b/target/arm/machine.c
282
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
283
/* This should never fail */
284
abort();
285
}
286
+
287
+ /*
288
+ * kvm_arm_cpu_pre_save() must be called after
289
+ * write_kvmstate_to_list()
290
+ */
291
+ kvm_arm_cpu_pre_save(cpu);
292
} else {
293
if (!write_cpustate_to_list(cpu, false)) {
294
/* This should never fail. */
295
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
296
* we're using it.
297
*/
298
write_list_to_cpustate(cpu);
299
+ kvm_arm_cpu_post_load(cpu);
300
} else {
301
if (!write_list_to_cpustate(cpu)) {
302
return -1;
303
--
244
--
304
2.20.1
245
2.20.1
305
246
306
247
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
The constant-expander functions like negate, plus_2, etc, are
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
2
4
3
Deprecate device_legacy_reset(), qdev_reset_all() and
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
qbus_reset_all() to be replaced by new functions
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
device_cold_reset() and bus_cold_reset() which uses resettable API.
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
8
---
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
10
1 file changed, 25 insertions(+), 21 deletions(-)
6
11
7
Also introduce resettable_cold_reset_fn() which may be used as a
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
8
replacement for qdev_reset_all_fn and qbus_reset_all_fn().
9
10
Following patches will be needed to look at legacy reset call sites
11
and switch to resettable api. The legacy functions will be removed
12
when unused.
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Message-id: 20200123132823.1117486-9-damien.hedde@greensocs.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++
23
include/hw/resettable.h | 9 +++++++++
24
hw/core/bus.c | 5 +++++
25
hw/core/qdev.c | 5 +++++
26
hw/core/resettable.c | 5 +++++
27
5 files changed, 51 insertions(+)
28
29
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
30
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/qdev-core.h
14
--- a/target/arm/translate.c
32
+++ b/include/hw/qdev-core.h
15
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ int qdev_walk_children(DeviceState *dev,
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
34
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
17
}
35
void *opaque);
18
}
36
19
37
+/**
20
+/*
38
+ * @qdev_reset_all:
21
+ * Constant expanders for the decoders.
39
+ * Reset @dev. See @qbus_reset_all() for more details.
40
+ *
41
+ * Note: This function is deprecated and will be removed when it becomes unused.
42
+ * Please use device_cold_reset() now.
43
+ */
22
+ */
44
void qdev_reset_all(DeviceState *dev);
45
void qdev_reset_all_fn(void *opaque);
46
47
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
48
* hard reset means that qbus_reset_all will reset all state of the device.
49
* For PCI devices, for example, this will include the base address registers
50
* or configuration space.
51
+ *
52
+ * Note: This function is deprecated and will be removed when it becomes unused.
53
+ * Please use bus_cold_reset() now.
54
*/
55
void qbus_reset_all(BusState *bus);
56
void qbus_reset_all_fn(void *opaque);
57
58
+/**
59
+ * device_cold_reset:
60
+ * Reset device @dev and perform a recursive processing using the resettable
61
+ * interface. It triggers a RESET_TYPE_COLD.
62
+ */
63
+void device_cold_reset(DeviceState *dev);
64
+
23
+
65
+/**
24
+static int negate(DisasContext *s, int x)
66
+ * bus_cold_reset:
67
+ *
68
+ * Reset bus @bus and perform a recursive processing using the resettable
69
+ * interface. It triggers a RESET_TYPE_COLD.
70
+ */
71
+void bus_cold_reset(BusState *bus);
72
+
73
/**
74
* device_is_in_reset:
75
* Return true if the device @dev is currently being reset.
76
@@ -XXX,XX +XXX,XX @@ void qdev_machine_init(void);
77
* device_legacy_reset:
78
*
79
* Reset a single device (by calling the reset method).
80
+ * Note: This function is deprecated and will be removed when it becomes unused.
81
+ * Please use device_cold_reset() now.
82
*/
83
void device_legacy_reset(DeviceState *dev);
84
85
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/hw/resettable.h
88
+++ b/include/hw/resettable.h
89
@@ -XXX,XX +XXX,XX @@ bool resettable_is_in_reset(Object *obj);
90
*/
91
void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
92
93
+/**
94
+ * resettable_cold_reset_fn:
95
+ * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD).
96
+ *
97
+ * This function is typically useful to register a reset handler with
98
+ * qemu_register_reset.
99
+ */
100
+void resettable_cold_reset_fn(void *opaque);
101
+
102
/**
103
* resettable_class_set_parent_phases:
104
*
105
diff --git a/hw/core/bus.c b/hw/core/bus.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/hw/core/bus.c
108
+++ b/hw/core/bus.c
109
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
110
return 0;
111
}
112
113
+void bus_cold_reset(BusState *bus)
114
+{
25
+{
115
+ resettable_reset(OBJECT(bus), RESET_TYPE_COLD);
26
+ return -x;
116
+}
27
+}
117
+
28
+
118
bool bus_is_in_reset(BusState *bus)
29
+static int plus_2(DisasContext *s, int x)
119
{
120
return resettable_is_in_reset(OBJECT(bus));
121
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/core/qdev.c
124
+++ b/hw/core/qdev.c
125
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
126
qbus_reset_all(bus);
127
}
128
129
+void device_cold_reset(DeviceState *dev)
130
+{
30
+{
131
+ resettable_reset(OBJECT(dev), RESET_TYPE_COLD);
31
+ return x + 2;
132
+}
32
+}
133
+
33
+
134
bool device_is_in_reset(DeviceState *dev)
34
+static int times_2(DisasContext *s, int x)
135
{
136
return resettable_is_in_reset(OBJECT(dev));
137
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/hw/core/resettable.c
140
+++ b/hw/core/resettable.c
141
@@ -XXX,XX +XXX,XX @@ void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
142
}
143
}
144
145
+void resettable_cold_reset_fn(void *opaque)
146
+{
35
+{
147
+ resettable_reset((Object *) opaque, RESET_TYPE_COLD);
36
+ return x * 2;
148
+}
37
+}
149
+
38
+
150
void resettable_class_set_parent_phases(ResettableClass *rc,
39
+static int times_4(DisasContext *s, int x)
151
ResettableEnterPhase enter,
40
+{
152
ResettableHoldPhase hold,
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
56
-{
57
- return -x;
58
-}
59
-
60
-static int plus_2(DisasContext *s, int x)
61
-{
62
- return x + 2;
63
-}
64
-
65
-static int times_2(DisasContext *s, int x)
66
-{
67
- return x * 2;
68
-}
69
-
70
-static int times_4(DisasContext *s, int x)
71
-{
72
- return x * 4;
73
-}
74
-
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
77
{
153
--
78
--
154
2.20.1
79
2.20.1
155
80
156
81
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
read or write FP system registers to memory.
2
3
3
This commit adds support of Resettable interface to buses and devices:
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
+ ResettableState structure is added in the Bus/Device state
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
+ Resettable methods are implemented.
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
6
+ device/bus_is_in_reset function defined
7
---
8
target/arm/vfp.decode | 14 ++++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
10
2 files changed, 105 insertions(+)
7
11
8
This commit allows to transition the objects to the new
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
9
multi-phase interface without changing the reset behavior at all.
10
Object single reset method can be split into the 3 different phases
11
but the 3 phases are still executed in a row for a given object.
12
From the qdev/qbus reset api point of view, nothing is changed.
13
qdev_reset_all() and qbus_reset_all() are not modified as well as
14
device_legacy_reset().
15
16
Transition of an object must be done from parent class to child class.
17
Care has been taken to allow the transition of a parent class
18
without requiring the child classes to be transitioned at the same
19
time. Note that SysBus and SysBusDevice class do not need any transition
20
because they do not override the legacy reset method.
21
22
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
27
Message-id: 20200123132823.1117486-5-damien.hedde@greensocs.com
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
30
tests/Makefile.include | 1 +
31
include/hw/qdev-core.h | 27 ++++++++++++
32
hw/core/bus.c | 97 ++++++++++++++++++++++++++++++++++++++++++
33
hw/core/qdev.c | 93 ++++++++++++++++++++++++++++++++++++++++
34
4 files changed, 218 insertions(+)
35
36
diff --git a/tests/Makefile.include b/tests/Makefile.include
37
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/Makefile.include
14
--- a/target/arm/vfp.decode
39
+++ b/tests/Makefile.include
15
+++ b/target/arm/vfp.decode
40
@@ -XXX,XX +XXX,XX @@ tests/fp/%:
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
41
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
42
    hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
43
    hw/core/bus.o \
19
44
+    hw/core/resettable.o \
20
+# M-profile VLDR/VSTR to sysreg
45
    hw/core/irq.o \
21
+%vldr_sysreg 22:1 13:3
46
    hw/core/fw-path-provider.o \
22
+%imm7_0x4 0:7 !function=times_4
47
    hw/core/reset.o \
23
+
48
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
24
+&vldr_sysreg rn reg imm a w p
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
27
+
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
49
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/qdev-core.h
39
--- a/target/arm/translate-vfp.c.inc
51
+++ b/include/hw/qdev-core.h
40
+++ b/target/arm/translate-vfp.c.inc
52
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
53
#include "qemu/bitmap.h"
42
return true;
54
#include "qom/object.h"
43
}
55
#include "hw/hotplug.h"
44
56
+#include "hw/resettable.h"
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
57
46
+{
58
enum {
47
+ arg_vldr_sysreg *a = opaque;
59
DEV_NVECTORS_UNSPECIFIED = -1,
48
+ uint32_t offset = a->imm;
60
@@ -XXX,XX +XXX,XX @@ typedef struct DeviceClass {
49
+ TCGv_i32 addr;
61
bool hotpluggable;
62
63
/* callbacks */
64
+ /*
65
+ * Reset method here is deprecated and replaced by methods in the
66
+ * resettable class interface to implement a multi-phase reset.
67
+ * TODO: remove once every reset callback is unused
68
+ */
69
DeviceReset reset;
70
DeviceRealize realize;
71
DeviceUnrealize unrealize;
72
@@ -XXX,XX +XXX,XX @@ struct NamedGPIOList {
73
/**
74
* DeviceState:
75
* @realized: Indicates whether the device has been fully constructed.
76
+ * @reset: ResettableState for the device; handled by Resettable interface.
77
*
78
* This structure should not be accessed directly. We declare it here
79
* so that it can be embedded in individual device state structures.
80
@@ -XXX,XX +XXX,XX @@ struct DeviceState {
81
int num_child_bus;
82
int instance_id_alias;
83
int alias_required_for_version;
84
+ ResettableState reset;
85
};
86
87
struct DeviceListener {
88
@@ -XXX,XX +XXX,XX @@ typedef struct BusChild {
89
/**
90
* BusState:
91
* @hotplug_handler: link to a hotplug handler associated with bus.
92
+ * @reset: ResettableState for the bus; handled by Resettable interface.
93
*/
94
struct BusState {
95
Object obj;
96
@@ -XXX,XX +XXX,XX @@ struct BusState {
97
int num_children;
98
QTAILQ_HEAD(, BusChild) children;
99
QLIST_ENTRY(BusState) sibling;
100
+ ResettableState reset;
101
};
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
105
void qbus_reset_all(BusState *bus);
106
void qbus_reset_all_fn(void *opaque);
107
108
+/**
109
+ * device_is_in_reset:
110
+ * Return true if the device @dev is currently being reset.
111
+ */
112
+bool device_is_in_reset(DeviceState *dev);
113
+
50
+
114
+/**
51
+ if (!a->a) {
115
+ * bus_is_in_reset:
52
+ offset = - offset;
116
+ * Return true if the bus @bus is currently being reset.
53
+ }
117
+ */
118
+bool bus_is_in_reset(BusState *bus);
119
+
54
+
120
/* This should go away once we get rid of the NULL bus hack */
55
+ addr = load_reg(s, a->rn);
121
BusState *sysbus_get_default(void);
56
+ if (a->p) {
122
57
+ tcg_gen_addi_i32(addr, addr, offset);
123
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev);
58
+ }
124
125
void device_class_set_props(DeviceClass *dc, Property *props);
126
127
+/**
128
+ * device_class_set_parent_reset:
129
+ * TODO: remove the function when DeviceClass's reset method
130
+ * is not used anymore.
131
+ */
132
void device_class_set_parent_reset(DeviceClass *dc,
133
DeviceReset dev_reset,
134
DeviceReset *parent_reset);
135
diff --git a/hw/core/bus.c b/hw/core/bus.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/core/bus.c
138
+++ b/hw/core/bus.c
139
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
140
return 0;
141
}
142
143
+bool bus_is_in_reset(BusState *bus)
144
+{
145
+ return resettable_is_in_reset(OBJECT(bus));
146
+}
147
+
59
+
148
+static ResettableState *bus_get_reset_state(Object *obj)
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
149
+{
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
150
+ BusState *bus = BUS(obj);
62
+ }
151
+ return &bus->reset;
152
+}
153
+
63
+
154
+static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb,
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
155
+ void *opaque, ResetType type)
65
+ MO_UL | MO_ALIGN | s->be_data);
156
+{
66
+ tcg_temp_free_i32(value);
157
+ BusState *bus = BUS(obj);
158
+ BusChild *kid;
159
+
67
+
160
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
68
+ if (a->w) {
161
+ cb(OBJECT(kid->child), opaque, type);
69
+ /* writeback */
70
+ if (!a->p) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
74
+ } else {
75
+ tcg_temp_free_i32(addr);
162
+ }
76
+ }
163
+}
77
+}
164
+
78
+
165
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
166
{
167
const char *typename = object_get_typename(OBJECT(bus));
168
@@ -XXX,XX +XXX,XX @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
169
return g_strdup(object_get_typename(OBJECT(dev)));
170
}
171
172
+/**
173
+ * bus_phases_reset:
174
+ * Transition reset method for buses to allow moving
175
+ * smoothly from legacy reset method to multi-phases
176
+ */
177
+static void bus_phases_reset(BusState *bus)
178
+{
80
+{
179
+ ResettableClass *rc = RESETTABLE_GET_CLASS(bus);
81
+ arg_vldr_sysreg *a = opaque;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
180
+
85
+
181
+ if (rc->phases.enter) {
86
+ if (!a->a) {
182
+ rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD);
87
+ offset = - offset;
183
+ }
88
+ }
184
+ if (rc->phases.hold) {
89
+
185
+ rc->phases.hold(OBJECT(bus));
90
+ addr = load_reg(s, a->rn);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
186
+ }
93
+ }
187
+ if (rc->phases.exit) {
94
+
188
+ rc->phases.exit(OBJECT(bus));
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
189
+ }
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
190
+}
112
+}
191
+
113
+
192
+static void bus_transitional_reset(Object *obj)
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
193
+{
115
+{
194
+ BusClass *bc = BUS_GET_CLASS(obj);
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
195
+
117
+ return false;
196
+ /*
197
+ * This will call either @bus_phases_reset (for multi-phases transitioned
198
+ * buses) or a bus's specific method for not-yet transitioned buses.
199
+ * In both case, it does not reset children.
200
+ */
201
+ if (bc->reset) {
202
+ bc->reset(BUS(obj));
203
+ }
118
+ }
119
+ if (a->rn == 15) {
120
+ return false;
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
204
+}
123
+}
205
+
124
+
206
+/**
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
207
+ * bus_get_transitional_reset:
208
+ * check if the bus's class is ready for multi-phase
209
+ */
210
+static ResettableTrFunction bus_get_transitional_reset(Object *obj)
211
+{
126
+{
212
+ BusClass *dc = BUS_GET_CLASS(obj);
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
213
+ if (dc->reset != bus_phases_reset) {
128
+ return false;
214
+ /*
215
+ * dc->reset has been overridden by a subclass,
216
+ * the bus is not ready for multi phase yet.
217
+ */
218
+ return bus_transitional_reset;
219
+ }
129
+ }
220
+ return NULL;
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
221
+}
134
+}
222
+
135
+
223
static void bus_class_init(ObjectClass *class, void *data)
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
224
{
137
{
225
BusClass *bc = BUS_CLASS(class);
138
TCGv_i32 tmp;
226
+ ResettableClass *rc = RESETTABLE_CLASS(class);
227
228
class->unparent = bus_unparent;
229
bc->get_fw_dev_path = default_bus_get_fw_dev_path;
230
+
231
+ rc->get_state = bus_get_reset_state;
232
+ rc->child_foreach = bus_reset_child_foreach;
233
+
234
+ /*
235
+ * @bus_phases_reset is put as the default reset method below, allowing
236
+ * to do the multi-phase transition from base classes to leaf classes. It
237
+ * allows a legacy-reset Bus class to extend a multi-phases-reset
238
+ * Bus class for the following reason:
239
+ * + If a base class B has been moved to multi-phase, then it does not
240
+ * override this default reset method and may have defined phase methods.
241
+ * + A child class C (extending class B) which uses
242
+ * bus_class_set_parent_reset() (or similar means) to override the
243
+ * reset method will still work as expected. @bus_phases_reset function
244
+ * will be registered as the parent reset method and effectively call
245
+ * parent reset phases.
246
+ */
247
+ bc->reset = bus_phases_reset;
248
+ rc->get_transitional_function = bus_get_transitional_reset;
249
}
250
251
static void qbus_finalize(Object *obj)
252
@@ -XXX,XX +XXX,XX @@ static const TypeInfo bus_info = {
253
.instance_init = qbus_initfn,
254
.instance_finalize = qbus_finalize,
255
.class_init = bus_class_init,
256
+ .interfaces = (InterfaceInfo[]) {
257
+ { TYPE_RESETTABLE_INTERFACE },
258
+ { }
259
+ },
260
};
261
262
static void bus_register_types(void)
263
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/hw/core/qdev.c
266
+++ b/hw/core/qdev.c
267
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
268
qbus_reset_all(bus);
269
}
270
271
+bool device_is_in_reset(DeviceState *dev)
272
+{
273
+ return resettable_is_in_reset(OBJECT(dev));
274
+}
275
+
276
+static ResettableState *device_get_reset_state(Object *obj)
277
+{
278
+ DeviceState *dev = DEVICE(obj);
279
+ return &dev->reset;
280
+}
281
+
282
+static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
283
+ void *opaque, ResetType type)
284
+{
285
+ DeviceState *dev = DEVICE(obj);
286
+ BusState *bus;
287
+
288
+ QLIST_FOREACH(bus, &dev->child_bus, sibling) {
289
+ cb(OBJECT(bus), opaque, type);
290
+ }
291
+}
292
+
293
/* can be used as ->unplug() callback for the simple cases */
294
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
295
DeviceState *dev, Error **errp)
296
@@ -XXX,XX +XXX,XX @@ device_vmstate_if_get_id(VMStateIf *obj)
297
return qdev_get_dev_path(dev);
298
}
299
300
+/**
301
+ * device_phases_reset:
302
+ * Transition reset method for devices to allow moving
303
+ * smoothly from legacy reset method to multi-phases
304
+ */
305
+static void device_phases_reset(DeviceState *dev)
306
+{
307
+ ResettableClass *rc = RESETTABLE_GET_CLASS(dev);
308
+
309
+ if (rc->phases.enter) {
310
+ rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
311
+ }
312
+ if (rc->phases.hold) {
313
+ rc->phases.hold(OBJECT(dev));
314
+ }
315
+ if (rc->phases.exit) {
316
+ rc->phases.exit(OBJECT(dev));
317
+ }
318
+}
319
+
320
+static void device_transitional_reset(Object *obj)
321
+{
322
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
323
+
324
+ /*
325
+ * This will call either @device_phases_reset (for multi-phases transitioned
326
+ * devices) or a device's specific method for not-yet transitioned devices.
327
+ * In both case, it does not reset children.
328
+ */
329
+ if (dc->reset) {
330
+ dc->reset(DEVICE(obj));
331
+ }
332
+}
333
+
334
+/**
335
+ * device_get_transitional_reset:
336
+ * check if the device's class is ready for multi-phase
337
+ */
338
+static ResettableTrFunction device_get_transitional_reset(Object *obj)
339
+{
340
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
341
+ if (dc->reset != device_phases_reset) {
342
+ /*
343
+ * dc->reset has been overridden by a subclass,
344
+ * the device is not ready for multi phase yet.
345
+ */
346
+ return device_transitional_reset;
347
+ }
348
+ return NULL;
349
+}
350
+
351
static void device_class_init(ObjectClass *class, void *data)
352
{
353
DeviceClass *dc = DEVICE_CLASS(class);
354
VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
355
+ ResettableClass *rc = RESETTABLE_CLASS(class);
356
357
class->unparent = device_unparent;
358
359
@@ -XXX,XX +XXX,XX @@ static void device_class_init(ObjectClass *class, void *data)
360
dc->hotpluggable = true;
361
dc->user_creatable = true;
362
vc->get_id = device_vmstate_if_get_id;
363
+ rc->get_state = device_get_reset_state;
364
+ rc->child_foreach = device_reset_child_foreach;
365
+
366
+ /*
367
+ * @device_phases_reset is put as the default reset method below, allowing
368
+ * to do the multi-phase transition from base classes to leaf classes. It
369
+ * allows a legacy-reset Device class to extend a multi-phases-reset
370
+ * Device class for the following reason:
371
+ * + If a base class B has been moved to multi-phase, then it does not
372
+ * override this default reset method and may have defined phase methods.
373
+ * + A child class C (extending class B) which uses
374
+ * device_class_set_parent_reset() (or similar means) to override the
375
+ * reset method will still work as expected. @device_phases_reset function
376
+ * will be registered as the parent reset method and effectively call
377
+ * parent reset phases.
378
+ */
379
+ dc->reset = device_phases_reset;
380
+ rc->get_transitional_function = device_get_transitional_reset;
381
382
object_class_property_add_bool(class, "realized",
383
device_get_realized, device_set_realized,
384
@@ -XXX,XX +XXX,XX @@ static const TypeInfo device_type_info = {
385
.class_size = sizeof(DeviceClass),
386
.interfaces = (InterfaceInfo[]) {
387
{ TYPE_VMSTATE_IF },
388
+ { TYPE_RESETTABLE_INTERFACE },
389
{ }
390
}
391
};
392
--
139
--
393
2.20.1
140
2.20.1
394
141
395
142
diff view generated by jsdifflib
New patch
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
1
6
7
Implement the register. Since we don't yet implement MVE, we handle
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
14
---
15
target/arm/cpu.h | 13 +++++++++++++
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
17
2 files changed, 40 insertions(+)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
31
+
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
34
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
36
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
38
#define ARM_VFP_FPEXC 8
39
#define ARM_VFP_FPINST 9
40
#define ARM_VFP_FPINST2 10
41
+/* These ones are M-profile only */
42
+#define ARM_VFP_FPSCR_NZCVQC 2
43
+#define ARM_VFP_VPR 12
44
+#define ARM_VFP_P0 13
45
+#define ARM_VFP_FPCXT_NS 14
46
+#define ARM_VFP_FPCXT_S 15
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
67
tcg_temp_free_i32(tmp);
68
gen_lookup_tb(s);
69
break;
70
+ case ARM_VFP_FPSCR_NZCVQC:
71
+ {
72
+ TCGv_i32 fpscr;
73
+ tmp = loadfn(s, opaque);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
86
default:
87
g_assert_not_reached();
88
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
New patch
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
*/
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
24
break;
25
default:
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
case ARM_VFP_FPSCR:
28
if (a->rt == 15) {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
} else {
33
tmp = tcg_temp_new_i32();
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
Factor out the code which handles M-profile lazy FP state preservation
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
2
7
3
Add a function resettable_change_parent() to do the required
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
plumbing when changing the parent a of Resettable object.
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
14
1 file changed, 27 insertions(+), 18 deletions(-)
5
15
6
We need to make sure that the reset state of the object remains
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
7
coherent with the reset state of the new parent.
8
9
We make the 2 following hypothesis:
10
+ when an object is put in a parent under reset, the object goes in
11
reset.
12
+ when an object is removed from a parent under reset, the object
13
leaves reset.
14
15
The added function avoids any glitch if both old and new parent are
16
already in reset.
17
18
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20200123132823.1117486-6-damien.hedde@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
include/hw/resettable.h | 16 +++++++++++
26
hw/core/resettable.c | 62 +++++++++++++++++++++++++++++++++++++++--
27
hw/core/trace-events | 1 +
28
3 files changed, 77 insertions(+), 2 deletions(-)
29
30
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
31
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/resettable.h
18
--- a/target/arm/translate-vfp.c.inc
33
+++ b/include/hw/resettable.h
19
+++ b/target/arm/translate-vfp.c.inc
34
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type);
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
35
*/
21
return offs;
36
bool resettable_is_in_reset(Object *obj);
22
}
37
23
38
+/**
24
+/*
39
+ * resettable_change_parent:
25
+ * Generate code for M-profile lazy FP state preservation if needed;
40
+ * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp.
26
+ * this corresponds to the pseudocode PreserveFPState() function.
41
+ * All 3 objects must implement resettable interface. @oldp or @newp may be
42
+ * NULL.
43
+ *
44
+ * This function will adapt the reset state of @obj so that it is coherent
45
+ * with the reset state of @newp. It may trigger @resettable_assert_reset()
46
+ * or @resettable_release_reset(). It will do such things only if the reset
47
+ * state of @newp and @oldp are different.
48
+ *
49
+ * When using this function during reset, it must only be called during
50
+ * a hold phase method. Calling this during enter or exit phase is an error.
51
+ */
27
+ */
52
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
28
+static void gen_preserve_fp_state(DisasContext *s)
53
+
54
/**
55
* resettable_class_set_parent_phases:
56
*
57
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/core/resettable.c
60
+++ b/hw/core/resettable.c
61
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
62
* enter_phase_in_progress:
63
* True if we are currently in reset enter phase.
64
*
65
- * Note: This flag is only used to guarantee (using asserts) that the reset
66
- * API is used correctly. We can use a global variable because we rely on the
67
+ * exit_phase_in_progress:
68
+ * count the number of exit phase we are in.
69
+ *
70
+ * Note: These flags are only used to guarantee (using asserts) that the reset
71
+ * API is used correctly. We can use global variables because we rely on the
72
* iothread mutex to ensure only one reset operation is in a progress at a
73
* given time.
74
*/
75
static bool enter_phase_in_progress;
76
+static unsigned exit_phase_in_progress;
77
78
void resettable_reset(Object *obj, ResetType type)
79
{
80
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type)
81
trace_resettable_reset_release_begin(obj, type);
82
assert(!enter_phase_in_progress);
83
84
+ exit_phase_in_progress += 1;
85
resettable_phase_exit(obj, NULL, type);
86
+ exit_phase_in_progress -= 1;
87
88
trace_resettable_reset_release_end(obj);
89
}
90
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
91
trace_resettable_phase_exit_end(obj, obj_typename, s->count);
92
}
93
94
+/*
95
+ * resettable_get_count:
96
+ * Get the count of the Resettable object @obj. Return 0 if @obj is NULL.
97
+ */
98
+static unsigned resettable_get_count(Object *obj)
99
+{
29
+{
100
+ if (obj) {
30
+ if (s->v7m_lspact) {
101
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
31
+ /*
102
+ return rc->get_state(obj)->count;
32
+ * Lazy state saving affects external memory and also the NVIC,
103
+ }
33
+ * so we must mark it as an IO operation for icount (and cause
104
+ return 0;
34
+ * this to be the last insn in the TB).
105
+}
35
+ */
106
+
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
107
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
108
+{
38
+ gen_io_start();
109
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
39
+ }
110
+ ResettableState *s = rc->get_state(obj);
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
111
+ unsigned newp_count = resettable_get_count(newp);
41
+ /*
112
+ unsigned oldp_count = resettable_get_count(oldp);
42
+ * If the preserve_fp_state helper doesn't throw an exception
113
+
43
+ * then it will clear LSPACT; we don't need to repeat this for
114
+ /*
44
+ * any further FP insns in this TB.
115
+ * Ensure we do not change parent when in enter or exit phase.
45
+ */
116
+ * During these phases, the reset subtree being updated is partly in reset
46
+ s->v7m_lspact = false;
117
+ * and partly not in reset (it depends on the actual position in
118
+ * resettable_child_foreach()s). We are not able to tell in which part is a
119
+ * leaving or arriving device. Thus we cannot set the reset count of the
120
+ * moving device to the proper value.
121
+ */
122
+ assert(!enter_phase_in_progress && !exit_phase_in_progress);
123
+ trace_resettable_change_parent(obj, oldp, oldp_count, newp, newp_count);
124
+
125
+ /*
126
+ * At most one of the two 'for' loops will be executed below
127
+ * in order to cope with the difference between the two counts.
128
+ */
129
+ /* if newp is more reset than oldp */
130
+ for (unsigned i = oldp_count; i < newp_count; i++) {
131
+ resettable_assert_reset(obj, RESET_TYPE_COLD);
132
+ }
133
+ /*
134
+ * if obj is leaving a bus under reset, we need to ensure
135
+ * hold phase is not pending.
136
+ */
137
+ if (oldp_count && s->hold_phase_pending) {
138
+ resettable_phase_hold(obj, NULL, RESET_TYPE_COLD);
139
+ }
140
+ /* if oldp is more reset than newp */
141
+ for (unsigned i = newp_count; i < oldp_count; i++) {
142
+ resettable_release_reset(obj, RESET_TYPE_COLD);
143
+ }
47
+ }
144
+}
48
+}
145
+
49
+
146
void resettable_class_set_parent_phases(ResettableClass *rc,
50
/*
147
ResettableEnterPhase enter,
51
* Check that VFP access is enabled. If it is, do the necessary
148
ResettableHoldPhase hold,
52
* M-profile lazy-FP handling and then return true.
149
diff --git a/hw/core/trace-events b/hw/core/trace-events
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
150
index XXXXXXX..XXXXXXX 100644
54
/* Handle M-profile lazy FP state mechanics */
151
--- a/hw/core/trace-events
55
152
+++ b/hw/core/trace-events
56
/* Trigger lazy-state preservation if necessary */
153
@@ -XXX,XX +XXX,XX @@ resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
57
- if (s->v7m_lspact) {
154
resettable_reset_assert_end(void *obj) "obj=%p"
58
- /*
155
resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
59
- * Lazy state saving affects external memory and also the NVIC,
156
resettable_reset_release_end(void *obj) "obj=%p"
60
- * so we must mark it as an IO operation for icount (and cause
157
+resettable_change_parent(void *obj, void *o, unsigned oc, void *n, unsigned nc) "obj=%p from=%p(%d) to=%p(%d)"
61
- * this to be the last insn in the TB).
158
resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
62
- */
159
resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
160
resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
- gen_io_start();
66
- }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- /*
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- * any further FP insns in this TB.
72
- */
73
- s->v7m_lspact = false;
74
- }
75
+ gen_preserve_fp_state(s);
76
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
if (s->v8m_fpccr_s_wrong) {
161
--
79
--
162
2.20.1
80
2.20.1
163
81
164
82
diff view generated by jsdifflib
New patch
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
1 file changed, 58 insertions(+)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
return false;
19
}
20
break;
21
+ case ARM_VFP_FPCXT_S:
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
23
+ return false;
24
+ }
25
+ if (!s->v8m_secure) {
26
+ return false;
27
+ }
28
+ break;
29
default:
30
return FPSysRegCheckFailed;
31
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
33
tcg_temp_free_i32(tmp);
34
break;
35
}
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
55
+ }
56
default:
57
g_assert_not_reached();
58
}
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
61
storefn(s, opaque, tmp);
62
break;
63
+ case ARM_VFP_FPCXT_S:
64
+ {
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
92
+ }
93
default:
94
g_assert_not_reached();
95
}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
New patch
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
gains new fields FZ16 (if half-precision floating point is supported)
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 5 +++++
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
12
target/arm/cpu.c | 3 +++
13
3 files changed, 16 insertions(+), 1 deletion(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
break;
45
case 0xf3c: /* FPDSCR */
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
- value &= 0x07c00000;
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
50
+ mask |= FPCR_FZ16;
51
+ }
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
64
* always reset to 4.
65
*/
66
env->v7m.ltpsize = 4;
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
70
}
71
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
New patch
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
1
5
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
20
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
22
* Clear registers if necessary to prevent non-secure exception
23
* code being able to see register values from secure code.
24
* Where register values become architecturally UNKNOWN we leave
25
- * them with their previous values.
26
+ * them with their previous values. v8.1M is tighter than v8.0M
27
+ * here and always zeroes the caller-saved registers regardless
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
2
4
3
Replace deprecated qdev_reset_all by resettable_cold_reset_fn for
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the ipl registration in the main reset handlers.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
5
11
6
This does not impact the behavior for the following reasons:
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
7
+ at this point resettable just call the old reset methods of devices
8
and buses in the same order than qdev/qbus.
9
+ resettable handlers registered with qemu_register_reset are
10
serialized; there is no interleaving.
11
+ eventual explicit calls to legacy reset API (device_reset or
12
qdev/qbus_reset) inside this reset handler will not be masked out
13
by resettable mechanism; they do not go through resettable api.
14
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200123132823.1117486-12-damien.hedde@greensocs.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/s390x/ipl.c | 10 +++++++++-
24
1 file changed, 9 insertions(+), 1 deletion(-)
25
26
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/s390x/ipl.c
14
--- a/target/arm/m_helper.c
29
+++ b/hw/s390x/ipl.c
15
+++ b/target/arm/m_helper.c
30
@@ -XXX,XX +XXX,XX @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ load_fail:
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
18
* secure); otherwise it targets the same security state as the
19
* underlying exception.
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
31
*/
21
*/
32
ipl->compat_start_addr = ipl->start_addr;
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
33
ipl->compat_bios_start_addr = ipl->bios_start_addr;
23
exc_secure = true;
34
- qemu_register_reset(qdev_reset_all_fn, dev);
24
}
35
+ /*
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
36
+ * Because this Device is not on any bus in the qbus tree (it is
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
37
+ * not a sysbus device and it's not on some other bus like a PCI
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
38
+ * bus) it will not be automatically reset by the 'reset the
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
39
+ * sysbus' hook registered by vl.c like most devices. So we must
29
+ }
40
+ * manually register a reset hook for it.
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
41
+ * TODO: there should be a better way to do this.
31
return false;
42
+ */
43
+ qemu_register_reset(resettable_cold_reset_fn, dev);
44
error:
45
error_propagate(errp, err);
46
}
32
}
47
--
33
--
48
2.20.1
34
2.20.1
49
35
50
36
diff view generated by jsdifflib
New patch
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
8
---
9
hw/intc/armv7m_nvic.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
}
18
return val;
19
}
20
+ case 0xcfc:
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ goto bad_offset;
23
+ }
24
+ return cpu->revidr;
25
case 0xd00: /* CPUID Base. */
26
return cpu->midr;
27
case 0xd04: /* Interrupt Control State (ICSR) */
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
New patch
1
In v8.1M a new exception return check is added which may cause a NOCP
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
1
5
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
16
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
18
1 file changed, 21 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
23
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
v7m_exception_taken(cpu, excret, true, false);
26
return;
27
} else {
28
- /* Clear s0..s15 and FPSCR */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
30
+ /* v8.1M adds this NOCP check */
31
+ bool nsacr_pass = exc_secure ||
32
+ extract32(env->v7m.nsacr, 10, 1);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
34
+ if (!nsacr_pass) {
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
39
+ v7m_exception_taken(cpu, excret, true, false);
40
+ } else if (!cpacr_pass) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ exc_secure);
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
46
+ v7m_exception_taken(cpu, excret, true, false);
47
+ }
48
+ }
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
50
int i;
51
52
for (i = 0; i < 16; i += 2) {
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
New patch
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
1
8
9
We choose not to make those accesses, so for us the two
10
instructions behave identically assuming they don't UNDEF.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
15
---
16
target/arm/m-nocp.decode | 2 +-
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
18
2 files changed, 26 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
23
+++ b/target/arm/m-nocp.decode
24
@@ -XXX,XX +XXX,XX @@
25
26
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
30
# VSCCLRM (new in v8.1M) is similar:
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
39
return false;
40
}
41
+
42
+ if (a->op) {
43
+ /*
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
45
+ * to take the IMPDEF option to make memory accesses to the stack
46
+ * slots that correspond to the D16-D31 registers (discarding
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
51
+ return false;
52
+ }
53
+ } else {
54
+ /*
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
56
+ * This is currently architecturally impossible, but we add the
57
+ * check to stay in line with the pseudocode. Note that we must
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
59
+ */
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
61
+ unallocated_encoding(s);
62
+ return true;
63
+ }
64
+ }
65
+
66
/*
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
69
--
70
2.20.1
71
72
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
2
5
3
Replace deprecated qbus_reset_all by resettable_cold_reset_fn for
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the sysbus reset registration.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 2 ++
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
2 files changed, 20 insertions(+), 8 deletions(-)
5
13
6
Apart for the raspi machines, this does not impact the behavior
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
7
because:
8
+ at this point resettable just calls the old reset methods of devices
9
and buses in the same order as qdev/qbus.
10
+ resettable handlers registered with qemu_register_reset are
11
serialized; there is no interleaving.
12
+ eventual explicit calls to legacy reset API (device_reset or
13
qdev/qbus_reset) inside this reset handler will not be masked out
14
by resettable mechanism; they do not go through resettable api.
15
16
For the raspi machines, during the sysbus reset the sd-card is not
17
reset twice anymore but only once. This is a consequence of switching
18
both sysbus reset and changing parent to resettable; it detects the
19
second reset is not needed. This has no impact on the state after
20
reset; the sd-card reset method only reset local state and query
21
information from the block backend.
22
23
The raspi reset change can be observed by using the following command
24
(reset will occurs, then do Ctrl-C to end qemu; no firmware is
25
given here).
26
qemu-system-aarch64 -M raspi3 \
27
-trace resettable_phase_hold_exec \
28
-trace qdev_update_parent_bus \
29
-trace resettable_change_parent \
30
-trace qdev_reset -trace qbus_reset
31
32
Before the patch, the qdev/qbus_reset traces show when reset method are
33
called. After the patch, the resettable_phase_hold_exec show when reset
34
method are called.
35
36
The traced reset order of the raspi3 is listed below. I've added empty
37
lines and the tree structure.
38
39
+->bcm2835-peripherals reset
40
|
41
| +->sd-card reset
42
| +->sd-bus reset
43
+->bcm2835_gpio reset
44
| -> dev_update_parent_bus (move the sd-card on the sdhci-bus)
45
| -> resettable_change_parent
46
|
47
+->bcm2835-dma reset
48
|
49
| +->bcm2835-sdhost-bus reset
50
+->bcm2835-sdhost reset
51
|
52
| +->sd-card (reset ONLY BEFORE BEFORE THE PATCH)
53
| +->sdhci-bus reset
54
+->generic-sdhci reset
55
|
56
+->bcm2835-rng reset
57
+->bcm2835-property reset
58
+->bcm2835-fb reset
59
+->bcm2835-mbox reset
60
+->bcm2835-aux reset
61
+->pl011 reset
62
+->bcm2835-ic reset
63
+->bcm2836-control reset
64
System reset
65
66
In both case, the sd-card is reset (being on bcm2835_gpio/sd-bus) then moved
67
to generic-sdhci/sdhci-bus by the bcm2835_gpio reset method.
68
69
Before the patch, it is then reset again being part of generic-sdhci/sdhci-bus.
70
After the patch, it considered again for reset but its reset method is not
71
called because it is already flagged as reset.
72
73
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
74
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
75
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
76
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
77
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
78
Message-id: 20200123132823.1117486-11-damien.hedde@greensocs.com
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
80
---
81
vl.c | 10 +++++++++-
82
1 file changed, 9 insertions(+), 1 deletion(-)
83
84
diff --git a/vl.c b/vl.c
85
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
86
--- a/vl.c
16
--- a/target/arm/cpu.h
87
+++ b/vl.c
17
+++ b/target/arm/cpu.h
88
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
89
19
FIELD(V7M_CCR, DC, 16, 1)
90
/* TODO: once all bus devices are qdevified, this should be done
20
FIELD(V7M_CCR, IC, 17, 1)
91
* when bus is created by qdev.c */
21
FIELD(V7M_CCR, BP, 18, 1)
92
- qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
22
+FIELD(V7M_CCR, LOB, 19, 1)
93
+ /*
23
+FIELD(V7M_CCR, TRD, 20, 1)
94
+ * TODO: If we had a main 'reset container' that the whole system
24
95
+ * lived in, we could reset that using the multi-phase reset
25
/* V7M SCR bits */
96
+ * APIs. For the moment, we just reset the sysbus, which will cause
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
97
+ * all devices hanging off it (and all their child buses, recursively)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
98
+ * to be reset. Note that this will *not* reset any Device objects
28
index XXXXXXX..XXXXXXX 100644
99
+ * which are not attached to some part of the qbus tree!
29
--- a/hw/intc/armv7m_nvic.c
100
+ */
30
+++ b/hw/intc/armv7m_nvic.c
101
+ qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
102
qemu_run_machine_init_done_notifiers();
32
}
103
33
return cpu->env.v7m.scr[attrs.secure];
104
if (rom_check_and_register_reset() != 0) {
34
case 0xd14: /* Configuration Control. */
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
36
- * keep it in the non-secure copy of the register.
37
+ /*
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
49
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
51
goto bad_offset;
52
}
53
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
56
- R_V7M_CCR_BFHFNMIGN_MASK |
57
- R_V7M_CCR_DIV_0_TRP_MASK |
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
59
- R_V7M_CCR_USERSETMPEND_MASK |
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
105
--
83
--
106
2.20.1
84
2.20.1
107
85
108
86
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
2
4
3
These buffers should be aligned on 16 bytes.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 86 insertions(+)
4
11
5
Ignore invalid RX and TX buffer addresses and log an error. All
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
6
incoming and outgoing traffic will be dropped because no valid RX or
7
TX descriptors will be available.
8
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Message-id: 20200114103433.30534-4-clg@kaod.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/net/ftgmac100.c | 13 +++++++++++++
15
1 file changed, 13 insertions(+)
16
17
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ftgmac100.c
14
--- a/target/arm/m_helper.c
20
+++ b/hw/net/ftgmac100.c
15
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
22
uint32_t des3;
17
return true;
23
} FTGMAC100Desc;
18
}
24
19
25
+#define FTGMAC100_DESC_ALIGNMENT 16
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
21
+ uint32_t addr, uint32_t *spdata)
22
+{
23
+ /*
24
+ * Read a word of data from the stack for the SG instruction,
25
+ * writing the value into *spdata. If the load succeeds, return
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
31
+ CPUState *cs = CPU(cpu);
32
+ CPUARMState *env = &cpu->env;
33
+ MemTxAttrs attrs = {};
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
26
+
41
+
27
/*
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
28
* Specific RTL8211E MII Registers
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
29
*/
44
+ /* MPU/SAU lookup failed */
30
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
45
+ if (fi.type == ARMFault_QEMU_SFault) {
31
s->itc = value;
46
+ qemu_log_mask(CPU_LOG_INT,
32
break;
47
+ "...SecureFault during stack word read\n");
33
case FTGMAC100_RXR_BADR: /* Ring buffer address */
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
34
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
49
+ env->v7m.sfar = addr;
35
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad RX buffer alignment 0x%"
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
36
+ HWADDR_PRIx "\n", __func__, value);
51
+ } else {
37
+ return;
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
60
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
71
+ return false;
72
+ }
73
+
74
+ *spdata = value;
75
+ return true;
76
+}
77
+
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
79
{
80
/*
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
82
*/
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
84
", executing it\n", env->regs[15]);
85
+
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
87
+ !arm_v7m_is_handler_mode(env)) {
88
+ /*
89
+ * v8.1M exception stack frame integrity check. Note that we
90
+ * must perform the memory access even if CCR_S.TRD is zero
91
+ * and we aren't going to check what the data loaded is.
92
+ */
93
+ uint32_t spdata, sp;
94
+
95
+ /*
96
+ * We know we are currently NS, so the S stack pointers must be
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
38
+ }
103
+ }
39
+
104
+
40
s->rx_ring = value;
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
41
s->rx_descriptor = s->rx_ring;
106
+ if (((spdata & ~1) == 0xfefa125a) ||
42
break;
107
+ !(env->v7m.control[M_REG_S] & 1)) {
43
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
108
+ goto gen_invep;
44
break;
109
+ }
45
46
case FTGMAC100_NPTXR_BADR: /* Transmit buffer address */
47
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad TX buffer alignment 0x%"
49
+ HWADDR_PRIx "\n", __func__, value);
50
+ return;
51
+ }
110
+ }
52
s->tx_ring = value;
111
+ }
53
s->tx_descriptor = s->tx_ring;
112
+
54
break;
113
env->regs[14] &= ~1;
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
115
switch_v7m_security_state(env, true);
55
--
116
--
56
2.20.1
117
2.20.1
57
118
58
119
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In commit 077d7449100d824a4 we added code to handle the v8M
2
requirement that returns from NMI or HardFault forcibly deactivate
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
2
12
3
Since we enabled parallel TCG code generation for softmmu (see
13
In the case for "configurable exception targeting the opposite
4
commit 3468b59 "tcg: enable multiple TCG contexts in softmmu")
14
security state" we detected the illegal-return case but went ahead
5
and its subsequent fix (commit 72649619 "add .min_cpus and
15
and deactivated the VecInfo anyway, which is wrong because that is
6
.default_cpus fields to machine_class"), the raspi machines are
16
the VecInfo for the other security state.
7
restricted to always use their 4 cores:
8
17
9
See in hw/arm/raspi2 (with BCM283X_NCPUS set to 4):
18
Rearrange the code so that we first identify the illegal return
19
cases, then see if we really need to deactivate NMI or HardFault
20
instead, and finally do the deactivation.
10
21
11
222 static void raspi2_machine_init(MachineClass *mc)
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
223 {
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
224 mc->desc = "Raspberry Pi 2";
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
14
230 mc->max_cpus = BCM283X_NCPUS;
25
---
15
231 mc->min_cpus = BCM283X_NCPUS;
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
16
232 mc->default_cpus = BCM283X_NCPUS;
27
1 file changed, 32 insertions(+), 27 deletions(-)
17
235 };
18
236 DEFINE_MACHINE("raspi2", raspi2_machine_init)
19
28
20
We can no longer use the -smp option, as we get:
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
21
22
$ qemu-system-arm -M raspi2 -smp 1
23
qemu-system-arm: Invalid SMP CPUs 1. The min CPUs supported by machine 'raspi2' is 4
24
25
Since we can not set the TYPE_BCM283x SOC "enabled-cpus" with -smp,
26
remove the unuseful code.
27
28
We can achieve the same by using the '-global bcm2836.enabled-cpus=1'
29
option.
30
31
Reported-by: Laurent Bonnans <laurent.bonnans@here.com>
32
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
33
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
34
Message-id: 20200120235159.18510-2-f4bug@amsat.org
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
---
37
hw/arm/raspi.c | 2 --
38
1 file changed, 2 deletions(-)
39
40
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
41
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/raspi.c
31
--- a/hw/intc/armv7m_nvic.c
43
+++ b/hw/arm/raspi.c
32
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
45
/* Setup the SOC */
34
{
46
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
35
NVICState *s = (NVICState *)opaque;
47
&error_abort);
36
VecInfo *vec = NULL;
48
- object_property_set_int(OBJECT(&s->soc), machine->smp.cpus, "enabled-cpus",
37
- int ret;
49
- &error_abort);
38
+ int ret = 0;
50
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
39
51
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
52
&error_abort);
41
42
+ trace_nvic_complete_irq(irq, secure);
43
+
44
+ if (secure && exc_is_banked(irq)) {
45
+ vec = &s->sec_vectors[irq];
46
+ } else {
47
+ vec = &s->vectors[irq];
48
+ }
49
+
50
+ /*
51
+ * Identify illegal exception return cases. We can't immediately
52
+ * return at this point because we still need to deactivate
53
+ * (either this exception or NMI/HardFault) first.
54
+ */
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
56
+ /*
57
+ * Return from a configurable exception targeting the opposite
58
+ * security state from the one we're trying to complete it for.
59
+ * Clear vec because it's not really the VecInfo for this
60
+ * (irq, secstate) so we mustn't deactivate it.
61
+ */
62
+ ret = -1;
63
+ vec = NULL;
64
+ } else if (!vec->active) {
65
+ /* Return from an inactive interrupt */
66
+ ret = -1;
67
+ } else {
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
70
+ }
71
+
72
/*
73
* For negative priorities, v8M will forcibly deactivate the appropriate
74
* NMI or HardFault regardless of what interrupt we're being asked to
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
76
}
77
78
if (!vec) {
79
- if (secure && exc_is_banked(irq)) {
80
- vec = &s->sec_vectors[irq];
81
- } else {
82
- vec = &s->vectors[irq];
83
- }
84
- }
85
-
86
- trace_nvic_complete_irq(irq, secure);
87
-
88
- if (!vec->active) {
89
- /* Tell the caller this was an illegal exception return */
90
- return -1;
91
- }
92
-
93
- /*
94
- * If this is a configurable exception and it is currently
95
- * targeting the opposite security state from the one we're trying
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
100
- */
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
102
- ret = -1;
103
- } else {
104
- ret = nvic_rettobase(s);
105
+ return ret;
106
}
107
108
vec->active = 0;
53
--
109
--
54
2.20.1
110
2.20.1
55
111
56
112
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
For v8.1M the architecture mandates that CPUs must provide at
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
2
15
3
Adds trace events to reset procedure and when updating the parent
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
bus of a device.
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
19
---
20
target/arm/cpu.h | 14 ++++++++++++++
21
target/arm/t32.decode | 4 ++++
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
23
3 files changed, 31 insertions(+)
5
24
6
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20200123132823.1117486-3-damien.hedde@greensocs.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/core/qdev.c | 29 ++++++++++++++++++++++++++---
15
hw/core/trace-events | 9 +++++++++
16
2 files changed, 35 insertions(+), 3 deletions(-)
17
18
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
19
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/core/qdev.c
27
--- a/target/arm/cpu.h
21
+++ b/hw/core/qdev.c
28
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
23
#include "hw/boards.h"
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
24
#include "hw/sysbus.h"
31
FIELD(ID_MMFR4, EVT, 28, 4)
25
#include "migration/vmstate.h"
32
26
+#include "trace.h"
33
+FIELD(ID_PFR0, STATE0, 0, 4)
27
34
+FIELD(ID_PFR0, STATE1, 4, 4)
28
bool qdev_hotplug = false;
35
+FIELD(ID_PFR0, STATE2, 8, 4)
29
static bool qdev_hot_added = false;
36
+FIELD(ID_PFR0, STATE3, 12, 4)
30
@@ -XXX,XX +XXX,XX @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
31
bool replugging = dev->parent_bus != NULL;
38
+FIELD(ID_PFR0, AMU, 20, 4)
32
39
+FIELD(ID_PFR0, DIT, 24, 4)
33
if (replugging) {
40
+FIELD(ID_PFR0, RAS, 28, 4)
34
- /* Keep a reference to the device while it's not plugged into
41
+
35
+ trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
36
+ dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
43
FIELD(ID_PFR1, SECURITY, 4, 4)
37
+ OBJECT(bus), object_get_typename(OBJECT(bus)));
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
38
+ /*
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
39
+ * Keep a reference to the device while it's not plugged into
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
40
* any bus, to avoid it potentially evaporating when it is
41
* dereffed in bus_remove_child().
42
*/
43
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
44
return hotplug_ctrl;
45
}
47
}
46
48
47
+static int qdev_prereset(DeviceState *dev, void *opaque)
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
48
+{
50
+{
49
+ trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev)));
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
50
+ return 0;
51
+}
52
+}
52
+
53
+
53
+static int qbus_prereset(BusState *bus, void *opaque)
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
54
+{
55
{
55
+ trace_qbus_reset_tree(bus, object_get_typename(OBJECT(bus)));
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
56
+ return 0;
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
57
+}
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/t32.decode
60
+++ b/target/arm/t32.decode
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
64
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
66
+ # default behaviour since it is in the hint space.
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
58
+
68
+
59
static int qdev_reset_one(DeviceState *dev, void *opaque)
69
# The canonical nop ends in 0000 0000, but the whole rest
60
{
70
# of the space is "reserved hint, behaves as nop".
61
device_legacy_reset(dev);
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
62
@@ -XXX,XX +XXX,XX @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
63
static int qbus_reset_one(BusState *bus, void *opaque)
73
index XXXXXXX..XXXXXXX 100644
64
{
74
--- a/hw/intc/armv7m_nvic.c
65
BusClass *bc = BUS_GET_CLASS(bus);
75
+++ b/hw/intc/armv7m_nvic.c
66
+ trace_qbus_reset(bus, object_get_typename(OBJECT(bus)));
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
67
if (bc->reset) {
77
return 0;
68
bc->reset(bus);
78
}
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
83
+ }
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
85
+ return 0;
86
case 0xf34: /* FPCCR */
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
92
}
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
94
if (attrs.secure) {
95
/* These bits are only writable by secure */
96
cpu->env.v7m.aircr = value &
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
}
99
break;
69
}
100
}
70
@@ -XXX,XX +XXX,XX @@ static int qbus_reset_one(BusState *bus, void *opaque)
101
+ case 0xf04: /* RFSR */
71
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
72
void qdev_reset_all(DeviceState *dev)
103
+ goto bad_offset;
73
{
104
+ }
74
- qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
75
+ trace_qdev_reset_all(dev, object_get_typename(OBJECT(dev)));
106
+ break;
76
+ qdev_walk_children(dev, qdev_prereset, qbus_prereset,
107
case 0xf34: /* FPCCR */
77
+ qdev_reset_one, qbus_reset_one, NULL);
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
78
}
109
/* Not all bits here are banked. */
79
80
void qdev_reset_all_fn(void *opaque)
81
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque)
82
83
void qbus_reset_all(BusState *bus)
84
{
85
- qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
86
+ trace_qbus_reset_all(bus, object_get_typename(OBJECT(bus)));
87
+ qbus_walk_children(bus, qdev_prereset, qbus_prereset,
88
+ qdev_reset_one, qbus_reset_one, NULL);
89
}
90
91
void qbus_reset_all_fn(void *opaque)
92
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev)
93
{
94
DeviceClass *klass = DEVICE_GET_CLASS(dev);
95
96
+ trace_qdev_reset(dev, object_get_typename(OBJECT(dev)));
97
if (klass->reset) {
98
klass->reset(dev);
99
}
100
diff --git a/hw/core/trace-events b/hw/core/trace-events
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/core/trace-events
103
+++ b/hw/core/trace-events
104
@@ -XXX,XX +XXX,XX @@
105
# loader.c
106
loader_write_rom(const char *name, uint64_t gpa, uint64_t size, bool isrom) "%s: @0x%"PRIx64" size=0x%"PRIx64" ROM=%d"
107
+
108
+# qdev.c
109
+qdev_reset(void *obj, const char *objtype) "obj=%p(%s)"
110
+qdev_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
111
+qdev_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
112
+qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
113
+qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
114
+qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
115
+qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
116
--
110
--
117
2.20.1
111
2.20.1
118
112
119
113
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
The RAS feature has a block of memory-mapped registers at offset
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
2
5
3
Following the pattern of the work recently done with the ASPEED GPIO
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
4
model, this adds support for inspecting and modifying the PCA9552 LEDs
7
of the "nvic-default" region is actually valid for minimal-RAS,
5
from the monitor.
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
6
12
7
(qemu) qom-set /machine/unattached/device[17] led0 on
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
(qemu) qom-set /machine/unattached/device[17] led0 off
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
(qemu) qom-set /machine/unattached/device[17] led0 pwm0
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
10
(qemu) qom-set /machine/unattached/device[17] led0 pwm1
16
---
17
include/hw/intc/armv7m_nvic.h | 1 +
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
19
2 files changed, 57 insertions(+)
11
20
12
Signed-off-by: Joel Stanley <joel@jms.id.au>
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20200114103433.30534-6-clg@kaod.org
15
[clg: - removed the "qom-get" examples from the commit log
16
- merged memory leak fixes from Joel ]
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/misc/pca9552.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
22
1 file changed, 90 insertions(+)
23
24
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/pca9552.c
23
--- a/include/hw/intc/armv7m_nvic.h
27
+++ b/hw/misc/pca9552.c
24
+++ b/include/hw/intc/armv7m_nvic.h
28
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
29
#include "hw/misc/pca9552.h"
26
MemoryRegion sysreg_ns_mem;
30
#include "hw/misc/pca9552_regs.h"
27
MemoryRegion systickmem;
31
#include "migration/vmstate.h"
28
MemoryRegion systick_ns_mem;
32
+#include "qapi/error.h"
29
+ MemoryRegion ras_mem;
33
+#include "qapi/visitor.h"
30
MemoryRegion container;
34
31
MemoryRegion defaultmem;
35
#define PCA9552_LED_ON 0x0
32
36
#define PCA9552_LED_OFF 0x1
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
37
#define PCA9552_LED_PWM0 0x2
34
index XXXXXXX..XXXXXXX 100644
38
#define PCA9552_LED_PWM1 0x3
35
--- a/hw/intc/armv7m_nvic.c
39
36
+++ b/hw/intc/armv7m_nvic.c
40
+static const char *led_state[] = {"on", "off", "pwm0", "pwm1"};
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
38
.endianness = DEVICE_NATIVE_ENDIAN,
39
};
40
41
+
41
+
42
static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
43
{
43
+ uint64_t *data, unsigned size,
44
uint8_t reg = PCA9552_LS0 + (pin / 4);
44
+ MemTxAttrs attrs)
45
@@ -XXX,XX +XXX,XX @@ static int pca9552_event(I2CSlave *i2c, enum i2c_event event)
46
return 0;
47
}
48
49
+static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
50
+ void *opaque, Error **errp)
51
+{
45
+{
52
+ PCA9552State *s = PCA9552(obj);
46
+ if (attrs.user) {
53
+ int led, rc, reg;
47
+ return MEMTX_ERROR;
54
+ uint8_t state;
48
+ }
55
+
49
+
56
+ rc = sscanf(name, "led%2d", &led);
50
+ switch (addr) {
57
+ if (rc != 1) {
51
+ case 0xe10: /* ERRIIDR */
58
+ error_setg(errp, "%s: error reading %s", __func__, name);
52
+ /* architect field = Arm; product/variant/revision 0 */
59
+ return;
53
+ *data = 0x43b;
54
+ break;
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
60
+ }
64
+ }
61
+ if (led < 0 || led > s->nr_leds) {
65
+ return MEMTX_OK;
62
+ error_setg(errp, "%s invalid led %s", __func__, name);
63
+ return;
64
+ }
65
+ /*
66
+ * Get the LSx register as the qom interface should expose the device
67
+ * state, not the modeled 'input line' behaviour which would come from
68
+ * reading the INPUTx reg
69
+ */
70
+ reg = PCA9552_LS0 + led / 4;
71
+ state = (pca9552_read(s, reg) >> (led % 8)) & 0x3;
72
+ visit_type_str(v, name, (char **)&led_state[state], errp);
73
+}
66
+}
74
+
67
+
75
+/*
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
76
+ * Return an LED selector register value based on an existing one, with
69
+ uint64_t value, unsigned size,
77
+ * the appropriate 2-bit state value set for the given LED number (0-3).
70
+ MemTxAttrs attrs)
78
+ */
79
+static inline uint8_t pca955x_ledsel(uint8_t oldval, int led_num, int state)
80
+{
71
+{
81
+ return (oldval & (~(0x3 << (led_num << 1)))) |
72
+ if (attrs.user) {
82
+ ((state & 0x3) << (led_num << 1));
73
+ return MEMTX_ERROR;
74
+ }
75
+
76
+ switch (addr) {
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
83
+}
84
+
84
+
85
+static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
85
+static const MemoryRegionOps ras_ops = {
86
+ void *opaque, Error **errp)
86
+ .read_with_attrs = ras_read,
87
+{
87
+ .write_with_attrs = ras_write,
88
+ PCA9552State *s = PCA9552(obj);
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+ Error *local_err = NULL;
89
+};
90
+ int led, rc, reg, val;
91
+ uint8_t state;
92
+ char *state_str;
93
+
90
+
94
+ visit_type_str(v, name, &state_str, &local_err);
91
/*
95
+ if (local_err) {
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
96
+ error_propagate(errp, local_err);
93
* accesses, and fault for non-privileged accesses.
97
+ return;
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
98
+ }
95
&s->systick_ns_mem, 1);
99
+ rc = sscanf(name, "led%2d", &led);
96
}
100
+ if (rc != 1) {
97
101
+ error_setg(errp, "%s: error reading %s", __func__, name);
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
102
+ return;
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
103
+ }
100
+ &ras_ops, s, "nvic_ras", 0x1000);
104
+ if (led < 0 || led > s->nr_leds) {
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
105
+ error_setg(errp, "%s invalid led %s", __func__, name);
106
+ return;
107
+ }
102
+ }
108
+
103
+
109
+ for (state = 0; state < ARRAY_SIZE(led_state); state++) {
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
110
+ if (!strcmp(state_str, led_state[state])) {
111
+ break;
112
+ }
113
+ }
114
+ if (state >= ARRAY_SIZE(led_state)) {
115
+ error_setg(errp, "%s invalid led state %s", __func__, state_str);
116
+ return;
117
+ }
118
+
119
+ reg = PCA9552_LS0 + led / 4;
120
+ val = pca9552_read(s, reg);
121
+ val = pca955x_ledsel(val, led % 4, state);
122
+ pca9552_write(s, reg, val);
123
+}
124
+
125
static const VMStateDescription pca9552_vmstate = {
126
.name = "PCA9552",
127
.version_id = 0,
128
@@ -XXX,XX +XXX,XX @@ static void pca9552_reset(DeviceState *dev)
129
static void pca9552_initfn(Object *obj)
130
{
131
PCA9552State *s = PCA9552(obj);
132
+ int led;
133
134
/* If support for the other PCA955X devices are implemented, these
135
* constant values might be part of class structure describing the
136
@@ -XXX,XX +XXX,XX @@ static void pca9552_initfn(Object *obj)
137
*/
138
s->max_reg = PCA9552_LS3;
139
s->nr_leds = 16;
140
+
141
+ for (led = 0; led < s->nr_leds; led++) {
142
+ char *name;
143
+
144
+ name = g_strdup_printf("led%d", led);
145
+ object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led,
146
+ NULL, NULL, NULL);
147
+ g_free(name);
148
+ }
149
}
105
}
150
106
151
static void pca9552_class_init(ObjectClass *klass, void *data)
152
--
107
--
153
2.20.1
108
2.20.1
154
109
155
110
diff view generated by jsdifflib
1
The guest can use the semihosting API to open a handle
1
Correct a typo in the name we give the NVIC object.
2
corresponding to QEMU's own stdin, stdout, or stderr.
3
When the guest closes this handle, we should not
4
close the underlying host stdin/stdout/stderr
5
the way we would do if the handle corresponded to
6
a host fd we'd opened on behalf of the guest in SYS_OPEN.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200124172954.28481-1-peter.maydell@linaro.org
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
12
---
7
---
13
target/arm/arm-semi.c | 9 +++++++++
8
hw/arm/armv7m.c | 2 +-
14
1 file changed, 9 insertions(+)
9
1 file changed, 1 insertion(+), 1 deletion(-)
15
10
16
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/arm-semi.c
13
--- a/hw/arm/armv7m.c
19
+++ b/target/arm/arm-semi.c
14
+++ b/hw/arm/armv7m.c
20
@@ -XXX,XX +XXX,XX @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
21
{
16
22
CPUARMState *env = &cpu->env;
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
23
18
24
+ /*
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
25
+ * Only close the underlying host fd if it's one we opened on behalf
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
26
+ * of the guest in SYS_OPEN.
21
object_property_add_alias(obj, "num-irq",
27
+ */
22
OBJECT(&s->nvic), "num-irq");
28
+ if (gf->hostfd == STDIN_FILENO ||
29
+ gf->hostfd == STDOUT_FILENO ||
30
+ gf->hostfd == STDERR_FILENO) {
31
+ return 0;
32
+ }
33
return set_swi_errno(env, close(gf->hostfd));
34
}
35
23
36
--
24
--
37
2.20.1
25
2.20.1
38
26
39
27
diff view generated by jsdifflib