1
ARM queue for 2.10 soft freeze...
1
Only thing for Arm for rc1 is RTH's fix for the KVM SVE probe code.
2
2
3
thanks
4
-- PMM
3
-- PMM
5
4
6
The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5:
5
The following changes since commit 4e06b3fc1b5e1ec03f22190eabe56891dc9c2236:
7
6
8
Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging (2017-07-17 11:46:36 +0100)
7
Merge tag 'pull-hex-20220731' of https://github.com/quic/qemu into staging (2022-07-31 21:38:54 -0700)
9
8
10
are available in the git repository at:
9
are available in the Git repository at:
11
10
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170717
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220801
13
12
14
for you to fetch changes up to e5a6a6e64e82a132cebef023d867085b0a2993d7:
13
for you to fetch changes up to 5265d24c981dfdda8d29b44f7e84a514da75eedc:
15
14
16
MAINTAINERS: Add entries for MPS2 board (2017-07-17 13:36:09 +0100)
15
target/arm: Move sve probe inside kvm >= 4.15 branch (2022-08-01 16:21:18 +0100)
17
16
18
----------------------------------------------------------------
17
----------------------------------------------------------------
19
target-arm queue:
18
target-arm queue:
20
* new model of the ARM MPS2/MPS2+ FPGA based development board
19
* Fix KVM SVE ID register probe code
21
* clean up DISAS_* exit conditions and fix various regressions
22
since commits e75449a346 8a6b28c7b5 (in particular including
23
ones which broke OP-TEE guests)
24
* make Cortex-M3 and M4 correctly default to 8 PMSA regions
25
20
26
----------------------------------------------------------------
21
----------------------------------------------------------------
27
Alex Bennée (6):
22
Richard Henderson (3):
28
include/exec/exec-all: document common exit conditions
23
target/arm: Use kvm_arm_sve_supported in kvm_arm_get_host_cpu_features
29
target/arm/translate: make DISAS_UPDATE match declared semantics
24
target/arm: Set KVM_ARM_VCPU_SVE while probing the host
30
target/arm/translate.h: expand comment on DISAS_EXIT
25
target/arm: Move sve probe inside kvm >= 4.15 branch
31
target/arm/translate: ensure gen_goto_tb sets exit flags
32
target/arm: use gen_goto_tb for ISB handling
33
target/arm: use DISAS_EXIT for eret handling
34
26
35
Peter Maydell (12):
27
target/arm/kvm64.c | 45 ++++++++++++++++++++++-----------------------
36
qdev-properties.h: Explicitly set the default value for arraylen properties
28
1 file changed, 22 insertions(+), 23 deletions(-)
37
qdev: support properties which don't set a default value
38
target/arm: Make Cortex-M3 and M4 default to 8 PMSA regions
39
hw/arm/mps2: Implement skeleton mps2-an385 and mps2-an511 board models
40
hw/char/cmsdk-apb-uart.c: Implement CMSDK APB UART
41
hw/arm/mps2: Add UARTs
42
hw/char/cmsdk-apb-timer: Implement CMSDK APB timer device
43
hw/arm/mps2: Add timers
44
hw/misc/mps2_scc: Implement MPS2 Serial Communication Controller
45
hw/arm/mps2: Add SCC
46
hw/arm/mps2: Add ethernet
47
MAINTAINERS: Add entries for MPS2 board
48
49
hw/arm/Makefile.objs | 1 +
50
hw/char/Makefile.objs | 1 +
51
hw/misc/Makefile.objs | 1 +
52
hw/timer/Makefile.objs | 1 +
53
include/exec/exec-all.h | 29 ++-
54
include/hw/char/cmsdk-apb-uart.h | 78 +++++++
55
include/hw/misc/mps2-scc.h | 43 ++++
56
include/hw/qdev-core.h | 10 +
57
include/hw/qdev-properties.h | 21 ++
58
include/hw/timer/cmsdk-apb-timer.h | 59 ++++++
59
target/arm/translate.h | 5 +-
60
hw/arm/mps2.c | 385 +++++++++++++++++++++++++++++++++++
61
hw/char/cmsdk-apb-uart.c | 403 +++++++++++++++++++++++++++++++++++++
62
hw/core/qdev.c | 2 +-
63
hw/misc/mps2-scc.c | 310 ++++++++++++++++++++++++++++
64
hw/timer/cmsdk-apb-timer.c | 253 +++++++++++++++++++++++
65
target/arm/cpu.c | 12 +-
66
target/arm/translate-a64.c | 19 +-
67
target/arm/translate.c | 22 +-
68
MAINTAINERS | 14 +-
69
default-configs/arm-softmmu.mak | 6 +
70
hw/char/trace-events | 9 +
71
hw/misc/trace-events | 8 +
72
hw/timer/trace-events | 5 +
73
24 files changed, 1673 insertions(+), 24 deletions(-)
74
create mode 100644 include/hw/char/cmsdk-apb-uart.h
75
create mode 100644 include/hw/misc/mps2-scc.h
76
create mode 100644 include/hw/timer/cmsdk-apb-timer.h
77
create mode 100644 hw/arm/mps2.c
78
create mode 100644 hw/char/cmsdk-apb-uart.c
79
create mode 100644 hw/misc/mps2-scc.c
80
create mode 100644 hw/timer/cmsdk-apb-timer.c
81
diff view generated by jsdifflib
Deleted patch
1
In DEFINE_PROP_ARRAY, because we use a PropertyInfo (qdev_prop_arraylen)
2
which has a .set_default_value member we will set the field to a default
3
value. That default value will be zero, by the C rule that struct
4
initialization sets unmentioned members to zero if at least one member
5
is initialized. However it's clearer to state it explicitly.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Message-id: 1499788408-10096-2-git-send-email-peter.maydell@linaro.org
10
---
11
include/hw/qdev-properties.h | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/qdev-properties.h
17
+++ b/include/hw/qdev-properties.h
18
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
19
_arrayfield, _arrayprop, _arraytype) { \
20
.name = (PROP_ARRAY_LEN_PREFIX _name), \
21
.info = &(qdev_prop_arraylen), \
22
+ .defval.u = 0, \
23
.offset = offsetof(_state, _field) \
24
+ type_check(uint32_t, typeof_field(_state, _field)), \
25
.arrayinfo = &(_arrayprop), \
26
--
27
2.7.4
28
29
diff view generated by jsdifflib
Deleted patch
1
In some situations it's useful to have a qdev property which doesn't
2
automatically set its default value when qdev_property_add_static is
3
called (for instance when the default value is not constant).
4
1
5
Support this by adding a flag to the Property struct indicating
6
whether to set the default value. This replaces the existing test
7
for whether the PropertyInfo set_default_value function pointer is
8
NULL, and we set the .set_default field to true for all those cases
9
of struct Property which use a PropertyInfo with a non-NULL
10
set_default_value, so behaviour remains the same as before.
11
12
This gives us the semantics of:
13
* if .set_default is true, then .info->set_default_value must
14
be not NULL, and .defval is used as the the default value of
15
the property
16
* otherwise, the property system does not set any default, and
17
the field will retain whatever initial value it was given by
18
the device's .instance_init method
19
20
We define two new macros DEFINE_PROP_SIGNED_NODEFAULT and
21
DEFINE_PROP_UNSIGNED_NODEFAULT, to cover the most plausible use cases
22
of wanting to set an integer property with no default value.
23
24
Suggested-by: Markus Armbruster <armbru@redhat.com>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
27
Reviewed-by: Markus Armbruster <armbru@redhat.com>
28
Message-id: 1499788408-10096-3-git-send-email-peter.maydell@linaro.org
29
---
30
include/hw/qdev-core.h | 10 ++++++++++
31
include/hw/qdev-properties.h | 20 ++++++++++++++++++++
32
hw/core/qdev.c | 2 +-
33
3 files changed, 31 insertions(+), 1 deletion(-)
34
35
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/qdev-core.h
38
+++ b/include/hw/qdev-core.h
39
@@ -XXX,XX +XXX,XX @@ struct BusState {
40
QLIST_ENTRY(BusState) sibling;
41
};
42
43
+/**
44
+ * Property:
45
+ * @set_default: true if the default value should be set from @defval,
46
+ * in which case @info->set_default_value must not be NULL
47
+ * (if false then no default value is set by the property system
48
+ * and the field retains whatever value it was given by instance_init).
49
+ * @defval: default value for the property. This is used only if @set_default
50
+ * is true.
51
+ */
52
struct Property {
53
const char *name;
54
const PropertyInfo *info;
55
ptrdiff_t offset;
56
uint8_t bitnr;
57
+ bool set_default;
58
union {
59
int64_t i;
60
uint64_t u;
61
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/hw/qdev-properties.h
64
+++ b/include/hw/qdev-properties.h
65
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
66
.info = &(_prop), \
67
.offset = offsetof(_state, _field) \
68
+ type_check(_type,typeof_field(_state, _field)), \
69
+ .set_default = true, \
70
.defval.i = (_type)_defval, \
71
}
72
73
+#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
74
+ .name = (_name), \
75
+ .info = &(_prop), \
76
+ .offset = offsetof(_state, _field) \
77
+ + type_check(_type, typeof_field(_state, _field)), \
78
+ }
79
+
80
#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
81
.name = (_name), \
82
.info = &(qdev_prop_bit), \
83
.bitnr = (_bit), \
84
.offset = offsetof(_state, _field) \
85
+ type_check(uint32_t,typeof_field(_state, _field)), \
86
+ .set_default = true, \
87
.defval.u = (bool)_defval, \
88
}
89
90
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
91
.info = &(_prop), \
92
.offset = offsetof(_state, _field) \
93
+ type_check(_type, typeof_field(_state, _field)), \
94
+ .set_default = true, \
95
.defval.u = (_type)_defval, \
96
}
97
98
+#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
99
+ .name = (_name), \
100
+ .info = &(_prop), \
101
+ .offset = offsetof(_state, _field) \
102
+ + type_check(_type, typeof_field(_state, _field)), \
103
+ }
104
+
105
#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \
106
.name = (_name), \
107
.info = &(qdev_prop_bit64), \
108
.bitnr = (_bit), \
109
.offset = offsetof(_state, _field) \
110
+ type_check(uint64_t, typeof_field(_state, _field)), \
111
+ .set_default = true, \
112
.defval.u = (bool)_defval, \
113
}
114
115
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
116
.info = &(qdev_prop_bool), \
117
.offset = offsetof(_state, _field) \
118
+ type_check(bool, typeof_field(_state, _field)), \
119
+ .set_default = true, \
120
.defval.u = (bool)_defval, \
121
}
122
123
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
124
_arrayfield, _arrayprop, _arraytype) { \
125
.name = (PROP_ARRAY_LEN_PREFIX _name), \
126
.info = &(qdev_prop_arraylen), \
127
+ .set_default = true, \
128
.defval.u = 0, \
129
.offset = offsetof(_state, _field) \
130
+ type_check(uint32_t, typeof_field(_state, _field)), \
131
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/core/qdev.c
134
+++ b/hw/core/qdev.c
135
@@ -XXX,XX +XXX,XX @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
136
prop->info->description,
137
&error_abort);
138
139
- if (prop->info->set_default_value) {
140
+ if (prop->set_default) {
141
prop->info->set_default_value(obj, prop);
142
}
143
}
144
--
145
2.7.4
146
147
diff view generated by jsdifflib
Deleted patch
1
The Cortex-M3 and M4 CPUs always have 8 PMSA MPU regions (this isn't
2
a configurable option for the hardware). Make the default value of
3
the pmsav7-dregion property be set per-cpu, so we don't need to have
4
every user of these CPUs set it manually. (The existing default of
5
16 is correct for the other PMSAv7 core, the Cortex-R5.)
6
1
7
This fixes a bug where we were creating the M3 and M4 with
8
too many regions; most guest software would not notice or
9
care, though, since it would just not use the registers
10
associated with the unexpected extra regions.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
14
Message-id: 1499788408-10096-4-git-send-email-peter.maydell@linaro.org
15
---
16
target/arm/cpu.c | 12 +++++++++++-
17
1 file changed, 11 insertions(+), 1 deletion(-)
18
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_has_pmu_property =
24
static Property arm_cpu_has_mpu_property =
25
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
26
27
+/* This is like DEFINE_PROP_UINT32 but it doesn't set the default value,
28
+ * because the CPU initfn will have already set cpu->pmsav7_dregion to
29
+ * the right value for that particular CPU type, and we don't want
30
+ * to override that with an incorrect constant value.
31
+ */
32
static Property arm_cpu_pmsav7_dregion_property =
33
- DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
34
+ DEFINE_PROP_UNSIGNED_NODEFAULT("pmsav7-dregion", ARMCPU,
35
+ pmsav7_dregion,
36
+ qdev_prop_uint32, uint32_t);
37
38
static void arm_cpu_post_init(Object *obj)
39
{
40
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
41
set_feature(&cpu->env, ARM_FEATURE_V7);
42
set_feature(&cpu->env, ARM_FEATURE_M);
43
cpu->midr = 0x410fc231;
44
+ cpu->pmsav7_dregion = 8;
45
}
46
47
static void cortex_m4_initfn(Object *obj)
48
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
49
set_feature(&cpu->env, ARM_FEATURE_M);
50
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
51
cpu->midr = 0x410fc240; /* r0p0 */
52
+ cpu->pmsav7_dregion = 8;
53
}
54
static void arm_v7m_class_init(ObjectClass *oc, void *data)
55
{
56
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
57
cpu->id_isar4 = 0x0010142;
58
cpu->id_isar5 = 0x0;
59
cpu->mp_is_up = true;
60
+ cpu->pmsav7_dregion = 16;
61
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
62
}
63
64
--
65
2.7.4
66
67
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already have an exit condition, DISAS_UPDATE which will exit the
3
Indication for support for SVE will not depend on whether we
4
run-loop. Expand on the difference with DISAS_EXIT in the comments.
4
perform the query on the main kvm_state or the temp vcpu.
5
5
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <rth@twiddle.net>
7
Message-id: 20220726045828.53697-2-richard.henderson@linaro.org
8
Message-id: 20170713141928.25419-4-alex.bennee@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/translate.h | 5 ++++-
11
target/arm/kvm64.c | 2 +-
12
1 file changed, 4 insertions(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
13
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.h
16
--- a/target/arm/kvm64.c
17
+++ b/target/arm/translate.h
17
+++ b/target/arm/kvm64.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
18
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
19
*/
19
}
20
#define DISAS_BX_EXCRET 11
20
}
21
/* For instructions which want an immediate exit to the main loop,
21
22
- * as opposed to attempting to use lookup_and_goto_ptr.
22
- sve_supported = ioctl(fdarray[0], KVM_CHECK_EXTENSION, KVM_CAP_ARM_SVE) > 0;
23
+ * as opposed to attempting to use lookup_and_goto_ptr. Unlike
23
+ sve_supported = kvm_arm_sve_supported();
24
+ * DISAS_UPDATE this doesn't write the PC on exiting the translation
24
25
+ * loop so you need to ensure something (gen_a64_set_pc_im or runtime
25
/* Add feature bits that can't appear until after VCPU init. */
26
+ * helper) has done so before we reach return from cpu_tb_exec.
26
if (sve_supported) {
27
*/
28
#define DISAS_EXIT 12
29
30
--
27
--
31
2.7.4
28
2.25.1
32
33
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
DISAS_UPDATE should be used when the wider CPU state other than just
3
Because we weren't setting this flag, our probe of ID_AA64ZFR0
4
the PC has been updated and we should therefore exit the TCG runtime
4
was always returning zero. This also obviates the adjustment
5
and return to the main execution loop rather assuming DISAS_JUMP would
5
of ID_AA64PFR0, which had sanitized the SVE field.
6
do that.
7
6
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
The effects of the bug are not visible, because the only thing that
9
Reviewed-by: Richard Henderson <rth@twiddle.net>
8
ID_AA64ZFR0 is used for within qemu at present is tcg translation.
10
Message-id: 20170713141928.25419-3-alex.bennee@linaro.org
9
The other tests for SVE within KVM are via ID_AA64PFR0.SVE.
10
11
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220726045828.53697-3-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
target/arm/translate-a64.c | 14 +++++++-------
17
target/arm/kvm64.c | 27 +++++++++++++--------------
14
target/arm/translate.c | 6 +++---
18
1 file changed, 13 insertions(+), 14 deletions(-)
15
2 files changed, 10 insertions(+), 10 deletions(-)
16
19
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
20
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
22
--- a/target/arm/kvm64.c
20
+++ b/target/arm/translate-a64.c
23
+++ b/target/arm/kvm64.c
21
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
24
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
22
case DISAS_NEXT:
25
bool sve_supported;
23
gen_goto_tb(dc, 1, dc->pc);
26
bool pmu_supported = false;
24
break;
27
uint64_t features = 0;
25
- default:
28
- uint64_t t;
26
- case DISAS_UPDATE:
29
int err;
27
- gen_a64_set_pc_im(dc->pc);
30
28
- /* fall through */
31
/* Old kernels may not know about the PREFERRED_TARGET ioctl: however
29
case DISAS_JUMP:
32
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
30
tcg_gen_lookup_and_goto_ptr(cpu_pc);
33
struct kvm_vcpu_init init = { .target = -1, };
31
break;
34
32
- case DISAS_EXIT:
35
/*
33
- tcg_gen_exit_tb(0);
36
- * Ask for Pointer Authentication if supported. We can't play the
34
- break;
37
- * SVE trick of synthesising the ID reg as KVM won't tell us
35
case DISAS_TB_JUMP:
38
- * whether we have the architected or IMPDEF version of PAuth, so
36
case DISAS_EXC:
39
- * we have to use the actual ID regs.
37
case DISAS_SWI:
40
+ * Ask for SVE if supported, so that we can query ID_AA64ZFR0,
38
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
41
+ * which is otherwise RAZ.
39
*/
42
+ */
40
tcg_gen_exit_tb(0);
43
+ sve_supported = kvm_arm_sve_supported();
41
break;
44
+ if (sve_supported) {
42
+ case DISAS_UPDATE:
45
+ init.features[0] |= 1 << KVM_ARM_VCPU_SVE;
43
+ gen_a64_set_pc_im(dc->pc);
46
+ }
44
+ /* fall through */
47
+
45
+ case DISAS_EXIT:
48
+ /*
46
+ default:
49
+ * Ask for Pointer Authentication if supported, so that we get
47
+ tcg_gen_exit_tb(0);
50
+ * the unsanitized field values for AA64ISAR1_EL1.
48
+ break;
51
*/
52
if (kvm_arm_pauth_supported()) {
53
init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS |
54
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
49
}
55
}
50
}
56
}
51
57
52
diff --git a/target/arm/translate.c b/target/arm/translate.c
58
- sve_supported = kvm_arm_sve_supported();
53
index XXXXXXX..XXXXXXX 100644
59
-
54
--- a/target/arm/translate.c
60
- /* Add feature bits that can't appear until after VCPU init. */
55
+++ b/target/arm/translate.c
61
if (sve_supported) {
56
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
62
- t = ahcf->isar.id_aa64pfr0;
57
case DISAS_NEXT:
63
- t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
58
gen_goto_tb(dc, 1, dc->pc);
64
- ahcf->isar.id_aa64pfr0 = t;
59
break;
65
-
60
- case DISAS_UPDATE:
66
/*
61
- gen_set_pc_im(dc, dc->pc);
67
* There is a range of kernels between kernel commit 73433762fcae
62
- /* fall through */
68
* and f81cb2c3ad41 which have a bug where the kernel doesn't expose
63
case DISAS_JUMP:
69
* SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has enabled
64
gen_goto_ptr();
70
- * SVE support, so we only read it here, rather than together with all
65
break;
71
- * the other ID registers earlier.
66
+ case DISAS_UPDATE:
72
+ * SVE support, which resulted in an error rather than RAZ.
67
+ gen_set_pc_im(dc, dc->pc);
73
+ * So only read the register if we set KVM_ARM_VCPU_SVE above.
68
+ /* fall through */
74
*/
69
default:
75
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0,
70
/* indicate that the hash table must be used to find the next TB */
76
ARM64_SYS_REG(3, 0, 0, 4, 4));
71
tcg_gen_exit_tb(0);
72
--
77
--
73
2.7.4
78
2.25.1
74
75
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
As a precursor to later patches attempt to come up with a more
3
The test for the IF block indicates no ID registers are exposed, much
4
concrete wording for what each of the common exit cases would be.
4
less host support for SVE. Move the SVE probe into the ELSE block.
5
5
6
CC: Emilio G. Cota <cota@braap.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
CC: Richard Henderson <rth@twiddle.net>
7
Message-id: 20220726045828.53697-4-richard.henderson@linaro.org
8
CC: Lluís Vilanova <vilanova@ac.upc.edu>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Richard Henderson <rth@twiddle.net>
11
Message-id: 20170713141928.25419-2-alex.bennee@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
include/exec/exec-all.h | 29 ++++++++++++++++++++++++++---
11
target/arm/kvm64.c | 22 +++++++++++-----------
15
1 file changed, 26 insertions(+), 3 deletions(-)
12
1 file changed, 11 insertions(+), 11 deletions(-)
16
13
17
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
14
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/exec-all.h
16
--- a/target/arm/kvm64.c
20
+++ b/include/exec/exec-all.h
17
+++ b/target/arm/kvm64.c
21
@@ -XXX,XX +XXX,XX @@ typedef abi_ulong tb_page_addr_t;
18
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
22
typedef ram_addr_t tb_page_addr_t;
19
err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0,
23
#endif
20
ARM64_SYS_REG(3, 3, 9, 12, 0));
24
21
}
25
-/* is_jmp field values */
22
- }
26
+/* DisasContext is_jmp field values
23
27
+ *
24
- if (sve_supported) {
28
+ * is_jmp starts as DISAS_NEXT. The translator will keep processing
25
- /*
29
+ * instructions until an exit condition is reached. If we reach the
26
- * There is a range of kernels between kernel commit 73433762fcae
30
+ * exit condition and is_jmp is still DISAS_NEXT (because of some
27
- * and f81cb2c3ad41 which have a bug where the kernel doesn't expose
31
+ * other condition) we simply "jump" to the next address.
28
- * SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has enabled
32
+ * The remaining exit cases are:
29
- * SVE support, which resulted in an error rather than RAZ.
33
+ *
30
- * So only read the register if we set KVM_ARM_VCPU_SVE above.
34
+ * DISAS_JUMP - Only the PC was modified dynamically (e.g computed)
31
- */
35
+ * DISAS_TB_JUMP - Only the PC was modified statically (e.g. branch)
32
- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0,
36
+ *
33
- ARM64_SYS_REG(3, 0, 0, 4, 4));
37
+ * In these cases as long as the PC is updated we can chain to the
34
+ if (sve_supported) {
38
+ * next TB either by exiting the loop or looking up the next TB via
35
+ /*
39
+ * the loookup helper.
36
+ * There is a range of kernels between kernel commit 73433762fcae
40
+ *
37
+ * and f81cb2c3ad41 which have a bug where the kernel doesn't
41
+ * DISAS_UPDATE - CPU State was modified dynamically
38
+ * expose SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has
42
+ *
39
+ * enabled SVE support, which resulted in an error rather than RAZ.
43
+ * This covers any other CPU state which necessities us exiting the
40
+ * So only read the register if we set KVM_ARM_VCPU_SVE above.
44
+ * TCG code to the main run-loop. Typically this includes anything
41
+ */
45
+ * that might change the interrupt state.
42
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0,
46
+ *
43
+ ARM64_SYS_REG(3, 0, 0, 4, 4));
47
+ * Individual translators may define additional exit cases to deal
44
+ }
48
+ * with per-target special conditions.
45
}
49
+ */
46
50
#define DISAS_NEXT 0 /* next instruction can be analyzed */
47
kvm_arm_destroy_scratch_host_vcpu(fdarray);
51
#define DISAS_JUMP 1 /* only pc was modified dynamically */
52
-#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
53
-#define DISAS_TB_JUMP 3 /* only pc was modified statically */
54
+#define DISAS_TB_JUMP 2 /* only pc was modified statically */
55
+#define DISAS_UPDATE 3 /* cpu state was modified dynamically */
56
57
#include "qemu/log.h"
58
59
--
48
--
60
2.7.4
49
2.25.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Alex Bennée <alex.bennee@linaro.org>
2
1
3
As the gen_goto_tb function can do both static and dynamic jumps it
4
should also set the is_jmp field. This matches the behaviour of the
5
a64 code.
6
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Richard Henderson <rth@twiddle.net>
9
Message-id: 20170713141928.25419-5-alex.bennee@linaro.org
10
[tweak to multiline comment formatting]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/translate.c | 6 +++++-
14
1 file changed, 5 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
21
tcg_temp_free(addr);
22
}
23
24
+/* This will end the TB but doesn't guarantee we'll return to
25
+ * cpu_loop_exec. Any live exit_requests will be processed as we
26
+ * enter the next TB.
27
+ */
28
static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
29
{
30
if (use_goto_tb(s, dest)) {
31
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
32
gen_set_pc_im(s, dest);
33
gen_goto_ptr();
34
}
35
+ s->is_jmp = DISAS_TB_JUMP;
36
}
37
38
static inline void gen_jmp (DisasContext *s, uint32_t dest)
39
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
40
gen_bx_im(s, dest);
41
} else {
42
gen_goto_tb(s, 0, dest);
43
- s->is_jmp = DISAS_TB_JUMP;
44
}
45
}
46
47
--
48
2.7.4
49
50
diff view generated by jsdifflib
Deleted patch
1
From: Alex Bennée <alex.bennee@linaro.org>
2
1
3
While an ISB will ensure any raised IRQs happen on the next
4
instruction it doesn't cause any to get raised by itself. We can
5
therefore use a simple tb exit for ISB instructions and rely on the
6
exit_request check at the top of each TB to deal with exiting if
7
needed.
8
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Richard Henderson <rth@twiddle.net>
11
Message-id: 20170713141928.25419-6-alex.bennee@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/translate-a64.c | 2 +-
15
target/arm/translate.c | 4 ++--
16
2 files changed, 3 insertions(+), 3 deletions(-)
17
18
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-a64.c
21
+++ b/target/arm/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
23
* a self-modified code correctly and also to take
24
* any pending interrupts immediately.
25
*/
26
- s->is_jmp = DISAS_UPDATE;
27
+ gen_goto_tb(s, 0, s->pc);
28
return;
29
default:
30
unallocated_encoding(s);
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.c
34
+++ b/target/arm/translate.c
35
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
36
* self-modifying code correctly and also to take
37
* any pending interrupts immediately.
38
*/
39
- gen_lookup_tb(s);
40
+ gen_goto_tb(s, 0, s->pc & ~1);
41
return;
42
default:
43
goto illegal_op;
44
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
45
* and also to take any pending interrupts
46
* immediately.
47
*/
48
- gen_lookup_tb(s);
49
+ gen_goto_tb(s, 0, s->pc & ~1);
50
break;
51
default:
52
goto illegal_op;
53
--
54
2.7.4
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Alex Bennée <alex.bennee@linaro.org>
2
1
3
Previously DISAS_JUMP did ensure this but with the optimisation of
4
8a6b28c7 (optimize indirect branches) we might not leave the loop.
5
This means if any pending interrupts are cleared by changing IRQ flags
6
we might never get around to servicing them. You usually notice this
7
by seeing the lookup_tb_ptr() helper gainfully chaining TBs together
8
while cpu->interrupt_request remains high and the exit_request has not
9
been set.
10
11
This breaks amongst other things the OPTEE test suite which executes
12
an eret from the secure world after a non-secure world IRQ has gone
13
pending which then never gets serviced.
14
15
Instead of using the previously implied semantics of DISAS_JUMP we use
16
DISAS_EXIT which will always exit the run-loop.
17
18
CC: Etienne Carriere <etienne.carriere@linaro.org>
19
CC: Joakim Bech <joakim.bech@linaro.org>
20
CC: Jaroslaw Pelczar <j.pelczar@samsung.com>
21
CC: Peter Maydell <peter.maydell@linaro.org>
22
CC: Emilio G. Cota <cota@braap.org>
23
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
24
Reviewed-by: Richard Henderson <rth@twiddle.net>
25
Message-id: 20170713141928.25419-7-alex.bennee@linaro.org
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
28
target/arm/translate-a64.c | 3 ++-
29
target/arm/translate.c | 6 ++++--
30
2 files changed, 6 insertions(+), 3 deletions(-)
31
32
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-a64.c
35
+++ b/target/arm/translate-a64.c
36
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
37
return;
38
}
39
gen_helper_exception_return(cpu_env);
40
- s->is_jmp = DISAS_JUMP;
41
+ /* Must exit loop to check un-masked IRQs */
42
+ s->is_jmp = DISAS_EXIT;
43
return;
44
case 5: /* DRPS */
45
if (rn != 0x1f) {
46
diff --git a/target/arm/translate.c b/target/arm/translate.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate.c
49
+++ b/target/arm/translate.c
50
@@ -XXX,XX +XXX,XX @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
51
*/
52
gen_helper_cpsr_write_eret(cpu_env, cpsr);
53
tcg_temp_free_i32(cpsr);
54
- s->is_jmp = DISAS_JUMP;
55
+ /* Must exit loop to check un-masked IRQs */
56
+ s->is_jmp = DISAS_EXIT;
57
}
58
59
/* Generate an old-style exception return. Marks pc as dead. */
60
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
61
tmp = load_cpu_field(spsr);
62
gen_helper_cpsr_write_eret(cpu_env, tmp);
63
tcg_temp_free_i32(tmp);
64
- s->is_jmp = DISAS_JUMP;
65
+ /* Must exit loop to check un-masked IRQs */
66
+ s->is_jmp = DISAS_EXIT;
67
}
68
}
69
break;
70
--
71
2.7.4
72
73
diff view generated by jsdifflib
Deleted patch
1
Model the ARM MPS2/MPS2+ FPGA based development board.
2
1
3
The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
4
FPGA but is otherwise the same as the 2). Since the CPU itself
5
and most of the devices are in the FPGA, the details of the board
6
as seen by the guest depend significantly on the FPGA image.
7
8
We model the following FPGA images:
9
"mps2_an385" -- Cortex-M3 as documented in ARM Application Note AN385
10
"mps2_an511" -- Cortex-M3 'DesignStart' as documented in AN511
11
12
They are fairly similar but differ in the details for some
13
peripherals.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1500029487-14822-2-git-send-email-peter.maydell@linaro.org
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
19
hw/arm/Makefile.objs | 1 +
20
hw/arm/mps2.c | 270 ++++++++++++++++++++++++++++++++++++++++
21
default-configs/arm-softmmu.mak | 1 +
22
3 files changed, 272 insertions(+)
23
create mode 100644 hw/arm/mps2.c
24
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
28
+++ b/hw/arm/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
30
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
31
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
32
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
33
+obj-$(CONFIG_MPS2) += mps2.o
34
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/hw/arm/mps2.c
39
@@ -XXX,XX +XXX,XX @@
40
+/*
41
+ * ARM V2M MPS2 board emulation.
42
+ *
43
+ * Copyright (c) 2017 Linaro Limited
44
+ * Written by Peter Maydell
45
+ *
46
+ * This program is free software; you can redistribute it and/or modify
47
+ * it under the terms of the GNU General Public License version 2 or
48
+ * (at your option) any later version.
49
+ */
50
+
51
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
52
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
53
+ * and most of the devices are in the FPGA, the details of the board
54
+ * as seen by the guest depend significantly on the FPGA image.
55
+ * We model the following FPGA images:
56
+ * "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
57
+ * "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
58
+ *
59
+ * Links to the TRM for the board itself and to the various Application
60
+ * Notes which document the FPGA images can be found here:
61
+ * https://developer.arm.com/products/system-design/development-boards/cortex-m-prototyping-system
62
+ */
63
+
64
+#include "qemu/osdep.h"
65
+#include "qapi/error.h"
66
+#include "qemu/error-report.h"
67
+#include "hw/arm/arm.h"
68
+#include "hw/arm/armv7m.h"
69
+#include "hw/boards.h"
70
+#include "exec/address-spaces.h"
71
+#include "hw/misc/unimp.h"
72
+
73
+typedef enum MPS2FPGAType {
74
+ FPGA_AN385,
75
+ FPGA_AN511,
76
+} MPS2FPGAType;
77
+
78
+typedef struct {
79
+ MachineClass parent;
80
+ MPS2FPGAType fpga_type;
81
+ const char *cpu_model;
82
+} MPS2MachineClass;
83
+
84
+typedef struct {
85
+ MachineState parent;
86
+
87
+ ARMv7MState armv7m;
88
+ MemoryRegion psram;
89
+ MemoryRegion ssram1;
90
+ MemoryRegion ssram1_m;
91
+ MemoryRegion ssram23;
92
+ MemoryRegion ssram23_m;
93
+ MemoryRegion blockram;
94
+ MemoryRegion blockram_m1;
95
+ MemoryRegion blockram_m2;
96
+ MemoryRegion blockram_m3;
97
+ MemoryRegion sram;
98
+} MPS2MachineState;
99
+
100
+#define TYPE_MPS2_MACHINE "mps2"
101
+#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
102
+#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
103
+
104
+#define MPS2_MACHINE(obj) \
105
+ OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE)
106
+#define MPS2_MACHINE_GET_CLASS(obj) \
107
+ OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE)
108
+#define MPS2_MACHINE_CLASS(klass) \
109
+ OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE)
110
+
111
+/* Main SYSCLK frequency in Hz */
112
+#define SYSCLK_FRQ 25000000
113
+
114
+/* Initialize the auxiliary RAM region @mr and map it into
115
+ * the memory map at @base.
116
+ */
117
+static void make_ram(MemoryRegion *mr, const char *name,
118
+ hwaddr base, hwaddr size)
119
+{
120
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
121
+ memory_region_add_subregion(get_system_memory(), base, mr);
122
+}
123
+
124
+/* Create an alias of an entire original MemoryRegion @orig
125
+ * located at @base in the memory map.
126
+ */
127
+static void make_ram_alias(MemoryRegion *mr, const char *name,
128
+ MemoryRegion *orig, hwaddr base)
129
+{
130
+ memory_region_init_alias(mr, NULL, name, orig, 0,
131
+ memory_region_size(orig));
132
+ memory_region_add_subregion(get_system_memory(), base, mr);
133
+}
134
+
135
+static void mps2_common_init(MachineState *machine)
136
+{
137
+ MPS2MachineState *mms = MPS2_MACHINE(machine);
138
+ MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine);
139
+ MemoryRegion *system_memory = get_system_memory();
140
+ DeviceState *armv7m;
141
+
142
+ if (!machine->cpu_model) {
143
+ machine->cpu_model = mmc->cpu_model;
144
+ }
145
+
146
+ if (strcmp(machine->cpu_model, mmc->cpu_model) != 0) {
147
+ error_report("This board can only be used with CPU %s", mmc->cpu_model);
148
+ exit(1);
149
+ }
150
+
151
+ /* The FPGA images have an odd combination of different RAMs,
152
+ * because in hardware they are different implementations and
153
+ * connected to different buses, giving varying performance/size
154
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
155
+ * call the 16MB our "system memory", as it's the largest lump.
156
+ *
157
+ * Common to both boards:
158
+ * 0x21000000..0x21ffffff : PSRAM (16MB)
159
+ * AN385 only:
160
+ * 0x00000000 .. 0x003fffff : ZBT SSRAM1
161
+ * 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
162
+ * 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
163
+ * 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
164
+ * 0x01000000 .. 0x01003fff : block RAM (16K)
165
+ * 0x01004000 .. 0x01007fff : mirror of above
166
+ * 0x01008000 .. 0x0100bfff : mirror of above
167
+ * 0x0100c000 .. 0x0100ffff : mirror of above
168
+ * AN511 only:
169
+ * 0x00000000 .. 0x0003ffff : FPGA block RAM
170
+ * 0x00400000 .. 0x007fffff : ZBT SSRAM1
171
+ * 0x20000000 .. 0x2001ffff : SRAM
172
+ * 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
173
+ *
174
+ * The AN385 has a feature where the lowest 16K can be mapped
175
+ * either to the bottom of the ZBT SSRAM1 or to the block RAM.
176
+ * This is of no use for QEMU so we don't implement it (as if
177
+ * zbt_boot_ctrl is always zero).
178
+ */
179
+ memory_region_allocate_system_memory(&mms->psram,
180
+ NULL, "mps.ram", 0x1000000);
181
+ memory_region_add_subregion(system_memory, 0x21000000, &mms->psram);
182
+
183
+ switch (mmc->fpga_type) {
184
+ case FPGA_AN385:
185
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
186
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
187
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
188
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
189
+ &mms->ssram23, 0x20400000);
190
+ make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
191
+ make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
192
+ &mms->blockram, 0x01004000);
193
+ make_ram_alias(&mms->blockram_m2, "mps.blockram_m2",
194
+ &mms->blockram, 0x01008000);
195
+ make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
196
+ &mms->blockram, 0x0100c000);
197
+ break;
198
+ case FPGA_AN511:
199
+ make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
200
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00400000, 0x00800000);
201
+ make_ram(&mms->sram, "mps.sram", 0x20000000, 0x20000);
202
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20400000, 0x400000);
203
+ break;
204
+ default:
205
+ g_assert_not_reached();
206
+ }
207
+
208
+ object_initialize(&mms->armv7m, sizeof(mms->armv7m), TYPE_ARMV7M);
209
+ armv7m = DEVICE(&mms->armv7m);
210
+ qdev_set_parent_bus(armv7m, sysbus_get_default());
211
+ switch (mmc->fpga_type) {
212
+ case FPGA_AN385:
213
+ qdev_prop_set_uint32(armv7m, "num-irq", 32);
214
+ break;
215
+ case FPGA_AN511:
216
+ qdev_prop_set_uint32(armv7m, "num-irq", 64);
217
+ break;
218
+ default:
219
+ g_assert_not_reached();
220
+ }
221
+ qdev_prop_set_string(armv7m, "cpu-model", machine->cpu_model);
222
+ object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory),
223
+ "memory", &error_abort);
224
+ object_property_set_bool(OBJECT(&mms->armv7m), true, "realized",
225
+ &error_fatal);
226
+
227
+ create_unimplemented_device("zbtsmram mirror", 0x00400000, 0x00400000);
228
+ create_unimplemented_device("RESERVED 1", 0x00800000, 0x00800000);
229
+ create_unimplemented_device("Block RAM", 0x01000000, 0x00010000);
230
+ create_unimplemented_device("RESERVED 2", 0x01010000, 0x1EFF0000);
231
+ create_unimplemented_device("RESERVED 3", 0x20800000, 0x00800000);
232
+ create_unimplemented_device("PSRAM", 0x21000000, 0x01000000);
233
+ /* These three ranges all cover multiple devices; we may implement
234
+ * some of them below (in which case the real device takes precedence
235
+ * over the unimplemented-region mapping).
236
+ */
237
+ create_unimplemented_device("CMSDK APB peripheral region @0x40000000",
238
+ 0x40000000, 0x00010000);
239
+ create_unimplemented_device("CMSDK peripheral region @0x40010000",
240
+ 0x40010000, 0x00010000);
241
+ create_unimplemented_device("Extra peripheral region @0x40020000",
242
+ 0x40020000, 0x00010000);
243
+ create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
244
+ create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
245
+ create_unimplemented_device("VGA", 0x41000000, 0x0200000);
246
+
247
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
248
+
249
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
250
+ 0x400000);
251
+}
252
+
253
+static void mps2_class_init(ObjectClass *oc, void *data)
254
+{
255
+ MachineClass *mc = MACHINE_CLASS(oc);
256
+
257
+ mc->init = mps2_common_init;
258
+ mc->max_cpus = 1;
259
+}
260
+
261
+static void mps2_an385_class_init(ObjectClass *oc, void *data)
262
+{
263
+ MachineClass *mc = MACHINE_CLASS(oc);
264
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
265
+
266
+ mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
267
+ mmc->fpga_type = FPGA_AN385;
268
+ mmc->cpu_model = "cortex-m3";
269
+}
270
+
271
+static void mps2_an511_class_init(ObjectClass *oc, void *data)
272
+{
273
+ MachineClass *mc = MACHINE_CLASS(oc);
274
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
275
+
276
+ mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
277
+ mmc->fpga_type = FPGA_AN511;
278
+ mmc->cpu_model = "cortex-m3";
279
+}
280
+
281
+static const TypeInfo mps2_info = {
282
+ .name = TYPE_MPS2_MACHINE,
283
+ .parent = TYPE_MACHINE,
284
+ .abstract = true,
285
+ .instance_size = sizeof(MPS2MachineState),
286
+ .class_size = sizeof(MPS2MachineClass),
287
+ .class_init = mps2_class_init,
288
+};
289
+
290
+static const TypeInfo mps2_an385_info = {
291
+ .name = TYPE_MPS2_AN385_MACHINE,
292
+ .parent = TYPE_MPS2_MACHINE,
293
+ .class_init = mps2_an385_class_init,
294
+};
295
+
296
+static const TypeInfo mps2_an511_info = {
297
+ .name = TYPE_MPS2_AN511_MACHINE,
298
+ .parent = TYPE_MPS2_MACHINE,
299
+ .class_init = mps2_an511_class_init,
300
+};
301
+
302
+static void mps2_machine_init(void)
303
+{
304
+ type_register_static(&mps2_info);
305
+ type_register_static(&mps2_an385_info);
306
+ type_register_static(&mps2_an511_info);
307
+}
308
+
309
+type_init(mps2_machine_init);
310
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
311
index XXXXXXX..XXXXXXX 100644
312
--- a/default-configs/arm-softmmu.mak
313
+++ b/default-configs/arm-softmmu.mak
314
@@ -XXX,XX +XXX,XX @@ CONFIG_ONENAND=y
315
CONFIG_TUSB6010=y
316
CONFIG_IMX=y
317
CONFIG_MAINSTONE=y
318
+CONFIG_MPS2=y
319
CONFIG_NSERIES=y
320
CONFIG_RASPI=y
321
CONFIG_REALVIEW=y
322
--
323
2.7.4
324
325
diff view generated by jsdifflib
Deleted patch
1
Implement a model of the simple "APB UART" provided in
2
the Cortex-M System Design Kit (CMSDK).
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 1500029487-14822-3-git-send-email-peter.maydell@linaro.org
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
---
8
hw/char/Makefile.objs | 1 +
9
include/hw/char/cmsdk-apb-uart.h | 78 ++++++++
10
hw/char/cmsdk-apb-uart.c | 403 +++++++++++++++++++++++++++++++++++++++
11
default-configs/arm-softmmu.mak | 2 +
12
hw/char/trace-events | 9 +
13
5 files changed, 493 insertions(+)
14
create mode 100644 include/hw/char/cmsdk-apb-uart.h
15
create mode 100644 hw/char/cmsdk-apb-uart.c
16
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/Makefile.objs
20
+++ b/hw/char/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic-uart.o
22
obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
23
obj-$(CONFIG_RASPI) += bcm2835_aux.o
24
25
+common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o
26
common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
27
common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o
28
common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o
29
diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h
30
new file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- /dev/null
33
+++ b/include/hw/char/cmsdk-apb-uart.h
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * ARM CMSDK APB UART emulation
37
+ *
38
+ * Copyright (c) 2017 Linaro Limited
39
+ * Written by Peter Maydell
40
+ *
41
+ * This program is free software; you can redistribute it and/or modify
42
+ * it under the terms of the GNU General Public License version 2 or
43
+ * (at your option) any later version.
44
+ */
45
+
46
+#ifndef CMSDK_APB_UART_H
47
+#define CMSDK_APB_UART_H
48
+
49
+#include "hw/sysbus.h"
50
+#include "chardev/char-fe.h"
51
+
52
+#define TYPE_CMSDK_APB_UART "cmsdk-apb-uart"
53
+#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \
54
+ TYPE_CMSDK_APB_UART)
55
+
56
+typedef struct {
57
+ /*< private >*/
58
+ SysBusDevice parent_obj;
59
+
60
+ /*< public >*/
61
+ MemoryRegion iomem;
62
+ CharBackend chr;
63
+ qemu_irq txint;
64
+ qemu_irq rxint;
65
+ qemu_irq txovrint;
66
+ qemu_irq rxovrint;
67
+ qemu_irq uartint;
68
+ guint watch_tag;
69
+ uint32_t pclk_frq;
70
+
71
+ uint32_t state;
72
+ uint32_t ctrl;
73
+ uint32_t intstatus;
74
+ uint32_t bauddiv;
75
+ /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */
76
+ uint8_t txbuf;
77
+ uint8_t rxbuf;
78
+} CMSDKAPBUART;
79
+
80
+/**
81
+ * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART
82
+ * @addr: location in system memory to map registers
83
+ * @chr: Chardev backend to connect UART to, or NULL if no backend
84
+ * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
85
+ */
86
+static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr,
87
+ qemu_irq txint,
88
+ qemu_irq rxint,
89
+ qemu_irq txovrint,
90
+ qemu_irq rxovrint,
91
+ qemu_irq uartint,
92
+ Chardev *chr,
93
+ uint32_t pclk_frq)
94
+{
95
+ DeviceState *dev;
96
+ SysBusDevice *s;
97
+
98
+ dev = qdev_create(NULL, TYPE_CMSDK_APB_UART);
99
+ s = SYS_BUS_DEVICE(dev);
100
+ qdev_prop_set_chr(dev, "chardev", chr);
101
+ qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
102
+ qdev_init_nofail(dev);
103
+ sysbus_mmio_map(s, 0, addr);
104
+ sysbus_connect_irq(s, 0, txint);
105
+ sysbus_connect_irq(s, 1, rxint);
106
+ sysbus_connect_irq(s, 2, txovrint);
107
+ sysbus_connect_irq(s, 3, rxovrint);
108
+ sysbus_connect_irq(s, 4, uartint);
109
+ return dev;
110
+}
111
+
112
+#endif
113
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
114
new file mode 100644
115
index XXXXXXX..XXXXXXX
116
--- /dev/null
117
+++ b/hw/char/cmsdk-apb-uart.c
118
@@ -XXX,XX +XXX,XX @@
119
+/*
120
+ * ARM CMSDK APB UART emulation
121
+ *
122
+ * Copyright (c) 2017 Linaro Limited
123
+ * Written by Peter Maydell
124
+ *
125
+ * This program is free software; you can redistribute it and/or modify
126
+ * it under the terms of the GNU General Public License version 2 or
127
+ * (at your option) any later version.
128
+ */
129
+
130
+/* This is a model of the "APB UART" which is part of the Cortex-M
131
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
132
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
133
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
134
+ */
135
+
136
+#include "qemu/osdep.h"
137
+#include "qemu/log.h"
138
+#include "qapi/error.h"
139
+#include "trace.h"
140
+#include "hw/sysbus.h"
141
+#include "hw/registerfields.h"
142
+#include "chardev/char-fe.h"
143
+#include "chardev/char-serial.h"
144
+#include "hw/char/cmsdk-apb-uart.h"
145
+
146
+REG32(DATA, 0)
147
+REG32(STATE, 4)
148
+ FIELD(STATE, TXFULL, 0, 1)
149
+ FIELD(STATE, RXFULL, 1, 1)
150
+ FIELD(STATE, TXOVERRUN, 2, 1)
151
+ FIELD(STATE, RXOVERRUN, 3, 1)
152
+REG32(CTRL, 8)
153
+ FIELD(CTRL, TX_EN, 0, 1)
154
+ FIELD(CTRL, RX_EN, 1, 1)
155
+ FIELD(CTRL, TX_INTEN, 2, 1)
156
+ FIELD(CTRL, RX_INTEN, 3, 1)
157
+ FIELD(CTRL, TXO_INTEN, 4, 1)
158
+ FIELD(CTRL, RXO_INTEN, 5, 1)
159
+ FIELD(CTRL, HSTEST, 6, 1)
160
+REG32(INTSTATUS, 0xc)
161
+ FIELD(INTSTATUS, TX, 0, 1)
162
+ FIELD(INTSTATUS, RX, 1, 1)
163
+ FIELD(INTSTATUS, TXO, 2, 1)
164
+ FIELD(INTSTATUS, RXO, 3, 1)
165
+REG32(BAUDDIV, 0x10)
166
+REG32(PID4, 0xFD0)
167
+REG32(PID5, 0xFD4)
168
+REG32(PID6, 0xFD8)
169
+REG32(PID7, 0xFDC)
170
+REG32(PID0, 0xFE0)
171
+REG32(PID1, 0xFE4)
172
+REG32(PID2, 0xFE8)
173
+REG32(PID3, 0xFEC)
174
+REG32(CID0, 0xFF0)
175
+REG32(CID1, 0xFF4)
176
+REG32(CID2, 0xFF8)
177
+REG32(CID3, 0xFFC)
178
+
179
+/* PID/CID values */
180
+static const int uart_id[] = {
181
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
182
+ 0x21, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
183
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
184
+};
185
+
186
+static bool uart_baudrate_ok(CMSDKAPBUART *s)
187
+{
188
+ /* The minimum permitted bauddiv setting is 16, so we just ignore
189
+ * settings below that (usually this means the device has just
190
+ * been reset and not yet programmed).
191
+ */
192
+ return s->bauddiv >= 16 && s->bauddiv <= s->pclk_frq;
193
+}
194
+
195
+static void uart_update_parameters(CMSDKAPBUART *s)
196
+{
197
+ QEMUSerialSetParams ssp;
198
+
199
+ /* This UART is always 8N1 but the baud rate is programmable. */
200
+ if (!uart_baudrate_ok(s)) {
201
+ return;
202
+ }
203
+
204
+ ssp.data_bits = 8;
205
+ ssp.parity = 'N';
206
+ ssp.stop_bits = 1;
207
+ ssp.speed = s->pclk_frq / s->bauddiv;
208
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
209
+ trace_cmsdk_apb_uart_set_params(ssp.speed);
210
+}
211
+
212
+static void cmsdk_apb_uart_update(CMSDKAPBUART *s)
213
+{
214
+ /* update outbound irqs, including handling the way the rxo and txo
215
+ * interrupt status bits are just logical AND of the overrun bit in
216
+ * STATE and the overrun interrupt enable bit in CTRL.
217
+ */
218
+ uint32_t omask = (R_INTSTATUS_RXO_MASK | R_INTSTATUS_TXO_MASK);
219
+ s->intstatus &= ~omask;
220
+ s->intstatus |= (s->state & (s->ctrl >> 2) & omask);
221
+
222
+ qemu_set_irq(s->txint, !!(s->intstatus & R_INTSTATUS_TX_MASK));
223
+ qemu_set_irq(s->rxint, !!(s->intstatus & R_INTSTATUS_RX_MASK));
224
+ qemu_set_irq(s->txovrint, !!(s->intstatus & R_INTSTATUS_TXO_MASK));
225
+ qemu_set_irq(s->rxovrint, !!(s->intstatus & R_INTSTATUS_RXO_MASK));
226
+ qemu_set_irq(s->uartint, !!(s->intstatus));
227
+}
228
+
229
+static int uart_can_receive(void *opaque)
230
+{
231
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
232
+
233
+ /* We can take a char if RX is enabled and the buffer is empty */
234
+ if (s->ctrl & R_CTRL_RX_EN_MASK && !(s->state & R_STATE_RXFULL_MASK)) {
235
+ return 1;
236
+ }
237
+ return 0;
238
+}
239
+
240
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
241
+{
242
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
243
+
244
+ trace_cmsdk_apb_uart_receive(*buf);
245
+
246
+ /* In fact uart_can_receive() ensures that we can't be
247
+ * called unless RX is enabled and the buffer is empty,
248
+ * but we include this logic as documentation of what the
249
+ * hardware does if a character arrives in these circumstances.
250
+ */
251
+ if (!(s->ctrl & R_CTRL_RX_EN_MASK)) {
252
+ /* Just drop the character on the floor */
253
+ return;
254
+ }
255
+
256
+ if (s->state & R_STATE_RXFULL_MASK) {
257
+ s->state |= R_STATE_RXOVERRUN_MASK;
258
+ }
259
+
260
+ s->rxbuf = *buf;
261
+ s->state |= R_STATE_RXFULL_MASK;
262
+ if (s->ctrl & R_CTRL_RX_INTEN_MASK) {
263
+ s->intstatus |= R_INTSTATUS_RX_MASK;
264
+ }
265
+ cmsdk_apb_uart_update(s);
266
+}
267
+
268
+static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
269
+{
270
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
271
+ uint64_t r;
272
+
273
+ switch (offset) {
274
+ case A_DATA:
275
+ r = s->rxbuf;
276
+ s->state &= ~R_STATE_RXFULL_MASK;
277
+ cmsdk_apb_uart_update(s);
278
+ break;
279
+ case A_STATE:
280
+ r = s->state;
281
+ break;
282
+ case A_CTRL:
283
+ r = s->ctrl;
284
+ break;
285
+ case A_INTSTATUS:
286
+ r = s->intstatus;
287
+ break;
288
+ case A_BAUDDIV:
289
+ r = s->bauddiv;
290
+ break;
291
+ case A_PID4 ... A_CID3:
292
+ r = uart_id[(offset - A_PID4) / 4];
293
+ break;
294
+ default:
295
+ qemu_log_mask(LOG_GUEST_ERROR,
296
+ "CMSDK APB UART read: bad offset %x\n", (int) offset);
297
+ r = 0;
298
+ break;
299
+ }
300
+ trace_cmsdk_apb_uart_read(offset, r, size);
301
+ return r;
302
+}
303
+
304
+/* Try to send tx data, and arrange to be called back later if
305
+ * we can't (ie the char backend is busy/blocking).
306
+ */
307
+static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
308
+{
309
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
310
+ int ret;
311
+
312
+ s->watch_tag = 0;
313
+
314
+ if (!(s->ctrl & R_CTRL_TX_EN_MASK) || !(s->state & R_STATE_TXFULL_MASK)) {
315
+ return FALSE;
316
+ }
317
+
318
+ ret = qemu_chr_fe_write(&s->chr, &s->txbuf, 1);
319
+ if (ret <= 0) {
320
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
321
+ uart_transmit, s);
322
+ if (!s->watch_tag) {
323
+ /* Most common reason to be here is "no chardev backend":
324
+ * just insta-drain the buffer, so the serial output
325
+ * goes into a void, rather than blocking the guest.
326
+ */
327
+ goto buffer_drained;
328
+ }
329
+ /* Transmit pending */
330
+ trace_cmsdk_apb_uart_tx_pending();
331
+ return FALSE;
332
+ }
333
+
334
+buffer_drained:
335
+ /* Character successfully sent */
336
+ trace_cmsdk_apb_uart_tx(s->txbuf);
337
+ s->state &= ~R_STATE_TXFULL_MASK;
338
+ /* Going from TXFULL set to clear triggers the tx interrupt */
339
+ if (s->ctrl & R_CTRL_TX_INTEN_MASK) {
340
+ s->intstatus |= R_INTSTATUS_TX_MASK;
341
+ }
342
+ cmsdk_apb_uart_update(s);
343
+ return FALSE;
344
+}
345
+
346
+static void uart_cancel_transmit(CMSDKAPBUART *s)
347
+{
348
+ if (s->watch_tag) {
349
+ g_source_remove(s->watch_tag);
350
+ s->watch_tag = 0;
351
+ }
352
+}
353
+
354
+static void uart_write(void *opaque, hwaddr offset, uint64_t value,
355
+ unsigned size)
356
+{
357
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
358
+
359
+ trace_cmsdk_apb_uart_write(offset, value, size);
360
+
361
+ switch (offset) {
362
+ case A_DATA:
363
+ s->txbuf = value;
364
+ if (s->state & R_STATE_TXFULL_MASK) {
365
+ /* Buffer already full -- note the overrun and let the
366
+ * existing pending transmit callback handle the new char.
367
+ */
368
+ s->state |= R_STATE_TXOVERRUN_MASK;
369
+ cmsdk_apb_uart_update(s);
370
+ } else {
371
+ s->state |= R_STATE_TXFULL_MASK;
372
+ uart_transmit(NULL, G_IO_OUT, s);
373
+ }
374
+ break;
375
+ case A_STATE:
376
+ /* Bits 0 and 1 are read only; bits 2 and 3 are W1C */
377
+ s->state &= ~(value &
378
+ (R_STATE_TXOVERRUN_MASK | R_STATE_RXOVERRUN_MASK));
379
+ cmsdk_apb_uart_update(s);
380
+ break;
381
+ case A_CTRL:
382
+ s->ctrl = value & 0x7f;
383
+ if ((s->ctrl & R_CTRL_TX_EN_MASK) && !uart_baudrate_ok(s)) {
384
+ qemu_log_mask(LOG_GUEST_ERROR,
385
+ "CMSDK APB UART: Tx enabled with invalid baudrate\n");
386
+ }
387
+ cmsdk_apb_uart_update(s);
388
+ break;
389
+ case A_INTSTATUS:
390
+ /* All bits are W1C. Clearing the overrun interrupt bits really
391
+ * clears the overrun status bits in the STATE register (which
392
+ * is then reflected into the intstatus value by the update function).
393
+ */
394
+ s->state &= ~(value & (R_INTSTATUS_TXO_MASK | R_INTSTATUS_RXO_MASK));
395
+ cmsdk_apb_uart_update(s);
396
+ break;
397
+ case A_BAUDDIV:
398
+ s->bauddiv = value & 0xFFFFF;
399
+ uart_update_parameters(s);
400
+ break;
401
+ case A_PID4 ... A_CID3:
402
+ qemu_log_mask(LOG_GUEST_ERROR,
403
+ "CMSDK APB UART write: write to RO offset 0x%x\n",
404
+ (int)offset);
405
+ break;
406
+ default:
407
+ qemu_log_mask(LOG_GUEST_ERROR,
408
+ "CMSDK APB UART write: bad offset 0x%x\n", (int) offset);
409
+ break;
410
+ }
411
+}
412
+
413
+static const MemoryRegionOps uart_ops = {
414
+ .read = uart_read,
415
+ .write = uart_write,
416
+ .endianness = DEVICE_LITTLE_ENDIAN,
417
+};
418
+
419
+static void cmsdk_apb_uart_reset(DeviceState *dev)
420
+{
421
+ CMSDKAPBUART *s = CMSDK_APB_UART(dev);
422
+
423
+ trace_cmsdk_apb_uart_reset();
424
+ uart_cancel_transmit(s);
425
+ s->state = 0;
426
+ s->ctrl = 0;
427
+ s->intstatus = 0;
428
+ s->bauddiv = 0;
429
+ s->txbuf = 0;
430
+ s->rxbuf = 0;
431
+}
432
+
433
+static void cmsdk_apb_uart_init(Object *obj)
434
+{
435
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
436
+ CMSDKAPBUART *s = CMSDK_APB_UART(obj);
437
+
438
+ memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000);
439
+ sysbus_init_mmio(sbd, &s->iomem);
440
+ sysbus_init_irq(sbd, &s->txint);
441
+ sysbus_init_irq(sbd, &s->rxint);
442
+ sysbus_init_irq(sbd, &s->txovrint);
443
+ sysbus_init_irq(sbd, &s->rxovrint);
444
+ sysbus_init_irq(sbd, &s->uartint);
445
+}
446
+
447
+static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp)
448
+{
449
+ CMSDKAPBUART *s = CMSDK_APB_UART(dev);
450
+
451
+ if (s->pclk_frq == 0) {
452
+ error_setg(errp, "CMSDK APB UART: pclk-frq property must be set");
453
+ return;
454
+ }
455
+
456
+ /* This UART has no flow control, so we do not need to register
457
+ * an event handler to deal with CHR_EVENT_BREAK.
458
+ */
459
+ qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
460
+ NULL, s, NULL, true);
461
+}
462
+
463
+static int cmsdk_apb_uart_post_load(void *opaque, int version_id)
464
+{
465
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
466
+
467
+ /* If we have a pending character, arrange to resend it. */
468
+ if (s->state & R_STATE_TXFULL_MASK) {
469
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
470
+ uart_transmit, s);
471
+ }
472
+ uart_update_parameters(s);
473
+ return 0;
474
+}
475
+
476
+static const VMStateDescription cmsdk_apb_uart_vmstate = {
477
+ .name = "cmsdk-apb-uart",
478
+ .version_id = 1,
479
+ .minimum_version_id = 1,
480
+ .post_load = cmsdk_apb_uart_post_load,
481
+ .fields = (VMStateField[]) {
482
+ VMSTATE_UINT32(state, CMSDKAPBUART),
483
+ VMSTATE_UINT32(ctrl, CMSDKAPBUART),
484
+ VMSTATE_UINT32(intstatus, CMSDKAPBUART),
485
+ VMSTATE_UINT32(bauddiv, CMSDKAPBUART),
486
+ VMSTATE_UINT8(txbuf, CMSDKAPBUART),
487
+ VMSTATE_UINT8(rxbuf, CMSDKAPBUART),
488
+ VMSTATE_END_OF_LIST()
489
+ }
490
+};
491
+
492
+static Property cmsdk_apb_uart_properties[] = {
493
+ DEFINE_PROP_CHR("chardev", CMSDKAPBUART, chr),
494
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBUART, pclk_frq, 0),
495
+ DEFINE_PROP_END_OF_LIST(),
496
+};
497
+
498
+static void cmsdk_apb_uart_class_init(ObjectClass *klass, void *data)
499
+{
500
+ DeviceClass *dc = DEVICE_CLASS(klass);
501
+
502
+ dc->realize = cmsdk_apb_uart_realize;
503
+ dc->vmsd = &cmsdk_apb_uart_vmstate;
504
+ dc->reset = cmsdk_apb_uart_reset;
505
+ dc->props = cmsdk_apb_uart_properties;
506
+}
507
+
508
+static const TypeInfo cmsdk_apb_uart_info = {
509
+ .name = TYPE_CMSDK_APB_UART,
510
+ .parent = TYPE_SYS_BUS_DEVICE,
511
+ .instance_size = sizeof(CMSDKAPBUART),
512
+ .instance_init = cmsdk_apb_uart_init,
513
+ .class_init = cmsdk_apb_uart_class_init,
514
+};
515
+
516
+static void cmsdk_apb_uart_register_types(void)
517
+{
518
+ type_register_static(&cmsdk_apb_uart_info);
519
+}
520
+
521
+type_init(cmsdk_apb_uart_register_types);
522
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
523
index XXXXXXX..XXXXXXX 100644
524
--- a/default-configs/arm-softmmu.mak
525
+++ b/default-configs/arm-softmmu.mak
526
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_ADC=y
527
CONFIG_STM32F2XX_SPI=y
528
CONFIG_STM32F205_SOC=y
529
530
+CONFIG_CMSDK_APB_UART=y
531
+
532
CONFIG_VERSATILE_PCI=y
533
CONFIG_VERSATILE_I2C=y
534
535
diff --git a/hw/char/trace-events b/hw/char/trace-events
536
index XXXXXXX..XXXXXXX 100644
537
--- a/hw/char/trace-events
538
+++ b/hw/char/trace-events
539
@@ -XXX,XX +XXX,XX @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
540
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR %08x read_count %d returning %d"
541
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
542
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
543
+
544
+# hw/char/cmsdk_apb_uart.c
545
+cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
546
+cmsdk_apb_uart_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
547
+cmsdk_apb_uart_reset(void) "CMSDK APB UART: reset"
548
+cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backend"
549
+cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
550
+cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
551
+cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
552
--
553
2.7.4
554
555
diff view generated by jsdifflib
Deleted patch
1
Add the UARTs to the MPS2 board models.
2
1
3
Unfortunately the details of the wiring of the interrupts through
4
various OR gates differ between AN511 and AN385 so this can't
5
be purely a data-driven difference.
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
9
Message-id: 1500029487-14822-4-git-send-email-peter.maydell@linaro.org
10
---
11
hw/arm/mps2.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
12
hw/char/cmsdk-apb-uart.c | 2 +-
13
2 files changed, 89 insertions(+), 1 deletion(-)
14
15
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2.c
18
+++ b/hw/arm/mps2.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "qemu/error-report.h"
21
#include "hw/arm/arm.h"
22
#include "hw/arm/armv7m.h"
23
+#include "hw/or-irq.h"
24
#include "hw/boards.h"
25
#include "exec/address-spaces.h"
26
+#include "sysemu/sysemu.h"
27
#include "hw/misc/unimp.h"
28
+#include "hw/char/cmsdk-apb-uart.h"
29
30
typedef enum MPS2FPGAType {
31
FPGA_AN385,
32
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
33
create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
34
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
35
36
+ switch (mmc->fpga_type) {
37
+ case FPGA_AN385:
38
+ {
39
+ /* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
40
+ * Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
41
+ */
42
+ Object *orgate;
43
+ DeviceState *orgate_dev;
44
+ int i;
45
+
46
+ orgate = object_new(TYPE_OR_IRQ);
47
+ object_property_set_int(orgate, 6, "num-lines", &error_fatal);
48
+ object_property_set_bool(orgate, true, "realized", &error_fatal);
49
+ orgate_dev = DEVICE(orgate);
50
+ qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12));
51
+
52
+ for (i = 0; i < 5; i++) {
53
+ static const hwaddr uartbase[] = {0x40004000, 0x40005000,
54
+ 0x40006000, 0x40007000,
55
+ 0x40009000};
56
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
57
+ /* RX irq number; TX irq is always one greater */
58
+ static const int uartirq[] = {0, 2, 4, 18, 20};
59
+ qemu_irq txovrint = NULL, rxovrint = NULL;
60
+
61
+ if (i < 3) {
62
+ txovrint = qdev_get_gpio_in(orgate_dev, i * 2);
63
+ rxovrint = qdev_get_gpio_in(orgate_dev, i * 2 + 1);
64
+ }
65
+
66
+ cmsdk_apb_uart_create(uartbase[i],
67
+ qdev_get_gpio_in(armv7m, uartirq[i] + 1),
68
+ qdev_get_gpio_in(armv7m, uartirq[i]),
69
+ txovrint, rxovrint,
70
+ NULL,
71
+ uartchr, SYSCLK_FRQ);
72
+ }
73
+ break;
74
+ }
75
+ case FPGA_AN511:
76
+ {
77
+ /* The overflow IRQs for all UARTs are ORed together.
78
+ * Tx and Rx IRQs for each UART are ORed together.
79
+ */
80
+ Object *orgate;
81
+ DeviceState *orgate_dev;
82
+ int i;
83
+
84
+ orgate = object_new(TYPE_OR_IRQ);
85
+ object_property_set_int(orgate, 10, "num-lines", &error_fatal);
86
+ object_property_set_bool(orgate, true, "realized", &error_fatal);
87
+ orgate_dev = DEVICE(orgate);
88
+ qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12));
89
+
90
+ for (i = 0; i < 5; i++) {
91
+ /* system irq numbers for the combined tx/rx for each UART */
92
+ static const int uart_txrx_irqno[] = {0, 2, 45, 46, 56};
93
+ static const hwaddr uartbase[] = {0x40004000, 0x40005000,
94
+ 0x4002c000, 0x4002d000,
95
+ 0x4002e000};
96
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
97
+ Object *txrx_orgate;
98
+ DeviceState *txrx_orgate_dev;
99
+
100
+ txrx_orgate = object_new(TYPE_OR_IRQ);
101
+ object_property_set_int(txrx_orgate, 2, "num-lines", &error_fatal);
102
+ object_property_set_bool(txrx_orgate, true, "realized",
103
+ &error_fatal);
104
+ txrx_orgate_dev = DEVICE(txrx_orgate);
105
+ qdev_connect_gpio_out(txrx_orgate_dev, 0,
106
+ qdev_get_gpio_in(armv7m, uart_txrx_irqno[i]));
107
+ cmsdk_apb_uart_create(uartbase[i],
108
+ qdev_get_gpio_in(txrx_orgate_dev, 0),
109
+ qdev_get_gpio_in(txrx_orgate_dev, 1),
110
+ qdev_get_gpio_in(orgate_dev, 0),
111
+ qdev_get_gpio_in(orgate_dev, 1),
112
+ NULL,
113
+ uartchr, SYSCLK_FRQ);
114
+ }
115
+ break;
116
+ }
117
+ default:
118
+ g_assert_not_reached();
119
+ }
120
+
121
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
122
123
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
124
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/char/cmsdk-apb-uart.c
127
+++ b/hw/char/cmsdk-apb-uart.c
128
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp)
129
* an event handler to deal with CHR_EVENT_BREAK.
130
*/
131
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
132
- NULL, s, NULL, true);
133
+ NULL, NULL, s, NULL, true);
134
}
135
136
static int cmsdk_apb_uart_post_load(void *opaque, int version_id)
137
--
138
2.7.4
139
140
diff view generated by jsdifflib
Deleted patch
1
Implement a model of the simple timer device found in the CMSDK.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 1500029487-14822-5-git-send-email-peter.maydell@linaro.org
6
---
7
hw/timer/Makefile.objs | 1 +
8
include/hw/timer/cmsdk-apb-timer.h | 59 +++++++++
9
hw/timer/cmsdk-apb-timer.c | 253 +++++++++++++++++++++++++++++++++++++
10
default-configs/arm-softmmu.mak | 1 +
11
hw/timer/trace-events | 5 +
12
5 files changed, 319 insertions(+)
13
create mode 100644 include/hw/timer/cmsdk-apb-timer.h
14
create mode 100644 hw/timer/cmsdk-apb-timer.c
15
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
19
+++ b/hw/timer/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
21
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
22
23
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
24
+common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
25
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
26
new file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- /dev/null
29
+++ b/include/hw/timer/cmsdk-apb-timer.h
30
@@ -XXX,XX +XXX,XX @@
31
+/*
32
+ * ARM CMSDK APB timer emulation
33
+ *
34
+ * Copyright (c) 2017 Linaro Limited
35
+ * Written by Peter Maydell
36
+ *
37
+ * This program is free software; you can redistribute it and/or modify
38
+ * it under the terms of the GNU General Public License version 2 or
39
+ * (at your option) any later version.
40
+ */
41
+
42
+#ifndef CMSDK_APB_TIMER_H
43
+#define CMSDK_APB_TIMER_H
44
+
45
+#include "hw/sysbus.h"
46
+#include "hw/ptimer.h"
47
+
48
+#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
49
+#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \
50
+ TYPE_CMSDK_APB_TIMER)
51
+
52
+typedef struct {
53
+ /*< private >*/
54
+ SysBusDevice parent_obj;
55
+
56
+ /*< public >*/
57
+ MemoryRegion iomem;
58
+ qemu_irq timerint;
59
+ uint32_t pclk_frq;
60
+ struct ptimer_state *timer;
61
+
62
+ uint32_t ctrl;
63
+ uint32_t value;
64
+ uint32_t reload;
65
+ uint32_t intstatus;
66
+} CMSDKAPBTIMER;
67
+
68
+/**
69
+ * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
70
+ * @addr: location in system memory to map registers
71
+ * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
72
+ */
73
+static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
74
+ qemu_irq timerint,
75
+ uint32_t pclk_frq)
76
+{
77
+ DeviceState *dev;
78
+ SysBusDevice *s;
79
+
80
+ dev = qdev_create(NULL, TYPE_CMSDK_APB_TIMER);
81
+ s = SYS_BUS_DEVICE(dev);
82
+ qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
83
+ qdev_init_nofail(dev);
84
+ sysbus_mmio_map(s, 0, addr);
85
+ sysbus_connect_irq(s, 0, timerint);
86
+ return dev;
87
+}
88
+
89
+#endif
90
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/hw/timer/cmsdk-apb-timer.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * ARM CMSDK APB timer emulation
98
+ *
99
+ * Copyright (c) 2017 Linaro Limited
100
+ * Written by Peter Maydell
101
+ *
102
+ * This program is free software; you can redistribute it and/or modify
103
+ * it under the terms of the GNU General Public License version 2 or
104
+ * (at your option) any later version.
105
+ */
106
+
107
+/* This is a model of the "APB timer" which is part of the Cortex-M
108
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
109
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
110
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
111
+ *
112
+ * The hardware has an EXTIN input wire, which can be configured
113
+ * by the guest to act either as a 'timer enable' (timer does not run
114
+ * when EXTIN is low), or as a 'timer clock' (timer runs at frequency
115
+ * of EXTIN clock, not PCLK frequency). We don't model this.
116
+ *
117
+ * The documentation is not very clear about the exact behaviour;
118
+ * we choose to implement that the interrupt is triggered when
119
+ * the counter goes from 1 to 0, that the counter then holds at 0
120
+ * for one clock cycle before reloading from the RELOAD register,
121
+ * and that if the RELOAD register is 0 this does not cause an
122
+ * interrupt (as there is no further 1->0 transition).
123
+ */
124
+
125
+#include "qemu/osdep.h"
126
+#include "qemu/log.h"
127
+#include "qemu/main-loop.h"
128
+#include "qapi/error.h"
129
+#include "trace.h"
130
+#include "hw/sysbus.h"
131
+#include "hw/registerfields.h"
132
+#include "hw/timer/cmsdk-apb-timer.h"
133
+
134
+REG32(CTRL, 0)
135
+ FIELD(CTRL, EN, 0, 1)
136
+ FIELD(CTRL, SELEXTEN, 1, 1)
137
+ FIELD(CTRL, SELEXTCLK, 2, 1)
138
+ FIELD(CTRL, IRQEN, 3, 1)
139
+REG32(VALUE, 4)
140
+REG32(RELOAD, 8)
141
+REG32(INTSTATUS, 0xc)
142
+ FIELD(INTSTATUS, IRQ, 0, 1)
143
+REG32(PID4, 0xFD0)
144
+REG32(PID5, 0xFD4)
145
+REG32(PID6, 0xFD8)
146
+REG32(PID7, 0xFDC)
147
+REG32(PID0, 0xFE0)
148
+REG32(PID1, 0xFE4)
149
+REG32(PID2, 0xFE8)
150
+REG32(PID3, 0xFEC)
151
+REG32(CID0, 0xFF0)
152
+REG32(CID1, 0xFF4)
153
+REG32(CID2, 0xFF8)
154
+REG32(CID3, 0xFFC)
155
+
156
+/* PID/CID values */
157
+static const int timer_id[] = {
158
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
159
+ 0x22, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
160
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
161
+};
162
+
163
+static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
164
+{
165
+ qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
166
+}
167
+
168
+static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
169
+{
170
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
171
+ uint64_t r;
172
+
173
+ switch (offset) {
174
+ case A_CTRL:
175
+ r = s->ctrl;
176
+ break;
177
+ case A_VALUE:
178
+ r = ptimer_get_count(s->timer);
179
+ break;
180
+ case A_RELOAD:
181
+ r = ptimer_get_limit(s->timer);
182
+ break;
183
+ case A_INTSTATUS:
184
+ r = s->intstatus;
185
+ break;
186
+ case A_PID4 ... A_CID3:
187
+ r = timer_id[(offset - A_PID4) / 4];
188
+ break;
189
+ default:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "CMSDK APB timer read: bad offset %x\n", (int) offset);
192
+ r = 0;
193
+ break;
194
+ }
195
+ trace_cmsdk_apb_timer_read(offset, r, size);
196
+ return r;
197
+}
198
+
199
+static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
200
+ unsigned size)
201
+{
202
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
203
+
204
+ trace_cmsdk_apb_timer_write(offset, value, size);
205
+
206
+ switch (offset) {
207
+ case A_CTRL:
208
+ if (value & 6) {
209
+ /* Bits [1] and [2] enable using EXTIN as either clock or
210
+ * an enable line. We don't model this.
211
+ */
212
+ qemu_log_mask(LOG_UNIMP,
213
+ "CMSDK APB timer: EXTIN input not supported\n");
214
+ }
215
+ s->ctrl = value & 0xf;
216
+ if (s->ctrl & R_CTRL_EN_MASK) {
217
+ ptimer_run(s->timer, 0);
218
+ } else {
219
+ ptimer_stop(s->timer);
220
+ }
221
+ break;
222
+ case A_RELOAD:
223
+ /* Writing to reload also sets the current timer value */
224
+ ptimer_set_limit(s->timer, value, 1);
225
+ break;
226
+ case A_VALUE:
227
+ ptimer_set_count(s->timer, value);
228
+ break;
229
+ case A_INTSTATUS:
230
+ /* Just one bit, which is W1C. */
231
+ value &= 1;
232
+ s->intstatus &= ~value;
233
+ cmsdk_apb_timer_update(s);
234
+ break;
235
+ case A_PID4 ... A_CID3:
236
+ qemu_log_mask(LOG_GUEST_ERROR,
237
+ "CMSDK APB timer write: write to RO offset 0x%x\n",
238
+ (int)offset);
239
+ break;
240
+ default:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "CMSDK APB timer write: bad offset 0x%x\n", (int) offset);
243
+ break;
244
+ }
245
+}
246
+
247
+static const MemoryRegionOps cmsdk_apb_timer_ops = {
248
+ .read = cmsdk_apb_timer_read,
249
+ .write = cmsdk_apb_timer_write,
250
+ .endianness = DEVICE_LITTLE_ENDIAN,
251
+};
252
+
253
+static void cmsdk_apb_timer_tick(void *opaque)
254
+{
255
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
256
+
257
+ if (s->ctrl & R_CTRL_IRQEN_MASK) {
258
+ s->intstatus |= R_INTSTATUS_IRQ_MASK;
259
+ cmsdk_apb_timer_update(s);
260
+ }
261
+}
262
+
263
+static void cmsdk_apb_timer_reset(DeviceState *dev)
264
+{
265
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
266
+
267
+ trace_cmsdk_apb_timer_reset();
268
+ s->ctrl = 0;
269
+ s->intstatus = 0;
270
+ ptimer_stop(s->timer);
271
+ /* Set the limit and the count */
272
+ ptimer_set_limit(s->timer, 0, 1);
273
+}
274
+
275
+static void cmsdk_apb_timer_init(Object *obj)
276
+{
277
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
278
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
279
+
280
+ memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
281
+ s, "cmsdk-apb-timer", 0x1000);
282
+ sysbus_init_mmio(sbd, &s->iomem);
283
+ sysbus_init_irq(sbd, &s->timerint);
284
+}
285
+
286
+static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
287
+{
288
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
289
+ QEMUBH *bh;
290
+
291
+ if (s->pclk_frq == 0) {
292
+ error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
293
+ return;
294
+ }
295
+
296
+ bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
297
+ s->timer = ptimer_init(bh,
298
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
299
+ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
300
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
301
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
302
+
303
+ ptimer_set_freq(s->timer, s->pclk_frq);
304
+}
305
+
306
+static const VMStateDescription cmsdk_apb_timer_vmstate = {
307
+ .name = "cmsdk-apb-timer",
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
312
+ VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
313
+ VMSTATE_UINT32(value, CMSDKAPBTIMER),
314
+ VMSTATE_UINT32(reload, CMSDKAPBTIMER),
315
+ VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
316
+ VMSTATE_END_OF_LIST()
317
+ }
318
+};
319
+
320
+static Property cmsdk_apb_timer_properties[] = {
321
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
322
+ DEFINE_PROP_END_OF_LIST(),
323
+};
324
+
325
+static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
326
+{
327
+ DeviceClass *dc = DEVICE_CLASS(klass);
328
+
329
+ dc->realize = cmsdk_apb_timer_realize;
330
+ dc->vmsd = &cmsdk_apb_timer_vmstate;
331
+ dc->reset = cmsdk_apb_timer_reset;
332
+ dc->props = cmsdk_apb_timer_properties;
333
+}
334
+
335
+static const TypeInfo cmsdk_apb_timer_info = {
336
+ .name = TYPE_CMSDK_APB_TIMER,
337
+ .parent = TYPE_SYS_BUS_DEVICE,
338
+ .instance_size = sizeof(CMSDKAPBTIMER),
339
+ .instance_init = cmsdk_apb_timer_init,
340
+ .class_init = cmsdk_apb_timer_class_init,
341
+};
342
+
343
+static void cmsdk_apb_timer_register_types(void)
344
+{
345
+ type_register_static(&cmsdk_apb_timer_info);
346
+}
347
+
348
+type_init(cmsdk_apb_timer_register_types);
349
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
350
index XXXXXXX..XXXXXXX 100644
351
--- a/default-configs/arm-softmmu.mak
352
+++ b/default-configs/arm-softmmu.mak
353
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_ADC=y
354
CONFIG_STM32F2XX_SPI=y
355
CONFIG_STM32F205_SOC=y
356
357
+CONFIG_CMSDK_APB_TIMER=y
358
CONFIG_CMSDK_APB_UART=y
359
360
CONFIG_VERSATILE_PCI=y
361
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
362
index XXXXXXX..XXXXXXX 100644
363
--- a/hw/timer/trace-events
364
+++ b/hw/timer/trace-events
365
@@ -XXX,XX +XXX,XX @@ systick_reload(void) "systick reload"
366
systick_timer_tick(void) "systick reload"
367
systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
368
systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
369
+
370
+# hw/char/cmsdk_apb_timer.c
371
+cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
372
+cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
373
+cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
374
--
375
2.7.4
376
377
diff view generated by jsdifflib
Deleted patch
1
Add the CMSDK APB timers to the MPS2 board.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 1500029487-14822-6-git-send-email-peter.maydell@linaro.org
6
---
7
hw/arm/mps2.c | 4 ++++
8
1 file changed, 4 insertions(+)
9
10
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/mps2.c
13
+++ b/hw/arm/mps2.c
14
@@ -XXX,XX +XXX,XX @@
15
#include "sysemu/sysemu.h"
16
#include "hw/misc/unimp.h"
17
#include "hw/char/cmsdk-apb-uart.h"
18
+#include "hw/timer/cmsdk-apb-timer.h"
19
20
typedef enum MPS2FPGAType {
21
FPGA_AN385,
22
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
23
g_assert_not_reached();
24
}
25
26
+ cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
27
+ cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
28
+
29
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
30
31
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
32
--
33
2.7.4
34
35
diff view generated by jsdifflib
Deleted patch
1
Implement a model of the Serial Communication Controller (SCC) found
2
in MPS2 FPGA images.
3
1
4
The primary purpose of this device is to communicate with the
5
Motherboard Configuration Controller (MCC) which is located on
6
the MPS board itself, outside the FPGA image. This is used
7
for programming the MPS clock generators. The SCC also has
8
some basic ID registers and an output for the board LEDs.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 1500029487-14822-7-git-send-email-peter.maydell@linaro.org
13
---
14
hw/misc/Makefile.objs | 1 +
15
include/hw/misc/mps2-scc.h | 43 ++++++
16
hw/misc/mps2-scc.c | 310 ++++++++++++++++++++++++++++++++++++++++
17
default-configs/arm-softmmu.mak | 2 +
18
hw/misc/trace-events | 8 ++
19
5 files changed, 364 insertions(+)
20
create mode 100644 include/hw/misc/mps2-scc.h
21
create mode 100644 hw/misc/mps2-scc.c
22
23
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/Makefile.objs
26
+++ b/hw/misc/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
28
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
29
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
30
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
31
+obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
32
33
obj-$(CONFIG_PVPANIC) += pvpanic.o
34
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
35
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/misc/mps2-scc.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * ARM MPS2 SCC emulation
43
+ *
44
+ * Copyright (c) 2017 Linaro Limited
45
+ * Written by Peter Maydell
46
+ *
47
+ * This program is free software; you can redistribute it and/or modify
48
+ * it under the terms of the GNU General Public License version 2 or
49
+ * (at your option) any later version.
50
+ */
51
+
52
+#ifndef MPS2_SCC_H
53
+#define MPS2_SCC_H
54
+
55
+#include "hw/sysbus.h"
56
+
57
+#define TYPE_MPS2_SCC "mps2-scc"
58
+#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC)
59
+
60
+#define NUM_OSCCLK 3
61
+
62
+typedef struct {
63
+ /*< private >*/
64
+ SysBusDevice parent_obj;
65
+
66
+ /*< public >*/
67
+ MemoryRegion iomem;
68
+
69
+ uint32_t cfg0;
70
+ uint32_t cfg1;
71
+ uint32_t cfg4;
72
+ uint32_t cfgdata_rtn;
73
+ uint32_t cfgdata_out;
74
+ uint32_t cfgctrl;
75
+ uint32_t cfgstat;
76
+ uint32_t dll;
77
+ uint32_t aid;
78
+ uint32_t id;
79
+ uint32_t oscclk[NUM_OSCCLK];
80
+ uint32_t oscclk_reset[NUM_OSCCLK];
81
+} MPS2SCC;
82
+
83
+#endif
84
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
85
new file mode 100644
86
index XXXXXXX..XXXXXXX
87
--- /dev/null
88
+++ b/hw/misc/mps2-scc.c
89
@@ -XXX,XX +XXX,XX @@
90
+/*
91
+ * ARM MPS2 SCC emulation
92
+ *
93
+ * Copyright (c) 2017 Linaro Limited
94
+ * Written by Peter Maydell
95
+ *
96
+ * This program is free software; you can redistribute it and/or modify
97
+ * it under the terms of the GNU General Public License version 2 or
98
+ * (at your option) any later version.
99
+ */
100
+
101
+/* This is a model of the SCC (Serial Communication Controller)
102
+ * found in the FPGA images of MPS2 development boards.
103
+ *
104
+ * Documentation of it can be found in the MPS2 TRM:
105
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
106
+ * and also in the Application Notes documenting individual FPGA images.
107
+ */
108
+
109
+#include "qemu/osdep.h"
110
+#include "qemu/log.h"
111
+#include "qapi/error.h"
112
+#include "trace.h"
113
+#include "hw/sysbus.h"
114
+#include "hw/registerfields.h"
115
+#include "hw/misc/mps2-scc.h"
116
+
117
+REG32(CFG0, 0)
118
+REG32(CFG1, 4)
119
+REG32(CFG3, 0xc)
120
+REG32(CFG4, 0x10)
121
+REG32(CFGDATA_RTN, 0xa0)
122
+REG32(CFGDATA_OUT, 0xa4)
123
+REG32(CFGCTRL, 0xa8)
124
+ FIELD(CFGCTRL, DEVICE, 0, 12)
125
+ FIELD(CFGCTRL, RES1, 12, 8)
126
+ FIELD(CFGCTRL, FUNCTION, 20, 6)
127
+ FIELD(CFGCTRL, RES2, 26, 4)
128
+ FIELD(CFGCTRL, WRITE, 30, 1)
129
+ FIELD(CFGCTRL, START, 31, 1)
130
+REG32(CFGSTAT, 0xac)
131
+ FIELD(CFGSTAT, DONE, 0, 1)
132
+ FIELD(CFGSTAT, ERROR, 1, 1)
133
+REG32(DLL, 0x100)
134
+REG32(AID, 0xFF8)
135
+REG32(ID, 0xFFC)
136
+
137
+/* Handle a write via the SYS_CFG channel to the specified function/device.
138
+ * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
139
+ */
140
+static bool scc_cfg_write(MPS2SCC *s, unsigned function,
141
+ unsigned device, uint32_t value)
142
+{
143
+ trace_mps2_scc_cfg_write(function, device, value);
144
+
145
+ if (function != 1 || device >= NUM_OSCCLK) {
146
+ qemu_log_mask(LOG_GUEST_ERROR,
147
+ "MPS2 SCC config write: bad function %d device %d\n",
148
+ function, device);
149
+ return false;
150
+ }
151
+
152
+ s->oscclk[device] = value;
153
+ return true;
154
+}
155
+
156
+/* Handle a read via the SYS_CFG channel to the specified function/device.
157
+ * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit),
158
+ * or set *value on success.
159
+ */
160
+static bool scc_cfg_read(MPS2SCC *s, unsigned function,
161
+ unsigned device, uint32_t *value)
162
+{
163
+ if (function != 1 || device >= NUM_OSCCLK) {
164
+ qemu_log_mask(LOG_GUEST_ERROR,
165
+ "MPS2 SCC config read: bad function %d device %d\n",
166
+ function, device);
167
+ return false;
168
+ }
169
+
170
+ *value = s->oscclk[device];
171
+
172
+ trace_mps2_scc_cfg_read(function, device, *value);
173
+ return true;
174
+}
175
+
176
+static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
177
+{
178
+ MPS2SCC *s = MPS2_SCC(opaque);
179
+ uint64_t r;
180
+
181
+ switch (offset) {
182
+ case A_CFG0:
183
+ r = s->cfg0;
184
+ break;
185
+ case A_CFG1:
186
+ r = s->cfg1;
187
+ break;
188
+ case A_CFG3:
189
+ /* These are user-settable DIP switches on the board. We don't
190
+ * model that, so just return zeroes.
191
+ */
192
+ r = 0;
193
+ break;
194
+ case A_CFG4:
195
+ r = s->cfg4;
196
+ break;
197
+ case A_CFGDATA_RTN:
198
+ r = s->cfgdata_rtn;
199
+ break;
200
+ case A_CFGDATA_OUT:
201
+ r = s->cfgdata_out;
202
+ break;
203
+ case A_CFGCTRL:
204
+ r = s->cfgctrl;
205
+ break;
206
+ case A_CFGSTAT:
207
+ r = s->cfgstat;
208
+ break;
209
+ case A_DLL:
210
+ r = s->dll;
211
+ break;
212
+ case A_AID:
213
+ r = s->aid;
214
+ break;
215
+ case A_ID:
216
+ r = s->id;
217
+ break;
218
+ default:
219
+ qemu_log_mask(LOG_GUEST_ERROR,
220
+ "MPS2 SCC read: bad offset %x\n", (int) offset);
221
+ r = 0;
222
+ break;
223
+ }
224
+
225
+ trace_mps2_scc_read(offset, r, size);
226
+ return r;
227
+}
228
+
229
+static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
230
+ unsigned size)
231
+{
232
+ MPS2SCC *s = MPS2_SCC(opaque);
233
+
234
+ trace_mps2_scc_write(offset, value, size);
235
+
236
+ switch (offset) {
237
+ case A_CFG0:
238
+ /* TODO on some boards bit 0 controls RAM remapping */
239
+ s->cfg0 = value;
240
+ break;
241
+ case A_CFG1:
242
+ /* CFG1 bits [7:0] control the board LEDs. We don't currently have
243
+ * a mechanism for displaying this graphically, so use a trace event.
244
+ */
245
+ trace_mps2_scc_leds(value & 0x80 ? '*' : '.',
246
+ value & 0x40 ? '*' : '.',
247
+ value & 0x20 ? '*' : '.',
248
+ value & 0x10 ? '*' : '.',
249
+ value & 0x08 ? '*' : '.',
250
+ value & 0x04 ? '*' : '.',
251
+ value & 0x02 ? '*' : '.',
252
+ value & 0x01 ? '*' : '.');
253
+ s->cfg1 = value;
254
+ break;
255
+ case A_CFGDATA_OUT:
256
+ s->cfgdata_out = value;
257
+ break;
258
+ case A_CFGCTRL:
259
+ /* Writing to CFGCTRL clears SYS_CFGSTAT */
260
+ s->cfgstat = 0;
261
+ s->cfgctrl = value & ~(R_CFGCTRL_RES1_MASK |
262
+ R_CFGCTRL_RES2_MASK |
263
+ R_CFGCTRL_START_MASK);
264
+
265
+ if (value & R_CFGCTRL_START_MASK) {
266
+ /* Start bit set -- do a read or write (instantaneously) */
267
+ int device = extract32(s->cfgctrl, R_CFGCTRL_DEVICE_SHIFT,
268
+ R_CFGCTRL_DEVICE_LENGTH);
269
+ int function = extract32(s->cfgctrl, R_CFGCTRL_FUNCTION_SHIFT,
270
+ R_CFGCTRL_FUNCTION_LENGTH);
271
+
272
+ s->cfgstat = R_CFGSTAT_DONE_MASK;
273
+ if (s->cfgctrl & R_CFGCTRL_WRITE_MASK) {
274
+ if (!scc_cfg_write(s, function, device, s->cfgdata_out)) {
275
+ s->cfgstat |= R_CFGSTAT_ERROR_MASK;
276
+ }
277
+ } else {
278
+ uint32_t result;
279
+ if (!scc_cfg_read(s, function, device, &result)) {
280
+ s->cfgstat |= R_CFGSTAT_ERROR_MASK;
281
+ } else {
282
+ s->cfgdata_rtn = result;
283
+ }
284
+ }
285
+ }
286
+ break;
287
+ case A_DLL:
288
+ /* DLL stands for Digital Locked Loop.
289
+ * Bits [31:24] (DLL_LOCK_MASK) are writable, and indicate a
290
+ * mask of which of the DLL_LOCKED bits [16:23] should be ORed
291
+ * together to determine the ALL_UNMASKED_DLLS_LOCKED bit [0].
292
+ * For QEMU, our DLLs are always locked, so we can leave bit 0
293
+ * as 1 always and don't need to recalculate it.
294
+ */
295
+ s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
296
+ break;
297
+ default:
298
+ qemu_log_mask(LOG_GUEST_ERROR,
299
+ "MPS2 SCC write: bad offset 0x%x\n", (int) offset);
300
+ break;
301
+ }
302
+}
303
+
304
+static const MemoryRegionOps mps2_scc_ops = {
305
+ .read = mps2_scc_read,
306
+ .write = mps2_scc_write,
307
+ .endianness = DEVICE_LITTLE_ENDIAN,
308
+};
309
+
310
+static void mps2_scc_reset(DeviceState *dev)
311
+{
312
+ MPS2SCC *s = MPS2_SCC(dev);
313
+ int i;
314
+
315
+ trace_mps2_scc_reset();
316
+ s->cfg0 = 0;
317
+ s->cfg1 = 0;
318
+ s->cfgdata_rtn = 0;
319
+ s->cfgdata_out = 0;
320
+ s->cfgctrl = 0x100000;
321
+ s->cfgstat = 0;
322
+ s->dll = 0xffff0001;
323
+ for (i = 0; i < NUM_OSCCLK; i++) {
324
+ s->oscclk[i] = s->oscclk_reset[i];
325
+ }
326
+}
327
+
328
+static void mps2_scc_init(Object *obj)
329
+{
330
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
331
+ MPS2SCC *s = MPS2_SCC(obj);
332
+
333
+ memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000);
334
+ sysbus_init_mmio(sbd, &s->iomem);
335
+}
336
+
337
+static void mps2_scc_realize(DeviceState *dev, Error **errp)
338
+{
339
+}
340
+
341
+static const VMStateDescription mps2_scc_vmstate = {
342
+ .name = "mps2-scc",
343
+ .version_id = 1,
344
+ .minimum_version_id = 1,
345
+ .fields = (VMStateField[]) {
346
+ VMSTATE_UINT32(cfg0, MPS2SCC),
347
+ VMSTATE_UINT32(cfg1, MPS2SCC),
348
+ VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
349
+ VMSTATE_UINT32(cfgdata_out, MPS2SCC),
350
+ VMSTATE_UINT32(cfgctrl, MPS2SCC),
351
+ VMSTATE_UINT32(cfgstat, MPS2SCC),
352
+ VMSTATE_UINT32(dll, MPS2SCC),
353
+ VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
354
+ VMSTATE_END_OF_LIST()
355
+ }
356
+};
357
+
358
+static Property mps2_scc_properties[] = {
359
+ /* Values for various read-only ID registers (which are specific
360
+ * to the board model or FPGA image)
361
+ */
362
+ DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, aid, 0),
363
+ DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
364
+ DEFINE_PROP_UINT32("scc-id", MPS2SCC, aid, 0),
365
+ /* These are the initial settings for the source clocks on the board.
366
+ * In hardware they can be configured via a config file read by the
367
+ * motherboard configuration controller to suit the FPGA image.
368
+ * These default values are used by most of the standard FPGA images.
369
+ */
370
+ DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
371
+ DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
372
+ DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
373
+ DEFINE_PROP_END_OF_LIST(),
374
+};
375
+
376
+static void mps2_scc_class_init(ObjectClass *klass, void *data)
377
+{
378
+ DeviceClass *dc = DEVICE_CLASS(klass);
379
+
380
+ dc->realize = mps2_scc_realize;
381
+ dc->vmsd = &mps2_scc_vmstate;
382
+ dc->reset = mps2_scc_reset;
383
+ dc->props = mps2_scc_properties;
384
+}
385
+
386
+static const TypeInfo mps2_scc_info = {
387
+ .name = TYPE_MPS2_SCC,
388
+ .parent = TYPE_SYS_BUS_DEVICE,
389
+ .instance_size = sizeof(MPS2SCC),
390
+ .instance_init = mps2_scc_init,
391
+ .class_init = mps2_scc_class_init,
392
+};
393
+
394
+static void mps2_scc_register_types(void)
395
+{
396
+ type_register_static(&mps2_scc_info);
397
+}
398
+
399
+type_init(mps2_scc_register_types);
400
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
401
index XXXXXXX..XXXXXXX 100644
402
--- a/default-configs/arm-softmmu.mak
403
+++ b/default-configs/arm-softmmu.mak
404
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
405
CONFIG_CMSDK_APB_TIMER=y
406
CONFIG_CMSDK_APB_UART=y
407
408
+CONFIG_MPS2_SCC=y
409
+
410
CONFIG_VERSATILE_PCI=y
411
CONFIG_VERSATILE_I2C=y
412
413
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
414
index XXXXXXX..XXXXXXX 100644
415
--- a/hw/misc/trace-events
416
+++ b/hw/misc/trace-events
417
@@ -XXX,XX +XXX,XX @@ milkymist_pfpu_pulse_irq(void) "Pulse IRQ"
418
419
# hw/misc/aspeed_scu.c
420
aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
421
+
422
+# hw/misc/mps2_scc.c
423
+mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
424
+mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
425
+mps2_scc_reset(void) "MPS2 SCC: reset"
426
+mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2, char led1, char led0) "MPS2 SCC LEDs: %c%c%c%c%c%c%c%c"
427
+mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
428
+mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
429
--
430
2.7.4
431
432
diff view generated by jsdifflib
Deleted patch
1
Add the SCC to the MPS2 board models.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 1500029487-14822-8-git-send-email-peter.maydell@linaro.org
6
---
7
hw/arm/mps2.c | 17 ++++++++++++++++-
8
1 file changed, 16 insertions(+), 1 deletion(-)
9
10
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/mps2.c
13
+++ b/hw/arm/mps2.c
14
@@ -XXX,XX +XXX,XX @@
15
#include "hw/misc/unimp.h"
16
#include "hw/char/cmsdk-apb-uart.h"
17
#include "hw/timer/cmsdk-apb-timer.h"
18
+#include "hw/misc/mps2-scc.h"
19
20
typedef enum MPS2FPGAType {
21
FPGA_AN385,
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
MachineClass parent;
24
MPS2FPGAType fpga_type;
25
const char *cpu_model;
26
+ uint32_t scc_id;
27
} MPS2MachineClass;
28
29
typedef struct {
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
MemoryRegion blockram_m2;
32
MemoryRegion blockram_m3;
33
MemoryRegion sram;
34
+ MPS2SCC scc;
35
} MPS2MachineState;
36
37
#define TYPE_MPS2_MACHINE "mps2"
38
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
39
MPS2MachineState *mms = MPS2_MACHINE(machine);
40
MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine);
41
MemoryRegion *system_memory = get_system_memory();
42
- DeviceState *armv7m;
43
+ DeviceState *armv7m, *sccdev;
44
45
if (!machine->cpu_model) {
46
machine->cpu_model = mmc->cpu_model;
47
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
48
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
49
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
50
51
+ object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC);
52
+ sccdev = DEVICE(&mms->scc);
53
+ qdev_set_parent_bus(armv7m, sysbus_get_default());
54
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
55
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
56
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
57
+ object_property_set_bool(OBJECT(&mms->scc), true, "realized",
58
+ &error_fatal);
59
+ sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
60
+
61
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
62
63
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
64
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
65
mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
66
mmc->fpga_type = FPGA_AN385;
67
mmc->cpu_model = "cortex-m3";
68
+ mmc->scc_id = 0x41040000 | (385 << 4);
69
}
70
71
static void mps2_an511_class_init(ObjectClass *oc, void *data)
72
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
73
mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
74
mmc->fpga_type = FPGA_AN511;
75
mmc->cpu_model = "cortex-m3";
76
+ mmc->scc_id = 0x4104000 | (511 << 4);
77
}
78
79
static const TypeInfo mps2_info = {
80
--
81
2.7.4
82
83
diff view generated by jsdifflib
Deleted patch
1
The MPS2 FPGA images support ethernet via a LAN9220. We use
2
QEMU's LAN9118 model, which is software compatible except
3
that it is missing the checksum-offload feature.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 1500029487-14822-9-git-send-email-peter.maydell@linaro.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
---
10
hw/arm/mps2.c | 10 +++++++++-
11
1 file changed, 9 insertions(+), 1 deletion(-)
12
13
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2.c
16
+++ b/hw/arm/mps2.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/char/cmsdk-apb-uart.h"
19
#include "hw/timer/cmsdk-apb-timer.h"
20
#include "hw/misc/mps2-scc.h"
21
+#include "hw/devices.h"
22
+#include "net/net.h"
23
24
typedef enum MPS2FPGAType {
25
FPGA_AN385,
26
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
27
create_unimplemented_device("Extra peripheral region @0x40020000",
28
0x40020000, 0x00010000);
29
create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
30
- create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
31
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
32
33
switch (mmc->fpga_type) {
34
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
35
&error_fatal);
36
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
37
38
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
39
+ * except that it doesn't support the checksum-offload feature.
40
+ */
41
+ lan9118_init(&nd_table[0], 0x40200000,
42
+ qdev_get_gpio_in(armv7m,
43
+ mmc->fpga_type == FPGA_AN385 ? 13 : 47));
44
+
45
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
46
47
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
48
--
49
2.7.4
50
51
diff view generated by jsdifflib
Deleted patch
1
Add entries to the MAINTAINERS file for the new MPS2
2
board and devices.
3
1
4
Since the CMSDK devices are not specific to the MPS2 board,
5
extend the existing 'PrimeCell' section to cover CMSDK
6
devices as well; in both cases these are devices implemented
7
by ARM and provided as RTL that may be used in multiple
8
SoCs and boards.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 1500029487-14822-10-git-send-email-peter.maydell@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
---
15
MAINTAINERS | 14 +++++++++++++-
16
1 file changed, 13 insertions(+), 1 deletion(-)
17
18
diff --git a/MAINTAINERS b/MAINTAINERS
19
index XXXXXXX..XXXXXXX 100644
20
--- a/MAINTAINERS
21
+++ b/MAINTAINERS
22
@@ -XXX,XX +XXX,XX @@ F: hw/*/allwinner*
23
F: include/hw/*/allwinner*
24
F: hw/arm/cubieboard.c
25
26
-ARM PrimeCell
27
+ARM PrimeCell and CMSDK devices
28
M: Peter Maydell <peter.maydell@linaro.org>
29
L: qemu-arm@nongnu.org
30
S: Maintained
31
@@ -XXX,XX +XXX,XX @@ F: hw/intc/pl190.c
32
F: hw/sd/pl181.c
33
F: hw/timer/pl031.c
34
F: include/hw/arm/primecell.h
35
+F: hw/timer/cmsdk-apb-timer.c
36
+F: include/hw/timer/cmsdk-apb-timer.h
37
+F: hw/char/cmsdk-apb-uart.c
38
+F: include/hw/char/cmsdk-apb-uart.h
39
40
ARM cores
41
M: Peter Maydell <peter.maydell@linaro.org>
42
@@ -XXX,XX +XXX,XX @@ S: Maintained
43
F: hw/arm/integratorcp.c
44
F: hw/misc/arm_integrator_debug.c
45
46
+MPS2
47
+M: Peter Maydell <peter.maydell@linaro.org>
48
+L: qemu-arm@nongnu.org
49
+S: Maintained
50
+F: hw/arm/mps2.c
51
+F: hw/misc/mps2-scc.c
52
+F: include/hw/misc/mps2-scc.h
53
+
54
Musicpal
55
M: Jan Kiszka <jan.kiszka@web.de>
56
L: qemu-arm@nongnu.org
57
--
58
2.7.4
59
60
diff view generated by jsdifflib