1
target-arm queue: mostly just cleanup/minor stuff, but this does
1
target-arm queue: mostly smallish stuff. I expect to send
2
include the raspi3 board model.
2
out another pullreq at the end of this week, but since this
3
is up to 32 patches already I'd rather send it out now
4
than accumulate a monster sized patchset.
3
5
6
thanks
4
-- PMM
7
-- PMM
5
8
6
The following changes since commit 9f9c53368b219a9115eddb39f0ff5ad19c977134:
7
9
8
Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.12-pull-request' into staging (2018-02-15 10:14:11 +0000)
10
The following changes since commit 0ab4c574a55448a37b9f616259b82950742c9427:
11
12
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180626-pull-request' into staging (2018-06-26 16:44:57 +0100)
9
13
10
are available in the Git repository at:
14
are available in the Git repository at:
11
15
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180215
16
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180626
13
17
14
for you to fetch changes up to e545f0f9be1f9e60951017c1e6558216732cc14e:
18
for you to fetch changes up to 9b945a9ee36a34eaeca412ef9ef35fbfe33c2c85:
15
19
16
target/arm: Implement v8M MSPLIM and PSPLIM registers (2018-02-15 13:48:11 +0000)
20
aspeed/timer: use the APB frequency from the SCU (2018-06-26 17:50:42 +0100)
17
21
18
----------------------------------------------------------------
22
----------------------------------------------------------------
19
target-arm queue:
23
target-arm queue:
20
* aspeed: code cleanup to use unimplemented_device
24
* aspeed: set APB clocks correctly (fixes slowdown on palmetto)
21
* add 'raspi3' RaspberryPi 3 machine model
25
* smmuv3: cache config data and TLB entries
22
* more SVE prep work
26
* v7m/v8m: support read/write from MPU regions smaller than 1K
23
* v8M: add minor missing registers
27
* various: clean up logging/debug messages
24
* v7M: fix bug where we weren't migrating v7m.other_sp
28
* xilinx_spips: Make dma transactions as per dma_burst_size
25
* v7M: fix bugs in handling of interrupt registers for
26
external interrupts beyond 32
27
29
28
----------------------------------------------------------------
30
----------------------------------------------------------------
29
Pekka Enberg (3):
31
Cédric Le Goater (6):
30
bcm2836: Make CPU type configurable
32
aspeed/smc: fix dummy cycles count when in dual IO mode
31
raspi: Raspberry Pi 3 support
33
aspeed/smc: fix HW strapping
32
raspi: Add "raspi3" machine type
34
aspeed/smc: rename aspeed_smc_flash_send_addr() to aspeed_smc_flash_setup()
35
aspeed/scu: introduce clock frequencies
36
aspeed: initialize the SCU controller first
37
aspeed/timer: use the APB frequency from the SCU
33
38
34
Peter Maydell (11):
39
Eric Auger (3):
35
hw/intc/armv7m_nvic: Don't hardcode M profile ID registers in NVIC
40
hw/arm/smmuv3: Cache/invalidate config data
36
hw/intc/armv7m_nvic: Fix ICSR PENDNMISET/CLR handling
41
hw/arm/smmuv3: IOTLB emulation
37
hw/intc/armv7m_nvic: Implement M profile cache maintenance ops
42
hw/arm/smmuv3: Add notifications on invalidation
38
hw/intc/armv7m_nvic: Implement v8M CPPWR register
39
hw/intc/armv7m_nvic: Implement cache ID registers
40
hw/intc/armv7m_nvic: Implement SCR
41
target/arm: Implement writing to CONTROL_NS for v8M
42
hw/intc/armv7m_nvic: Fix byte-to-interrupt number conversions
43
target/arm: Add AIRCR to vmstate struct
44
target/arm: Migrate v7m.other_sp
45
target/arm: Implement v8M MSPLIM and PSPLIM registers
46
43
47
Philippe Mathieu-Daudé (2):
44
Jia He (1):
48
hw/arm/aspeed: directly map the serial device to the system address space
45
hw/arm/smmuv3: Fix translate error handling
49
hw/arm/aspeed: simplify using the 'unimplemented device' for aspeed_soc.io
50
46
51
Richard Henderson (5):
47
Joel Stanley (1):
52
target/arm: Remove ARM_CP_64BIT from ZCR_EL registers
48
MAINTAINERS: Add ASPEED BMCs
53
target/arm: Enforce FP access to FPCR/FPSR
54
target/arm: Suppress TB end for FPCR/FPSR
55
target/arm: Enforce access to ZCR_EL at translation
56
target/arm: Handle SVE registers when using clear_vec_high
57
49
58
include/hw/arm/aspeed_soc.h | 1 -
50
Peter Maydell (3):
59
include/hw/arm/bcm2836.h | 1 +
51
tcg: Support MMU protection regions smaller than TARGET_PAGE_SIZE
60
target/arm/cpu.h | 71 ++++++++++++-----
52
target/arm: Set page (region) size in get_phys_addr_pmsav7()
61
target/arm/internals.h | 6 ++
53
target/arm: Handle small regions in get_phys_addr_pmsav8()
62
hw/arm/aspeed_soc.c | 35 ++-------
63
hw/arm/bcm2836.c | 17 +++--
64
hw/arm/raspi.c | 57 +++++++++++---
65
hw/intc/armv7m_nvic.c | 98 ++++++++++++++++++------
66
target/arm/cpu.c | 28 +++++++
67
target/arm/helper.c | 84 +++++++++++++++-----
68
target/arm/machine.c | 84 ++++++++++++++++++++
69
target/arm/translate-a64.c | 181 ++++++++++++++++++++------------------------
70
12 files changed, 452 insertions(+), 211 deletions(-)
71
54
55
Philippe Mathieu-Daudé (17):
56
MAINTAINERS: Adopt the Gumstix computers-on-module machines
57
hw/input/pckbd: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
58
hw/input/tsc2005: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
59
hw/dma/omap_dma: Use qemu_log_mask(UNIMP) instead of printf
60
hw/dma/omap_dma: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
61
hw/ssi/omap_spi: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
62
hw/sd/omap_mmc: Use qemu_log_mask(UNIMP) instead of printf
63
hw/i2c/omap_i2c: Use qemu_log_mask(UNIMP) instead of fprintf
64
hw/arm/omap1: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
65
hw/arm/omap: Use qemu_log_mask(GUEST_ERROR) instead of fprintf
66
hw/arm/stellaris: Use qemu_log_mask(UNIMP) instead of fprintf
67
hw/net/stellaris_enet: Fix a typo
68
hw/net/stellaris_enet: Use qemu_log_mask(GUEST_ERROR) instead of hw_error
69
hw/net/smc91c111: Use qemu_log_mask(GUEST_ERROR) instead of hw_error
70
hw/net/smc91c111: Use qemu_log_mask(UNIMP) instead of fprintf
71
hw/arm/stellaris: Fix gptm_write() error message
72
hw/arm/stellaris: Use HWADDR_PRIx to display register address
73
74
Sai Pavan Boddu (1):
75
xilinx_spips: Make dma transactions as per dma_burst_size
76
77
accel/tcg/softmmu_template.h | 24 ++-
78
hw/arm/smmuv3-internal.h | 12 +-
79
include/exec/cpu-all.h | 5 +-
80
include/hw/arm/omap.h | 30 +--
81
include/hw/arm/smmu-common.h | 24 +++
82
include/hw/arm/smmuv3.h | 1 +
83
include/hw/misc/aspeed_scu.h | 70 ++++++-
84
include/hw/ssi/xilinx_spips.h | 5 +-
85
include/hw/timer/aspeed_timer.h | 4 +
86
accel/tcg/cputlb.c | 131 +++++++++++--
87
hw/arm/aspeed_soc.c | 42 ++--
88
hw/arm/omap1.c | 18 +-
89
hw/arm/smmu-common.c | 118 ++++++++++-
90
hw/arm/smmuv3.c | 420 ++++++++++++++++++++++++++++++++++++----
91
hw/arm/stellaris.c | 8 +-
92
hw/dma/omap_dma.c | 70 ++++---
93
hw/i2c/omap_i2c.c | 20 +-
94
hw/input/pckbd.c | 4 +-
95
hw/input/tsc2005.c | 13 +-
96
hw/misc/aspeed_scu.c | 106 ++++++++++
97
hw/net/smc91c111.c | 21 +-
98
hw/net/stellaris_enet.c | 11 +-
99
hw/sd/omap_mmc.c | 13 +-
100
hw/ssi/aspeed_smc.c | 48 ++---
101
hw/ssi/omap_spi.c | 15 +-
102
hw/ssi/xilinx_spips.c | 23 ++-
103
hw/timer/aspeed_timer.c | 19 +-
104
target/arm/helper.c | 115 +++++++----
105
MAINTAINERS | 14 +-
106
hw/arm/trace-events | 27 ++-
107
30 files changed, 1176 insertions(+), 255 deletions(-)
108
diff view generated by jsdifflib
1
From: Pekka Enberg <penberg@iki.fi>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
This patch adds a "cpu-type" property to BCM2836 SoC in preparation for
3
When configured in dual I/O mode, address and data are sent in dual
4
reusing the code for the Raspberry Pi 3, which has a different processor
4
mode, including the dummy byte cycles in between. Adapt the count to
5
model.
5
the IO setting.
6
6
7
Signed-off-by: Pekka Enberg <penberg@iki.fi>
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
9
Message-id: 20180612065716.10587-2-clg@kaod.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/hw/arm/bcm2836.h | 1 +
12
hw/ssi/aspeed_smc.c | 9 ++++++++-
12
hw/arm/bcm2836.c | 17 +++++++++--------
13
1 file changed, 8 insertions(+), 1 deletion(-)
13
hw/arm/raspi.c | 3 +++
14
3 files changed, 13 insertions(+), 8 deletions(-)
15
14
16
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
15
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/bcm2836.h
17
--- a/hw/ssi/aspeed_smc.c
19
+++ b/include/hw/arm/bcm2836.h
18
+++ b/hw/ssi/aspeed_smc.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2836State {
21
DeviceState parent_obj;
22
/*< public >*/
23
24
+ char *cpu_type;
25
uint32_t enabled_cpus;
26
27
ARMCPU cpus[BCM2836_NCPUS];
28
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/bcm2836.c
31
+++ b/hw/arm/bcm2836.c
32
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
33
static void bcm2836_init(Object *obj)
20
34
{
21
/* CEx Control Register */
35
BCM2836State *s = BCM2836(obj);
22
#define R_CTRL0 (0x10 / 4)
36
- int n;
23
+#define CTRL_IO_DUAL_DATA (1 << 29)
37
-
24
+#define CTRL_IO_DUAL_ADDR_DATA (1 << 28) /* Includes dummies */
38
- for (n = 0; n < BCM2836_NCPUS; n++) {
25
#define CTRL_CMD_SHIFT 16
39
- object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
26
#define CTRL_CMD_MASK 0xff
40
- "cortex-a15-" TYPE_ARM_CPU);
27
#define CTRL_DUMMY_HIGH_SHIFT 14
41
- object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
28
@@ -XXX,XX +XXX,XX @@ static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
42
- &error_abort);
29
uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->id];
43
- }
30
uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
44
31
uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
45
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
32
+ uint32_t dummies = ((dummy_high << 2) | dummy_low) * 8;
46
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
33
47
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
34
- return ((dummy_high << 2) | dummy_low) * 8;
48
35
+ if (r_ctrl0 & CTRL_IO_DUAL_ADDR_DATA) {
49
/* common peripherals from bcm2835 */
36
+ dummies /= 2;
50
51
+ obj = OBJECT(dev);
52
+ for (n = 0; n < BCM2836_NCPUS; n++) {
53
+ object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
54
+ s->cpu_type);
55
+ object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
56
+ &error_abort);
57
+ }
37
+ }
58
+
38
+
59
obj = object_property_get_link(OBJECT(dev), "ram", &err);
39
+ return dummies;
60
if (obj == NULL) {
61
error_setg(errp, "%s: required ram link not found: %s",
62
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
63
}
40
}
64
41
65
static Property bcm2836_props[] = {
42
static void aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
66
+ DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
67
DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
68
DEFINE_PROP_END_OF_LIST()
69
};
70
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/arm/raspi.c
73
+++ b/hw/arm/raspi.c
74
@@ -XXX,XX +XXX,XX @@ static void raspi2_init(MachineState *machine)
75
/* Setup the SOC */
76
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
77
&error_abort);
78
+ object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
79
+ &error_abort);
80
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
81
&error_abort);
82
object_property_set_int(OBJECT(&s->soc), 0xa21041, "board-rev",
83
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
84
mc->no_parallel = 1;
85
mc->no_floppy = 1;
86
mc->no_cdrom = 1;
87
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
88
mc->max_cpus = BCM2836_NCPUS;
89
mc->min_cpus = BCM2836_NCPUS;
90
mc->default_cpus = BCM2836_NCPUS;
91
--
43
--
92
2.16.1
44
2.17.1
93
45
94
46
diff view generated by jsdifflib
New patch
1
From: Cédric Le Goater <clg@kaod.org>
1
2
3
Only the flash type is strapped by HW. The 4BYTE mode is set by
4
firmware when the flash device is detected.
5
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
8
Message-id: 20180612065716.10587-3-clg@kaod.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/ssi/aspeed_smc.c | 8 +-------
12
1 file changed, 1 insertion(+), 7 deletions(-)
13
14
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/ssi/aspeed_smc.c
17
+++ b/hw/ssi/aspeed_smc.c
18
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_reset(DeviceState *d)
19
aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
20
}
21
22
- /* HW strapping for AST2500 FMC controllers */
23
+ /* HW strapping flash type for FMC controllers */
24
if (s->ctrl->segments == aspeed_segments_ast2500_fmc) {
25
/* flash type is fixed to SPI for CE0 and CE1 */
26
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
27
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1);
28
-
29
- /* 4BYTE mode is autodetected for CE0. Let's force it to 1 for
30
- * now */
31
- s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
32
}
33
34
/* HW strapping for AST2400 FMC controllers (SCU70). Let's use the
35
* configuration of the palmetto-bmc machine */
36
if (s->ctrl->segments == aspeed_segments_fmc) {
37
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
38
-
39
- s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
40
}
41
}
42
43
--
44
2.17.1
45
46
diff view generated by jsdifflib
1
Instead of hardcoding the values of M profile ID registers in the
1
From: Cédric Le Goater <clg@kaod.org>
2
NVIC, use the fields in the CPU struct. This will allow us to
3
give different M profile CPU types different ID register values.
4
2
5
This commit includes the addition of the missing ID_ISAR5,
3
Also handle the fake transfers for dummy bytes in this setup
6
which exists as RES0 in both v7M and v8M.
4
routine. It will be useful when we activate MMIO execution.
7
5
8
(The values of the ID registers might be wrong for the M4 --
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
this commit leaves the behaviour there unchanged.)
7
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
8
Message-id: 20180612065716.10587-4-clg@kaod.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/ssi/aspeed_smc.c | 31 ++++++++++++++++---------------
12
1 file changed, 16 insertions(+), 15 deletions(-)
10
13
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180209165810.6668-2-peter.maydell@linaro.org
15
---
16
hw/intc/armv7m_nvic.c | 30 ++++++++++++++++--------------
17
target/arm/cpu.c | 28 ++++++++++++++++++++++++++++
18
2 files changed, 44 insertions(+), 14 deletions(-)
19
20
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/armv7m_nvic.c
16
--- a/hw/ssi/aspeed_smc.c
23
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/hw/ssi/aspeed_smc.c
24
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
18
@@ -XXX,XX +XXX,XX @@ static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
25
"Aux Fault status registers unimplemented\n");
19
return dummies;
26
return 0;
27
case 0xd40: /* PFR0. */
28
- return 0x00000030;
29
- case 0xd44: /* PRF1. */
30
- return 0x00000200;
31
+ return cpu->id_pfr0;
32
+ case 0xd44: /* PFR1. */
33
+ return cpu->id_pfr1;
34
case 0xd48: /* DFR0. */
35
- return 0x00100000;
36
+ return cpu->id_dfr0;
37
case 0xd4c: /* AFR0. */
38
- return 0x00000000;
39
+ return cpu->id_afr0;
40
case 0xd50: /* MMFR0. */
41
- return 0x00000030;
42
+ return cpu->id_mmfr0;
43
case 0xd54: /* MMFR1. */
44
- return 0x00000000;
45
+ return cpu->id_mmfr1;
46
case 0xd58: /* MMFR2. */
47
- return 0x00000000;
48
+ return cpu->id_mmfr2;
49
case 0xd5c: /* MMFR3. */
50
- return 0x00000000;
51
+ return cpu->id_mmfr3;
52
case 0xd60: /* ISAR0. */
53
- return 0x01141110;
54
+ return cpu->id_isar0;
55
case 0xd64: /* ISAR1. */
56
- return 0x02111000;
57
+ return cpu->id_isar1;
58
case 0xd68: /* ISAR2. */
59
- return 0x21112231;
60
+ return cpu->id_isar2;
61
case 0xd6c: /* ISAR3. */
62
- return 0x01111110;
63
+ return cpu->id_isar3;
64
case 0xd70: /* ISAR4. */
65
- return 0x01310102;
66
+ return cpu->id_isar4;
67
+ case 0xd74: /* ISAR5. */
68
+ return cpu->id_isar5;
69
/* TODO: Implement debug registers. */
70
case 0xd90: /* MPU_TYPE */
71
/* Unified MPU; if the MPU is not present this value is zero */
72
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/cpu.c
75
+++ b/target/arm/cpu.c
76
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
77
set_feature(&cpu->env, ARM_FEATURE_M);
78
cpu->midr = 0x410fc231;
79
cpu->pmsav7_dregion = 8;
80
+ cpu->id_pfr0 = 0x00000030;
81
+ cpu->id_pfr1 = 0x00000200;
82
+ cpu->id_dfr0 = 0x00100000;
83
+ cpu->id_afr0 = 0x00000000;
84
+ cpu->id_mmfr0 = 0x00000030;
85
+ cpu->id_mmfr1 = 0x00000000;
86
+ cpu->id_mmfr2 = 0x00000000;
87
+ cpu->id_mmfr3 = 0x00000000;
88
+ cpu->id_isar0 = 0x01141110;
89
+ cpu->id_isar1 = 0x02111000;
90
+ cpu->id_isar2 = 0x21112231;
91
+ cpu->id_isar3 = 0x01111110;
92
+ cpu->id_isar4 = 0x01310102;
93
+ cpu->id_isar5 = 0x00000000;
94
}
20
}
95
21
96
static void cortex_m4_initfn(Object *obj)
22
-static void aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
97
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
23
+static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
98
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
24
{
99
cpu->midr = 0x410fc240; /* r0p0 */
25
const AspeedSMCState *s = fl->controller;
100
cpu->pmsav7_dregion = 8;
26
uint8_t cmd = aspeed_smc_flash_cmd(fl);
101
+ cpu->id_pfr0 = 0x00000030;
27
+ int i;
102
+ cpu->id_pfr1 = 0x00000200;
28
103
+ cpu->id_dfr0 = 0x00100000;
29
/* Flash access can not exceed CS segment */
104
+ cpu->id_afr0 = 0x00000000;
30
addr = aspeed_smc_check_segment_addr(fl, addr);
105
+ cpu->id_mmfr0 = 0x00000030;
31
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
106
+ cpu->id_mmfr1 = 0x00000000;
32
ssi_transfer(s->spi, (addr >> 16) & 0xff);
107
+ cpu->id_mmfr2 = 0x00000000;
33
ssi_transfer(s->spi, (addr >> 8) & 0xff);
108
+ cpu->id_mmfr3 = 0x00000000;
34
ssi_transfer(s->spi, (addr & 0xff));
109
+ cpu->id_isar0 = 0x01141110;
35
+
110
+ cpu->id_isar1 = 0x02111000;
36
+ /*
111
+ cpu->id_isar2 = 0x21112231;
37
+ * Use fake transfers to model dummy bytes. The value should
112
+ cpu->id_isar3 = 0x01111110;
38
+ * be configured to some non-zero value in fast read mode and
113
+ cpu->id_isar4 = 0x01310102;
39
+ * zero in read mode. But, as the HW allows inconsistent
114
+ cpu->id_isar5 = 0x00000000;
40
+ * settings, let's check for fast read mode.
41
+ */
42
+ if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
43
+ for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
44
+ ssi_transfer(fl->controller->spi, 0xFF);
45
+ }
46
+ }
115
}
47
}
116
48
117
static void arm_v7m_class_init(ObjectClass *oc, void *data)
49
static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
50
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
51
case CTRL_READMODE:
52
case CTRL_FREADMODE:
53
aspeed_smc_flash_select(fl);
54
- aspeed_smc_flash_send_addr(fl, addr);
55
-
56
- /*
57
- * Use fake transfers to model dummy bytes. The value should
58
- * be configured to some non-zero value in fast read mode and
59
- * zero in read mode. But, as the HW allows inconsistent
60
- * settings, let's check for fast read mode.
61
- */
62
- if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
63
- for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
64
- ssi_transfer(fl->controller->spi, 0xFF);
65
- }
66
- }
67
+ aspeed_smc_flash_setup(fl, addr);
68
69
for (i = 0; i < size; i++) {
70
ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
71
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
72
break;
73
case CTRL_WRITEMODE:
74
aspeed_smc_flash_select(fl);
75
- aspeed_smc_flash_send_addr(fl, addr);
76
+ aspeed_smc_flash_setup(fl, addr);
77
78
for (i = 0; i < size; i++) {
79
ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
118
--
80
--
119
2.16.1
81
2.17.1
120
82
121
83
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
(qemu) info mtree
3
These COMs are hard to find, and the companie dropped the support
4
address-space: cpu-memory-0
4
few years ago.
5
0000000000000000-ffffffffffffffff (prio 0, i/o): system
5
6
0000000000000000-0000000007ffffff (prio 0, rom): aspeed.boot_rom
6
Per the "Gumstix Product Changes, Known Issues, and EOL" pdf:
7
- 000000001e600000-000000001e7fffff (prio -1, i/o): aspeed_soc.io
7
8
+ 000000001e600000-000000001e7fffff (prio -1000, i/o): aspeed_soc.io
8
- Phasing out: PXA270-based Verdex product line
9
000000001e620000-000000001e6200ff (prio 0, i/o): aspeed.smc.ast2500-fmc
9
September 2012
10
000000001e630000-000000001e6300ff (prio 0, i/o): aspeed.smc.ast2500-spi1
10
11
000000001e631000-000000001e6310ff (prio 0, i/o): aspeed.smc.ast2500-spi2
11
- Phasing out: PXA255-based Basix & Connex
12
September 2009
13
14
However there are still booting SD card image availables, very
15
convenient to stress test the QEMU SD card implementation.
16
Therefore I volunteer to keep an eye on this file, while it
17
is useful for testing.
12
18
13
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
20
Reviewed-by: Thomas Huth <thuth@redhat.com>
15
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
21
Message-id: 20180606144706.29732-1-f4bug@amsat.org
16
Message-id: 20180209085755.30414-3-f4bug@amsat.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
23
---
19
include/hw/arm/aspeed_soc.h | 1 -
24
MAINTAINERS | 3 ++-
20
hw/arm/aspeed_soc.c | 32 +++-----------------------------
25
1 file changed, 2 insertions(+), 1 deletion(-)
21
2 files changed, 3 insertions(+), 30 deletions(-)
22
26
23
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
27
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/aspeed_soc.h
29
--- a/MAINTAINERS
26
+++ b/include/hw/arm/aspeed_soc.h
30
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
31
@@ -XXX,XX +XXX,XX @@ F: include/hw/arm/digic.h
28
32
F: hw/*/digic*
29
/*< public >*/
33
30
ARMCPU cpu;
34
Gumstix
31
- MemoryRegion iomem;
35
+M: Philippe Mathieu-Daudé <f4bug@amsat.org>
32
MemoryRegion sram;
36
L: qemu-devel@nongnu.org
33
AspeedVICState vic;
37
L: qemu-arm@nongnu.org
34
AspeedTimerCtrlState timerctrl;
38
-S: Orphan
35
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
39
+S: Odd Fixes
36
index XXXXXXX..XXXXXXX 100644
40
F: hw/arm/gumstix.c
37
--- a/hw/arm/aspeed_soc.c
41
38
+++ b/hw/arm/aspeed_soc.c
42
i.MX31
39
@@ -XXX,XX +XXX,XX @@
40
#include "qemu-common.h"
41
#include "cpu.h"
42
#include "exec/address-spaces.h"
43
+#include "hw/misc/unimp.h"
44
#include "hw/arm/aspeed_soc.h"
45
#include "hw/char/serial.h"
46
#include "qemu/log.h"
47
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
48
},
49
};
50
51
-/*
52
- * IO handlers: simply catch any reads/writes to IO addresses that aren't
53
- * handled by a device mapping.
54
- */
55
-
56
-static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
57
-{
58
- qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
59
- __func__, offset, size);
60
- return 0;
61
-}
62
-
63
-static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
64
- unsigned size)
65
-{
66
- qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
67
- __func__, offset, value, size);
68
-}
69
-
70
-static const MemoryRegionOps aspeed_soc_io_ops = {
71
- .read = aspeed_soc_io_read,
72
- .write = aspeed_soc_io_write,
73
- .endianness = DEVICE_LITTLE_ENDIAN,
74
-};
75
-
76
static void aspeed_soc_init(Object *obj)
77
{
78
AspeedSoCState *s = ASPEED_SOC(obj);
79
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
80
Error *err = NULL, *local_err = NULL;
81
82
/* IO space */
83
- memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
84
- "aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
85
- memory_region_add_subregion_overlap(get_system_memory(),
86
- ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
87
+ create_unimplemented_device("aspeed_soc.io",
88
+ ASPEED_SOC_IOMEM_BASE, ASPEED_SOC_IOMEM_SIZE);
89
90
/* CPU */
91
object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
92
--
43
--
93
2.16.1
44
2.17.1
94
45
95
46
diff view generated by jsdifflib
1
M profile cores have a similar setup for cache ID registers
1
From: Sai Pavan Boddu <saipava@xilinx.com>
2
to A profile:
3
* Cache Level ID Register (CLIDR) is a fixed value
4
* Cache Type Register (CTR) is a fixed value
5
* Cache Size ID Registers (CCSIDR) are a bank of registers;
6
which one you see is selected by the Cache Size Selection
7
Register (CSSELR)
8
2
9
The only difference is that they're in the NVIC memory mapped
3
Qspi dma has a burst length of 64 bytes, So limit the transactions w.r.t
10
register space rather than being coprocessor registers.
4
dma-burst-size property.
11
Implement the M profile view of them.
12
5
13
Since neither Cortex-M3 nor Cortex-M4 implement caches,
6
Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
14
we don't need to update their init functions and can leave
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
the ctr/clidr/ccsidr[] fields in their ARMCPU structs at zero.
8
Message-id: 1529660880-30376-1-git-send-email-sai.pavan.boddu@xilinx.com
16
Newer cores (like the Cortex-M33) will want to be able to
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
set these ID registers to non-zero values, though.
10
---
11
include/hw/ssi/xilinx_spips.h | 5 ++++-
12
hw/ssi/xilinx_spips.c | 23 ++++++++++++++++++++---
13
2 files changed, 24 insertions(+), 4 deletions(-)
18
14
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20180209165810.6668-6-peter.maydell@linaro.org
22
---
23
target/arm/cpu.h | 26 ++++++++++++++++++++++++++
24
hw/intc/armv7m_nvic.c | 16 ++++++++++++++++
25
target/arm/machine.c | 36 ++++++++++++++++++++++++++++++++++++
26
3 files changed, 78 insertions(+)
27
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
17
--- a/include/hw/ssi/xilinx_spips.h
31
+++ b/target/arm/cpu.h
18
+++ b/include/hw/ssi/xilinx_spips.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
19
@@ -XXX,XX +XXX,XX @@ typedef struct XilinxSPIPS XilinxSPIPS;
33
uint32_t faultmask[M_REG_NUM_BANKS];
20
/* Bite off 4k chunks at a time */
34
uint32_t aircr; /* only holds r/w state if security extn implemented */
21
#define LQSPI_CACHE_SIZE 1024
35
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
22
36
+ uint32_t csselr[M_REG_NUM_BANKS];
23
+#define QSPI_DMA_MAX_BURST_SIZE 2048
37
} v7m;
38
39
/* Information associated with an exception about to be taken:
40
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_MPU_CTRL, ENABLE, 0, 1)
41
FIELD(V7M_MPU_CTRL, HFNMIENA, 1, 1)
42
FIELD(V7M_MPU_CTRL, PRIVDEFENA, 2, 1)
43
44
+/* v7M CLIDR bits */
45
+FIELD(V7M_CLIDR, CTYPE_ALL, 0, 21)
46
+FIELD(V7M_CLIDR, LOUIS, 21, 3)
47
+FIELD(V7M_CLIDR, LOC, 24, 3)
48
+FIELD(V7M_CLIDR, LOUU, 27, 3)
49
+FIELD(V7M_CLIDR, ICB, 30, 2)
50
+
24
+
51
+FIELD(V7M_CSSELR, IND, 0, 1)
25
typedef enum {
52
+FIELD(V7M_CSSELR, LEVEL, 1, 3)
26
READ = 0x3, READ_4 = 0x13,
53
+/* We use the combination of InD and Level to index into cpu->ccsidr[];
27
FAST_READ = 0xb, FAST_READ_4 = 0x0c,
54
+ * define a mask for this and check that it doesn't permit running off
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
55
+ * the end of the array.
29
XilinxQSPIPS parent_obj;
56
+ */
30
57
+FIELD(V7M_CSSELR, INDEX, 0, 4)
31
StreamSlave *dma;
32
- uint8_t dma_buf[4];
33
int gqspi_irqline;
34
35
uint32_t regs[XLNX_ZYNQMP_SPIPS_R_MAX];
36
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
uint8_t rx_fifo_g_align;
38
uint8_t tx_fifo_g_align;
39
bool man_start_com_g;
40
+ uint32_t dma_burst_size;
41
+ uint8_t dma_buf[QSPI_DMA_MAX_BURST_SIZE];
42
} XlnxZynqMPQSPIPS;
43
44
typedef struct XilinxSPIPSClass {
45
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/ssi/xilinx_spips.c
48
+++ b/hw/ssi/xilinx_spips.c
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
50
{
51
size_t ret;
52
uint32_t num;
53
- const void *rxd = pop_buf(recv_fifo, 4, &num);
54
+ const void *rxd;
55
+ int len;
58
+
56
+
59
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
57
+ len = recv_fifo->num >= rq->dma_burst_size ? rq->dma_burst_size :
60
+
58
+ recv_fifo->num;
61
/* If adding a feature bit which corresponds to a Linux ELF
59
+ rxd = pop_buf(recv_fifo, len, &num);
62
* HWCAP bit, remember to update the feature-bit-to-hwcap
60
63
* mapping in linux-user/elfload.c:get_elf_hwcap().
61
memcpy(rq->dma_buf, rxd, num);
64
@@ -XXX,XX +XXX,XX @@ static inline int arm_debug_target_el(CPUARMState *env)
62
63
- ret = stream_push(rq->dma, rq->dma_buf, 4);
64
- assert(ret == 4);
65
+ ret = stream_push(rq->dma, rq->dma_buf, num);
66
+ assert(ret == num);
67
xlnx_zynqmp_qspips_check_flush(rq);
65
}
68
}
66
}
69
}
67
70
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_realize(DeviceState *dev, Error **errp)
68
+static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
71
XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(dev);
69
+{
72
XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
70
+ /* If all the CLIDR.Ctypem bits are 0 there are no caches, and
73
71
+ * CSSELR is RAZ/WI.
74
+ if (s->dma_burst_size > QSPI_DMA_MAX_BURST_SIZE) {
72
+ */
75
+ error_setg(errp,
73
+ return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
76
+ "qspi dma burst size %u exceeds maximum limit %d",
74
+}
77
+ s->dma_burst_size, QSPI_DMA_MAX_BURST_SIZE);
75
+
78
+ return;
76
static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
77
{
78
if (arm_is_secure(env)) {
79
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/intc/armv7m_nvic.c
82
+++ b/hw/intc/armv7m_nvic.c
83
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
84
return cpu->id_isar4;
85
case 0xd74: /* ISAR5. */
86
return cpu->id_isar5;
87
+ case 0xd78: /* CLIDR */
88
+ return cpu->clidr;
89
+ case 0xd7c: /* CTR */
90
+ return cpu->ctr;
91
+ case 0xd80: /* CSSIDR */
92
+ {
93
+ int idx = cpu->env.v7m.csselr[attrs.secure] & R_V7M_CSSELR_INDEX_MASK;
94
+ return cpu->ccsidr[idx];
95
+ }
79
+ }
96
+ case 0xd84: /* CSSELR */
80
xilinx_qspips_realize(dev, errp);
97
+ return cpu->env.v7m.csselr[attrs.secure];
81
fifo8_create(&s->rx_fifo_g, xsc->rx_fifo_size);
98
/* TODO: Implement debug registers. */
82
fifo8_create(&s->tx_fifo_g, xsc->tx_fifo_size);
99
case 0xd90: /* MPU_TYPE */
83
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_xlnx_zynqmp_qspips = {
100
/* Unified MPU; if the MPU is not present this value is zero */
101
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
102
qemu_log_mask(LOG_UNIMP,
103
"NVIC: Aux fault status registers unimplemented\n");
104
break;
105
+ case 0xd84: /* CSSELR */
106
+ if (!arm_v7m_csselr_razwi(cpu)) {
107
+ cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
108
+ }
109
+ break;
110
case 0xd90: /* MPU_TYPE */
111
return; /* RO */
112
case 0xd94: /* MPU_CTRL */
113
diff --git a/target/arm/machine.c b/target/arm/machine.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/machine.c
116
+++ b/target/arm/machine.c
117
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_faultmask_primask = {
118
}
84
}
119
};
85
};
120
86
121
+/* CSSELR is in a subsection because we didn't implement it previously.
87
+static Property xilinx_zynqmp_qspips_properties[] = {
122
+ * Migration from an old implementation will leave it at zero, which
88
+ DEFINE_PROP_UINT32("dma-burst-size", XlnxZynqMPQSPIPS, dma_burst_size, 64),
123
+ * is OK since the only CPUs in the old implementation make the
89
+ DEFINE_PROP_END_OF_LIST(),
124
+ * register RAZ/WI.
125
+ * Since there was no version of QEMU which implemented the CSSELR for
126
+ * just non-secure, we transfer both banks here rather than putting
127
+ * the secure banked version in the m-security subsection.
128
+ */
129
+static bool csselr_vmstate_validate(void *opaque, int version_id)
130
+{
131
+ ARMCPU *cpu = opaque;
132
+
133
+ return cpu->env.v7m.csselr[M_REG_NS] <= R_V7M_CSSELR_INDEX_MASK
134
+ && cpu->env.v7m.csselr[M_REG_S] <= R_V7M_CSSELR_INDEX_MASK;
135
+}
136
+
137
+static bool m_csselr_needed(void *opaque)
138
+{
139
+ ARMCPU *cpu = opaque;
140
+
141
+ return !arm_v7m_csselr_razwi(cpu);
142
+}
143
+
144
+static const VMStateDescription vmstate_m_csselr = {
145
+ .name = "cpu/m/csselr",
146
+ .version_id = 1,
147
+ .minimum_version_id = 1,
148
+ .needed = m_csselr_needed,
149
+ .fields = (VMStateField[]) {
150
+ VMSTATE_UINT32_ARRAY(env.v7m.csselr, ARMCPU, M_REG_NUM_BANKS),
151
+ VMSTATE_VALIDATE("CSSELR is valid", csselr_vmstate_validate),
152
+ VMSTATE_END_OF_LIST()
153
+ }
154
+};
90
+};
155
+
91
+
156
static const VMStateDescription vmstate_m = {
92
static Property xilinx_qspips_properties[] = {
157
.name = "cpu/m",
93
/* We had to turn this off for 2.10 as it is not compatible with migration.
158
.version_id = 4,
94
* It can be enabled but will prevent the device to be migrated.
159
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
95
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_class_init(ObjectClass *klass, void * data)
160
},
96
dc->realize = xlnx_zynqmp_qspips_realize;
161
.subsections = (const VMStateDescription*[]) {
97
dc->reset = xlnx_zynqmp_qspips_reset;
162
&vmstate_m_faultmask_primask,
98
dc->vmsd = &vmstate_xlnx_zynqmp_qspips;
163
+ &vmstate_m_csselr,
99
+ dc->props = xilinx_zynqmp_qspips_properties;
164
NULL
100
xsc->reg_ops = &xlnx_zynqmp_qspips_ops;
165
}
101
xsc->rx_fifo_size = RXFF_A_Q;
166
};
102
xsc->tx_fifo_size = TXFF_A_Q;
167
--
103
--
168
2.16.1
104
2.17.1
169
105
170
106
diff view generated by jsdifflib
1
In commit abc24d86cc0364f we accidentally broke migration of
1
From: Joel Stanley <joel@jms.id.au>
2
the stack pointer value for the mode (process, handler) the CPU
3
is not currently running as. (The commit correctly removed the
4
no-longer-used v7m.current_sp flag from the VMState but also
5
deleted the still very much in use v7m.other_sp SP value field.)
6
2
7
Add a subsection to migrate it again. (We don't need to care
3
This adds Cedric as the maintainer, with Andrew and I as reviewers, for
8
about trying to retain compatibility with pre-abc24d86cc0364f
4
the ASPEED boards and the peripherals we have developed.
9
versions of QEMU, because that commit bumped the version_id
10
and we've since bumped it again a couple of times.)
11
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
8
Acked-by: Cédric Le Goater <clg@kaod.org>
9
Signed-off-by: Joel Stanley <joel@jms.id.au>
10
Message-id: 20180625140055.32223-1-joel@jms.id.au
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180209165810.6668-11-peter.maydell@linaro.org
15
---
12
---
16
target/arm/machine.c | 11 +++++++++++
13
MAINTAINERS | 11 +++++++++++
17
1 file changed, 11 insertions(+)
14
1 file changed, 11 insertions(+)
18
15
19
diff --git a/target/arm/machine.c b/target/arm/machine.c
16
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/machine.c
18
--- a/MAINTAINERS
22
+++ b/target/arm/machine.c
19
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_scr = {
20
@@ -XXX,XX +XXX,XX @@ M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
24
}
21
S: Maintained
25
};
22
F: hw/arm/msf2-som.c
26
23
27
+static const VMStateDescription vmstate_m_other_sp = {
24
+ASPEED BMCs
28
+ .name = "cpu/m/other-sp",
25
+M: Cédric Le Goater <clg@kaod.org>
29
+ .version_id = 1,
26
+R: Andrew Jeffery <andrew@aj.id.au>
30
+ .minimum_version_id = 1,
27
+R: Joel Stanley <joel@jms.id.au>
31
+ .fields = (VMStateField[]) {
28
+L: qemu-arm@nongnu.org
32
+ VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
29
+S: Maintained
33
+ VMSTATE_END_OF_LIST()
30
+F: hw/*/*aspeed*
34
+ }
31
+F: include/hw/*/*aspeed*
35
+};
32
+F: hw/net/ftgmac100.c
33
+F: include/hw/net/ftgmac100.h
36
+
34
+
37
static const VMStateDescription vmstate_m = {
35
CRIS Machines
38
.name = "cpu/m",
36
-------------
39
.version_id = 4,
37
Axis Dev88
40
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
41
&vmstate_m_faultmask_primask,
42
&vmstate_m_csselr,
43
&vmstate_m_scr,
44
+ &vmstate_m_other_sp,
45
NULL
46
}
47
};
48
--
38
--
49
2.16.1
39
2.17.1
50
40
51
41
diff view generated by jsdifflib
1
The PENDNMISET/CLR bits in the ICSR should be RAZ/WI from
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
NonSecure state if the AIRCR.BFHFNMINS bit is zero. We had
3
misimplemented this as making the bits RAZ/WI from both
4
Secure and NonSecure states. Fix this bug by checking
5
attrs.secure so that Secure code can pend and unpend NMIs.
6
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-2-f4bug@amsat.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180209165810.6668-3-peter.maydell@linaro.org
10
---
7
---
11
hw/intc/armv7m_nvic.c | 6 +++---
8
hw/input/pckbd.c | 4 +++-
12
1 file changed, 3 insertions(+), 3 deletions(-)
9
1 file changed, 3 insertions(+), 1 deletion(-)
13
10
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
11
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
13
--- a/hw/input/pckbd.c
17
+++ b/hw/intc/armv7m_nvic.c
14
+++ b/hw/input/pckbd.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
15
@@ -XXX,XX +XXX,XX @@
19
}
16
* THE SOFTWARE.
20
}
17
*/
21
/* NMIPENDSET */
18
#include "qemu/osdep.h"
22
- if ((cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) &&
19
+#include "qemu/log.h"
23
- s->vectors[ARMV7M_EXCP_NMI].pending) {
20
#include "hw/hw.h"
24
+ if ((attrs.secure || (cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))
21
#include "hw/isa/isa.h"
25
+ && s->vectors[ARMV7M_EXCP_NMI].pending) {
22
#include "hw/i386/pc.h"
26
val |= (1 << 31);
23
@@ -XXX,XX +XXX,XX @@ static void kbd_write_command(void *opaque, hwaddr addr,
27
}
24
/* ignore that */
28
/* ISRPREEMPT: RES0 when halting debug not implemented */
25
break;
29
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
26
default:
27
- fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", (int)val);
28
+ qemu_log_mask(LOG_GUEST_ERROR,
29
+ "unsupported keyboard cmd=0x%02" PRIx64 "\n", val);
30
break;
30
break;
31
}
31
}
32
case 0xd04: /* Interrupt Control State (ICSR) */
32
}
33
- if (cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
34
+ if (attrs.secure || cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
35
if (value & (1 << 31)) {
36
armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
37
} else if (value & (1 << 30) &&
38
--
33
--
39
2.16.1
34
2.17.1
40
35
41
36
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Message-id: 20180211205848.4568-3-richard.henderson@linaro.org
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180624040609.17572-3-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/cpu.h | 35 ++++++++++++++++++-----------------
8
hw/input/tsc2005.c | 13 ++++++++-----
9
target/arm/helper.c | 6 ++++--
9
1 file changed, 8 insertions(+), 5 deletions(-)
10
target/arm/translate-a64.c | 3 +++
11
3 files changed, 25 insertions(+), 19 deletions(-)
12
10
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
13
--- a/hw/input/tsc2005.c
16
+++ b/target/arm/cpu.h
14
+++ b/hw/input/tsc2005.c
17
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
15
@@ -XXX,XX +XXX,XX @@
16
*/
17
18
#include "qemu/osdep.h"
19
+#include "qemu/log.h"
20
#include "hw/hw.h"
21
#include "qemu/timer.h"
22
#include "ui/console.h"
23
@@ -XXX,XX +XXX,XX @@ static void tsc2005_write(TSC2005State *s, int reg, uint16_t data)
24
}
25
s->nextprecision = (data >> 13) & 1;
26
s->timing[0] = data & 0x1fff;
27
- if ((s->timing[0] >> 11) == 3)
28
- fprintf(stderr, "%s: illegal conversion clock setting\n",
29
- __func__);
30
+ if ((s->timing[0] >> 11) == 3) {
31
+ qemu_log_mask(LOG_GUEST_ERROR,
32
+ "tsc2005_write: illegal conversion clock setting\n");
33
+ }
34
break;
35
case 0xd:    /* CFR1 */
36
s->timing[1] = data & 0xf07;
37
@@ -XXX,XX +XXX,XX @@ static void tsc2005_write(TSC2005State *s, int reg, uint16_t data)
38
break;
39
40
default:
41
- fprintf(stderr, "%s: write into read-only register %x\n",
42
- __func__, reg);
43
+ qemu_log_mask(LOG_GUEST_ERROR,
44
+ "%s: write into read-only register 0x%x\n",
45
+ __func__, reg);
46
}
18
}
47
}
19
48
20
/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
21
- * special-behaviour cp reg and bits [15..8] indicate what behaviour
22
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
23
* it has. Otherwise it is a simple cp reg, where CONST indicates that
24
* TCG can assume the value to be constant (ie load at translate time)
25
* and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
26
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
27
* need to be surrounded by gen_io_start()/gen_io_end(). In particular,
28
* registers which implement clocks or timers require this.
29
*/
30
-#define ARM_CP_SPECIAL 1
31
-#define ARM_CP_CONST 2
32
-#define ARM_CP_64BIT 4
33
-#define ARM_CP_SUPPRESS_TB_END 8
34
-#define ARM_CP_OVERRIDE 16
35
-#define ARM_CP_ALIAS 32
36
-#define ARM_CP_IO 64
37
-#define ARM_CP_NO_RAW 128
38
-#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
39
-#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
40
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
41
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
42
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
43
-#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
44
+#define ARM_CP_SPECIAL 0x0001
45
+#define ARM_CP_CONST 0x0002
46
+#define ARM_CP_64BIT 0x0004
47
+#define ARM_CP_SUPPRESS_TB_END 0x0008
48
+#define ARM_CP_OVERRIDE 0x0010
49
+#define ARM_CP_ALIAS 0x0020
50
+#define ARM_CP_IO 0x0040
51
+#define ARM_CP_NO_RAW 0x0080
52
+#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
53
+#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
54
+#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
55
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
56
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
57
+#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
58
+#define ARM_CP_FPU 0x1000
59
/* Used only as a terminator for ARMCPRegInfo lists */
60
-#define ARM_CP_SENTINEL 0xffff
61
+#define ARM_CP_SENTINEL 0xffff
62
/* Mask of only the flag bits in a type field */
63
-#define ARM_CP_FLAG_MASK 0xff
64
+#define ARM_CP_FLAG_MASK 0x10ff
65
66
/* Valid values for ARMCPRegInfo state field, indicating which of
67
* the AArch32 and AArch64 execution states this register is visible in.
68
diff --git a/target/arm/helper.c b/target/arm/helper.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/helper.c
71
+++ b/target/arm/helper.c
72
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
73
.writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
74
{ .name = "FPCR", .state = ARM_CP_STATE_AA64,
75
.opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
76
- .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
77
+ .access = PL0_RW, .type = ARM_CP_FPU,
78
+ .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
79
{ .name = "FPSR", .state = ARM_CP_STATE_AA64,
80
.opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
81
- .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
82
+ .access = PL0_RW, .type = ARM_CP_FPU,
83
+ .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
84
{ .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
85
.opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
86
.access = PL0_R, .type = ARM_CP_NO_RAW,
87
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/translate-a64.c
90
+++ b/target/arm/translate-a64.c
91
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
92
default:
93
break;
94
}
95
+ if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
96
+ return;
97
+ }
98
99
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
100
gen_io_start();
101
--
49
--
102
2.16.1
50
2.17.1
103
51
104
52
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-4-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/dma/omap_dma.c | 6 ++++--
9
1 file changed, 4 insertions(+), 2 deletions(-)
10
11
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/dma/omap_dma.c
14
+++ b/hw/dma/omap_dma.c
15
@@ -XXX,XX +XXX,XX @@
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
17
*/
18
#include "qemu/osdep.h"
19
+#include "qemu/log.h"
20
#include "qemu-common.h"
21
#include "qemu/timer.h"
22
#include "hw/arm/omap.h"
23
@@ -XXX,XX +XXX,XX @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
24
case 0x480:    /* DMA_PCh0_SR */
25
case 0x482:    /* DMA_PCh1_SR */
26
case 0x4c0:    /* DMA_PChD_SR_0 */
27
- printf("%s: Physical Channel Status Registers not implemented.\n",
28
- __func__);
29
+ qemu_log_mask(LOG_UNIMP,
30
+ "%s: Physical Channel Status Registers not implemented\n",
31
+ __func__);
32
*ret = 0xff;
33
break;
34
35
--
36
2.17.1
37
38
diff view generated by jsdifflib
1
We were previously making the system control register (SCR)
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
just RAZ/WI. Although we don't implement the functionality
3
this register controls, we should at least provide the state,
4
including the banked state for v8M.
5
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-5-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180209165810.6668-7-peter.maydell@linaro.org
9
---
7
---
10
target/arm/cpu.h | 7 +++++++
8
hw/dma/omap_dma.c | 64 +++++++++++++++++++++++++++++------------------
11
hw/intc/armv7m_nvic.c | 12 ++++++++----
9
1 file changed, 40 insertions(+), 24 deletions(-)
12
target/arm/machine.c | 12 ++++++++++++
13
3 files changed, 27 insertions(+), 4 deletions(-)
14
10
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
13
--- a/hw/dma/omap_dma.c
18
+++ b/target/arm/cpu.h
14
+++ b/hw/dma/omap_dma.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
15
@@ -XXX,XX +XXX,XX @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
20
uint32_t aircr; /* only holds r/w state if security extn implemented */
16
ch->burst[0] = (value & 0x0180) >> 7;
21
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
17
ch->pack[0] = (value & 0x0040) >> 6;
22
uint32_t csselr[M_REG_NUM_BANKS];
18
ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
23
+ uint32_t scr[M_REG_NUM_BANKS];
19
- if (ch->port[0] >= __omap_dma_port_last)
24
} v7m;
20
- printf("%s: invalid DMA port %i\n", __func__,
25
21
- ch->port[0]);
26
/* Information associated with an exception about to be taken:
22
- if (ch->port[1] >= __omap_dma_port_last)
27
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKALIGN, 9, 1)
23
- printf("%s: invalid DMA port %i\n", __func__,
28
FIELD(V7M_CCR, DC, 16, 1)
24
- ch->port[1]);
29
FIELD(V7M_CCR, IC, 17, 1)
25
+ if (ch->port[0] >= __omap_dma_port_last) {
30
26
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid DMA port %i\n",
31
+/* V7M SCR bits */
27
+ __func__, ch->port[0]);
32
+FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
28
+ }
33
+FIELD(V7M_SCR, SLEEPDEEP, 2, 1)
29
+ if (ch->port[1] >= __omap_dma_port_last) {
34
+FIELD(V7M_SCR, SLEEPDEEPS, 3, 1)
30
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid DMA port %i\n",
35
+FIELD(V7M_SCR, SEVONPEND, 4, 1)
31
+ __func__, ch->port[1]);
36
+
32
+ }
37
/* V7M AIRCR bits */
33
ch->data_type = 1 << (value & 3);
38
FIELD(V7M_AIRCR, VECTRESET, 0, 1)
34
if ((value & 3) == 3) {
39
FIELD(V7M_AIRCR, VECTCLRACTIVE, 1, 1)
35
- printf("%s: bad data_type for DMA channel\n", __func__);
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
36
+ qemu_log_mask(LOG_GUEST_ERROR,
41
index XXXXXXX..XXXXXXX 100644
37
+ "%s: bad data_type for DMA channel\n", __func__);
42
--- a/hw/intc/armv7m_nvic.c
38
ch->data_type >>= 1;
43
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
45
}
46
return val;
47
case 0xd10: /* System Control. */
48
- /* TODO: Implement SLEEPONEXIT. */
49
- return 0;
50
+ return cpu->env.v7m.scr[attrs.secure];
51
case 0xd14: /* Configuration Control. */
52
/* The BFHFNMIGN bit is the only non-banked bit; we
53
* keep it in the non-secure copy of the register.
54
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
55
}
39
}
56
break;
40
break;
57
case 0xd10: /* System Control. */
41
@@ -XXX,XX +XXX,XX @@ static void omap_dma4_write(void *opaque, hwaddr addr,
58
- /* TODO: Implement control registers. */
42
if (value & 2)                        /* SOFTRESET */
59
- qemu_log_mask(LOG_UNIMP, "NVIC: SCR unimplemented\n");
43
omap_dma_reset(s->dma);
60
+ /* We don't implement deep-sleep so these bits are RAZ/WI.
44
s->ocp = value & 0x3321;
61
+ * The other bits in the register are banked.
45
- if (((s->ocp >> 12) & 3) == 3)                /* MIDLEMODE */
62
+ * QEMU's implementation ignores SEVONPEND and SLEEPONEXIT, which
46
- fprintf(stderr, "%s: invalid DMA power mode\n", __func__);
63
+ * is architecturally permitted.
47
+ if (((s->ocp >> 12) & 3) == 3) { /* MIDLEMODE */
64
+ */
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid DMA power mode\n",
65
+ value &= ~(R_V7M_SCR_SLEEPDEEP_MASK | R_V7M_SCR_SLEEPDEEPS_MASK);
49
+ __func__);
66
+ cpu->env.v7m.scr[attrs.secure] = value;
50
+ }
51
return;
52
53
case 0x78:    /* DMA4_GCR */
54
s->gcr = value & 0x00ff00ff;
55
-    if ((value & 0xff) == 0x00)        /* MAX_CHANNEL_FIFO_DEPTH */
56
- fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __func__);
57
+ if ((value & 0xff) == 0x00) { /* MAX_CHANNEL_FIFO_DEPTH */
58
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: wrong FIFO depth in GCR\n",
59
+ __func__);
60
+ }
61
return;
62
63
case 0x80 ... 0xfff:
64
@@ -XXX,XX +XXX,XX @@ static void omap_dma4_write(void *opaque, hwaddr addr,
65
case 0x00:    /* DMA4_CCR */
66
ch->buf_disable = (value >> 25) & 1;
67
ch->src_sync = (value >> 24) & 1;    /* XXX For CamDMA must be 1 */
68
- if (ch->buf_disable && !ch->src_sync)
69
- fprintf(stderr, "%s: Buffering disable is not allowed in "
70
- "destination synchronised mode\n", __func__);
71
+ if (ch->buf_disable && !ch->src_sync) {
72
+ qemu_log_mask(LOG_GUEST_ERROR,
73
+ "%s: Buffering disable is not allowed in "
74
+ "destination synchronised mode\n", __func__);
75
+ }
76
ch->prefetch = (value >> 23) & 1;
77
ch->bs = (value >> 18) & 1;
78
ch->transparent_copy = (value >> 17) & 1;
79
@@ -XXX,XX +XXX,XX @@ static void omap_dma4_write(void *opaque, hwaddr addr,
80
ch->suspend = (value & 0x0100) >> 8;
81
ch->priority = (value & 0x0040) >> 6;
82
ch->fs = (value & 0x0020) >> 5;
83
- if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1])
84
- fprintf(stderr, "%s: For a packet transfer at least one port "
85
- "must be constant-addressed\n", __func__);
86
+ if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1]) {
87
+ qemu_log_mask(LOG_GUEST_ERROR,
88
+ "%s: For a packet transfer at least one port "
89
+ "must be constant-addressed\n", __func__);
90
+ }
91
ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060);
92
/* XXX must be 0x01 for CamDMA */
93
94
@@ -XXX,XX +XXX,XX @@ static void omap_dma4_write(void *opaque, hwaddr addr,
95
ch->endian_lock[0] =(value >> 20) & 1;
96
ch->endian[1] =(value >> 19) & 1;
97
ch->endian_lock[1] =(value >> 18) & 1;
98
- if (ch->endian[0] != ch->endian[1])
99
- fprintf(stderr, "%s: DMA endianness conversion enable attempt\n",
100
- __func__);
101
+ if (ch->endian[0] != ch->endian[1]) {
102
+ qemu_log_mask(LOG_GUEST_ERROR,
103
+ "%s: DMA endianness conversion enable attempt\n",
104
+ __func__);
105
+ }
106
ch->write_mode = (value >> 16) & 3;
107
ch->burst[1] = (value & 0xc000) >> 14;
108
ch->pack[1] = (value & 0x2000) >> 13;
109
@@ -XXX,XX +XXX,XX @@ static void omap_dma4_write(void *opaque, hwaddr addr,
110
ch->burst[0] = (value & 0x0180) >> 7;
111
ch->pack[0] = (value & 0x0040) >> 6;
112
ch->translate[0] = (value & 0x003c) >> 2;
113
- if (ch->translate[0] | ch->translate[1])
114
- fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n",
115
- __func__);
116
+ if (ch->translate[0] | ch->translate[1]) {
117
+ qemu_log_mask(LOG_GUEST_ERROR,
118
+ "%s: bad MReqAddressTranslate sideband signal\n",
119
+ __func__);
120
+ }
121
ch->data_type = 1 << (value & 3);
122
if ((value & 3) == 3) {
123
- printf("%s: bad data_type for DMA channel\n", __func__);
124
+ qemu_log_mask(LOG_GUEST_ERROR,
125
+ "%s: bad data_type for DMA channel\n", __func__);
126
ch->data_type >>= 1;
127
}
67
break;
128
break;
68
case 0xd14: /* Configuration Control. */
69
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
70
diff --git a/target/arm/machine.c b/target/arm/machine.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/machine.c
73
+++ b/target/arm/machine.c
74
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_csselr = {
75
}
76
};
77
78
+static const VMStateDescription vmstate_m_scr = {
79
+ .name = "cpu/m/scr",
80
+ .version_id = 1,
81
+ .minimum_version_id = 1,
82
+ .fields = (VMStateField[]) {
83
+ VMSTATE_UINT32(env.v7m.scr[M_REG_NS], ARMCPU),
84
+ VMSTATE_END_OF_LIST()
85
+ }
86
+};
87
+
88
static const VMStateDescription vmstate_m = {
89
.name = "cpu/m",
90
.version_id = 4,
91
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
92
.subsections = (const VMStateDescription*[]) {
93
&vmstate_m_faultmask_primask,
94
&vmstate_m_csselr,
95
+ &vmstate_m_scr,
96
NULL
97
}
98
};
99
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
100
VMSTATE_UINT32(env.sau.rnr, ARMCPU),
101
VMSTATE_VALIDATE("SAU_RNR is valid", sau_rnr_vmstate_validate),
102
VMSTATE_UINT32(env.sau.ctrl, ARMCPU),
103
+ VMSTATE_UINT32(env.v7m.scr[M_REG_S], ARMCPU),
104
VMSTATE_END_OF_LIST()
105
}
106
};
107
--
129
--
108
2.16.1
130
2.17.1
109
131
110
132
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Message-id: 20180624040609.17572-6-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/ssi/omap_spi.c | 15 ++++++++++-----
9
1 file changed, 10 insertions(+), 5 deletions(-)
10
11
diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/ssi/omap_spi.c
14
+++ b/hw/ssi/omap_spi.c
15
@@ -XXX,XX +XXX,XX @@
16
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
*/
18
#include "qemu/osdep.h"
19
+#include "qemu/log.h"
20
#include "hw/hw.h"
21
#include "hw/arm/omap.h"
22
23
@@ -XXX,XX +XXX,XX @@ static void omap_mcspi_write(void *opaque, hwaddr addr,
24
case 0x2c:    /* MCSPI_CHCONF */
25
if ((value ^ s->ch[ch].config) & (3 << 14))    /* DMAR | DMAW */
26
omap_mcspi_dmarequest_update(s->ch + ch);
27
- if (((value >> 12) & 3) == 3)            /* TRM */
28
- fprintf(stderr, "%s: invalid TRM value (3)\n", __func__);
29
- if (((value >> 7) & 0x1f) < 3)            /* WL */
30
- fprintf(stderr, "%s: invalid WL value (%" PRIx64 ")\n",
31
- __func__, (value >> 7) & 0x1f);
32
+ if (((value >> 12) & 3) == 3) { /* TRM */
33
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid TRM value (3)\n",
34
+ __func__);
35
+ }
36
+ if (((value >> 7) & 0x1f) < 3) { /* WL */
37
+ qemu_log_mask(LOG_GUEST_ERROR,
38
+ "%s: invalid WL value (%" PRIx64 ")\n",
39
+ __func__, (value >> 7) & 0x1f);
40
+ }
41
s->ch[ch].config = value & 0x7fffff;
42
break;
43
44
--
45
2.17.1
46
47
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-7-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/sd/omap_mmc.c | 13 +++++++++----
9
1 file changed, 9 insertions(+), 4 deletions(-)
10
11
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/sd/omap_mmc.c
14
+++ b/hw/sd/omap_mmc.c
15
@@ -XXX,XX +XXX,XX @@
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
17
*/
18
#include "qemu/osdep.h"
19
+#include "qemu/log.h"
20
#include "hw/hw.h"
21
#include "hw/arm/omap.h"
22
#include "hw/sd/sd.h"
23
@@ -XXX,XX +XXX,XX @@ static void omap_mmc_write(void *opaque, hwaddr offset,
24
s->enable = (value >> 11) & 1;
25
s->be = (value >> 10) & 1;
26
s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff);
27
- if (s->mode != 0)
28
- printf("SD mode %i unimplemented!\n", s->mode);
29
- if (s->be != 0)
30
- printf("SD FIFO byte sex unimplemented!\n");
31
+ if (s->mode != 0) {
32
+ qemu_log_mask(LOG_UNIMP,
33
+ "omap_mmc_wr: mode #%i unimplemented\n", s->mode);
34
+ }
35
+ if (s->be != 0) {
36
+ qemu_log_mask(LOG_UNIMP,
37
+ "omap_mmc_wr: Big Endian not implemented\n");
38
+ }
39
if (s->dw != 0 && s->lines < 4)
40
printf("4-bit SD bus enabled\n");
41
if (!s->enable)
42
--
43
2.17.1
44
45
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-8-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/i2c/omap_i2c.c | 20 ++++++++++++--------
9
1 file changed, 12 insertions(+), 8 deletions(-)
10
11
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/i2c/omap_i2c.c
14
+++ b/hw/i2c/omap_i2c.c
15
@@ -XXX,XX +XXX,XX @@
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
17
*/
18
#include "qemu/osdep.h"
19
+#include "qemu/log.h"
20
#include "hw/hw.h"
21
#include "hw/i2c/i2c.h"
22
#include "hw/arm/omap.h"
23
@@ -XXX,XX +XXX,XX @@ static void omap_i2c_write(void *opaque, hwaddr addr,
24
}
25
break;
26
}
27
- if ((value & (1 << 15)) && !(value & (1 << 10))) {    /* MST */
28
- fprintf(stderr, "%s: I^2C slave mode not supported\n",
29
- __func__);
30
+ if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
31
+ qemu_log_mask(LOG_UNIMP, "%s: I^2C slave mode not supported\n",
32
+ __func__);
33
break;
34
}
35
- if ((value & (1 << 15)) && value & (1 << 8)) {        /* XA */
36
- fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
37
- __func__);
38
+ if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
39
+ qemu_log_mask(LOG_UNIMP,
40
+ "%s: 10-bit addressing mode not supported\n",
41
+ __func__);
42
break;
43
}
44
if ((value & (1 << 15)) && value & (1 << 0)) {        /* STT */
45
@@ -XXX,XX +XXX,XX @@ static void omap_i2c_write(void *opaque, hwaddr addr,
46
s->stat |= 0x3f;
47
omap_i2c_interrupts_update(s);
48
}
49
- if (value & (1 << 15))                    /* ST_EN */
50
- fprintf(stderr, "%s: System Test not supported\n", __func__);
51
+ if (value & (1 << 15)) { /* ST_EN */
52
+ qemu_log_mask(LOG_UNIMP,
53
+ "%s: System Test not supported\n", __func__);
54
+ }
55
break;
56
57
default:
58
--
59
2.17.1
60
61
diff view generated by jsdifflib
1
From: Pekka Enberg <penberg@iki.fi>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
This patch adds a "raspi3" machine type, which can now be selected as
3
TCMI_VERBOSE is no more used, drop the OMAP_8/16/32B_REG macros.
4
the machine to run on by users via the "-M" command line option to QEMU.
5
4
6
The machine type does *not* ignore memory transaction failures so we
5
Suggested-by: Thomas Huth <thuth@redhat.com>
7
likely need to add some dummy devices later when people run something
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
more complicated than what I'm using for testing.
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
9
8
Message-id: 20180624040609.17572-9-f4bug@amsat.org
10
Signed-off-by: Pekka Enberg <penberg@iki.fi>
11
[PMM: added #ifdef TARGET_AARCH64 so we don't provide the 64-bit
12
board in the 32-bit only arm-softmmu build.]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/arm/raspi.c | 23 +++++++++++++++++++++++
11
include/hw/arm/omap.h | 18 ------------------
18
1 file changed, 23 insertions(+)
12
hw/arm/omap1.c | 18 ++++++++++++------
13
2 files changed, 12 insertions(+), 24 deletions(-)
19
14
20
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
15
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/raspi.c
17
--- a/include/hw/arm/omap.h
23
+++ b/hw/arm/raspi.c
18
+++ b/include/hw/arm/omap.h
24
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
19
@@ -XXX,XX +XXX,XX @@ enum {
25
mc->ignore_memory_transaction_failures = true;
20
#define OMAP_GPIOSW_INVERTED    0x0001
26
};
21
#define OMAP_GPIOSW_OUTPUT    0x0002
27
DEFINE_MACHINE("raspi2", raspi2_machine_init)
22
28
+
23
-# define TCMI_VERBOSE            1
29
+#ifdef TARGET_AARCH64
24
-
30
+static void raspi3_init(MachineState *machine)
25
-# ifdef TCMI_VERBOSE
26
-# define OMAP_8B_REG(paddr)        \
27
- fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n",    \
28
- __func__, paddr)
29
-# define OMAP_16B_REG(paddr)        \
30
- fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n",    \
31
- __func__, paddr)
32
-# define OMAP_32B_REG(paddr)        \
33
- fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n",    \
34
- __func__, paddr)
35
-# else
36
-# define OMAP_8B_REG(paddr)
37
-# define OMAP_16B_REG(paddr)
38
-# define OMAP_32B_REG(paddr)
39
-# endif
40
-
41
# define OMAP_MPUI_REG_MASK        0x000007ff
42
43
#endif /* hw_omap_h */
44
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/omap1.c
47
+++ b/hw/arm/omap1.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "qemu/cutils.h"
50
#include "qemu/bcd.h"
51
52
+static inline void omap_log_badwidth(const char *funcname, hwaddr addr, int sz)
31
+{
53
+{
32
+ raspi_init(machine, 3);
54
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: %d-bit register %#08" HWADDR_PRIx "\n",
55
+ funcname, 8 * sz, addr);
33
+}
56
+}
34
+
57
+
35
+static void raspi3_machine_init(MachineClass *mc)
58
/* Should signal the TCMI/GPMC */
36
+{
59
uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
37
+ mc->desc = "Raspberry Pi 3";
60
{
38
+ mc->init = raspi3_init;
61
uint8_t ret;
39
+ mc->block_default_type = IF_SD;
62
40
+ mc->no_parallel = 1;
63
- OMAP_8B_REG(addr);
41
+ mc->no_floppy = 1;
64
+ omap_log_badwidth(__func__, addr, 1);
42
+ mc->no_cdrom = 1;
65
cpu_physical_memory_read(addr, &ret, 1);
43
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
66
return ret;
44
+ mc->max_cpus = BCM2836_NCPUS;
67
}
45
+ mc->min_cpus = BCM2836_NCPUS;
68
@@ -XXX,XX +XXX,XX @@ void omap_badwidth_write8(void *opaque, hwaddr addr,
46
+ mc->default_cpus = BCM2836_NCPUS;
69
{
47
+ mc->default_ram_size = 1024 * 1024 * 1024;
70
uint8_t val8 = value;
48
+}
71
49
+DEFINE_MACHINE("raspi3", raspi3_machine_init)
72
- OMAP_8B_REG(addr);
50
+#endif
73
+ omap_log_badwidth(__func__, addr, 1);
74
cpu_physical_memory_write(addr, &val8, 1);
75
}
76
77
@@ -XXX,XX +XXX,XX @@ uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
78
{
79
uint16_t ret;
80
81
- OMAP_16B_REG(addr);
82
+ omap_log_badwidth(__func__, addr, 2);
83
cpu_physical_memory_read(addr, &ret, 2);
84
return ret;
85
}
86
@@ -XXX,XX +XXX,XX @@ void omap_badwidth_write16(void *opaque, hwaddr addr,
87
{
88
uint16_t val16 = value;
89
90
- OMAP_16B_REG(addr);
91
+ omap_log_badwidth(__func__, addr, 2);
92
cpu_physical_memory_write(addr, &val16, 2);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
96
{
97
uint32_t ret;
98
99
- OMAP_32B_REG(addr);
100
+ omap_log_badwidth(__func__, addr, 4);
101
cpu_physical_memory_read(addr, &ret, 4);
102
return ret;
103
}
104
@@ -XXX,XX +XXX,XX @@ uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
105
void omap_badwidth_write32(void *opaque, hwaddr addr,
106
uint32_t value)
107
{
108
- OMAP_32B_REG(addr);
109
+ omap_log_badwidth(__func__, addr, 4);
110
cpu_physical_memory_write(addr, &value, 4);
111
}
112
51
--
113
--
52
2.16.1
114
2.17.1
53
115
54
116
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-10-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
include/hw/arm/omap.h | 12 ++++++------
9
1 file changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/hw/arm/omap.h
14
+++ b/include/hw/arm/omap.h
15
@@ -XXX,XX +XXX,XX @@
16
# define hw_omap_h        "omap.h"
17
#include "hw/irq.h"
18
#include "target/arm/cpu-qom.h"
19
+#include "qemu/log.h"
20
21
# define OMAP_EMIFS_BASE    0x00000000
22
# define OMAP2_Q0_BASE        0x00000000
23
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
24
unsigned long sdram_size,
25
const char *core);
26
27
-#define OMAP_FMT_plx "%#08" HWADDR_PRIx
28
-
29
uint32_t omap_badwidth_read8(void *opaque, hwaddr addr);
30
void omap_badwidth_write8(void *opaque, hwaddr addr,
31
uint32_t value);
32
@@ -XXX,XX +XXX,XX @@ void omap_badwidth_write32(void *opaque, hwaddr addr,
33
void omap_mpu_wakeup(void *opaque, int irq, int req);
34
35
# define OMAP_BAD_REG(paddr)        \
36
- fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n",    \
37
- __func__, paddr)
38
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad register %#08"HWADDR_PRIx"\n", \
39
+ __func__, paddr)
40
# define OMAP_RO_REG(paddr)        \
41
- fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n",    \
42
- __func__, paddr)
43
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Read-only register %#08" \
44
+ HWADDR_PRIx "\n", \
45
+ __func__, paddr)
46
47
/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
48
(Board-specifc tags are not here) */
49
--
50
2.17.1
51
52
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-11-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/stellaris.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/stellaris.c
14
+++ b/hw/arm/stellaris.c
15
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
16
case 0x040: /* SRCR0 */
17
case 0x044: /* SRCR1 */
18
case 0x048: /* SRCR2 */
19
- fprintf(stderr, "Peripheral reset not implemented\n");
20
+ qemu_log_mask(LOG_UNIMP, "Peripheral reset not implemented\n");
21
break;
22
case 0x054: /* IMC */
23
s->int_mask = value & 0x7f;
24
--
25
2.17.1
26
27
diff view generated by jsdifflib
1
In commit commit 3b2e934463121 we added support for the AIRCR
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
register holding state, but forgot to add it to the vmstate
3
structs. Since it only holds r/w state if the security extension
4
is implemented, we can just add it to vmstate_m_security.
5
2
3
Suggested-by: Thomas Huth <thuth@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20180624040609.17572-12-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180209165810.6668-10-peter.maydell@linaro.org
9
---
7
---
10
target/arm/machine.c | 4 ++++
8
hw/net/stellaris_enet.c | 2 +-
11
1 file changed, 4 insertions(+)
9
1 file changed, 1 insertion(+), 1 deletion(-)
12
10
13
diff --git a/target/arm/machine.c b/target/arm/machine.c
11
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/machine.c
13
--- a/hw/net/stellaris_enet.c
16
+++ b/target/arm/machine.c
14
+++ b/hw/net/stellaris_enet.c
17
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
15
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
18
VMSTATE_VALIDATE("SAU_RNR is valid", sau_rnr_vmstate_validate),
16
return s->np;
19
VMSTATE_UINT32(env.sau.ctrl, ARMCPU),
17
case 0x38: /* TR */
20
VMSTATE_UINT32(env.v7m.scr[M_REG_S], ARMCPU),
18
return 0;
21
+ /* AIRCR is not secure-only, but our implementation is R/O if the
19
- case 0x3c: /* Undocuented: Timestamp? */
22
+ * security extension is unimplemented, so we migrate it here.
20
+ case 0x3c: /* Undocumented: Timestamp? */
23
+ */
21
return 0;
24
+ VMSTATE_UINT32(env.v7m.aircr, ARMCPU),
22
default:
25
VMSTATE_END_OF_LIST()
23
hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset);
26
}
27
};
28
--
24
--
29
2.16.1
25
2.17.1
30
26
31
27
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
When storing to an AdvSIMD FP register, all of the high
3
hw_error() finally calls abort(), but there is no need to abort here.
4
bits of the SVE register are zeroed. Therefore, call it
5
more often with is_q as a parameter.
6
4
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180211205848.4568-6-richard.henderson@linaro.org
6
Message-id: 20180624040609.17572-13-f4bug@amsat.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/translate-a64.c | 162 +++++++++++++++++----------------------------
10
hw/net/stellaris_enet.c | 9 +++++++--
13
1 file changed, 62 insertions(+), 100 deletions(-)
11
1 file changed, 7 insertions(+), 2 deletions(-)
14
12
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
13
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
15
--- a/hw/net/stellaris_enet.c
18
+++ b/target/arm/translate-a64.c
16
+++ b/hw/net/stellaris_enet.c
19
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
17
@@ -XXX,XX +XXX,XX @@
20
return v;
18
#include "qemu/osdep.h"
21
}
19
#include "hw/sysbus.h"
22
20
#include "net/net.h"
23
+/* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
21
+#include "qemu/log.h"
24
+ * If SVE is not enabled, then there are only 128 bits in the vector.
22
#include <zlib.h>
25
+ */
23
26
+static void clear_vec_high(DisasContext *s, bool is_q, int rd)
24
//#define DEBUG_STELLARIS_ENET 1
27
+{
25
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
28
+ unsigned ofs = fp_reg_offset(s, rd, MO_64);
26
case 0x3c: /* Undocumented: Timestamp? */
29
+ unsigned vsz = vec_full_reg_size(s);
27
return 0;
30
+
28
default:
31
+ if (!is_q) {
29
- hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset);
32
+ TCGv_i64 tcg_zero = tcg_const_i64(0);
30
+ qemu_log_mask(LOG_GUEST_ERROR, "stellaris_enet_rd%d: Illegal register"
33
+ tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
31
+ " 0x02%" HWADDR_PRIx "\n",
34
+ tcg_temp_free_i64(tcg_zero);
32
+ size * 8, offset);
35
+ }
33
return 0;
36
+ if (vsz > 16) {
37
+ tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0);
38
+ }
39
+}
40
+
41
static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
42
{
43
- TCGv_i64 tcg_zero = tcg_const_i64(0);
44
+ unsigned ofs = fp_reg_offset(s, reg, MO_64);
45
46
- tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
47
- tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg));
48
- tcg_temp_free_i64(tcg_zero);
49
+ tcg_gen_st_i64(v, cpu_env, ofs);
50
+ clear_vec_high(s, false, reg);
51
}
52
53
static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
54
@@ -XXX,XX +XXX,XX @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
55
56
tcg_temp_free_i64(tmplo);
57
tcg_temp_free_i64(tmphi);
58
+
59
+ clear_vec_high(s, true, destidx);
60
}
61
62
/*
63
@@ -XXX,XX +XXX,XX @@ static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
64
}
34
}
65
}
35
}
66
36
@@ -XXX,XX +XXX,XX @@ static void stellaris_enet_write(void *opaque, hwaddr offset,
67
-/* Clear the high 64 bits of a 128 bit vector (in general non-quad
37
/* Ignored. */
68
- * vector ops all need to do this).
38
break;
69
- */
39
default:
70
-static void clear_vec_high(DisasContext *s, int rd)
40
- hw_error("stellaris_enet_write: Bad offset %x\n", (int)offset);
71
-{
41
+ qemu_log_mask(LOG_GUEST_ERROR, "stellaris_enet_wr%d: Illegal register "
72
- TCGv_i64 tcg_zero = tcg_const_i64(0);
42
+ "0x02%" HWADDR_PRIx " = 0x%" PRIx64 "\n",
73
-
43
+ size * 8, offset, value);
74
- write_vec_element(s, tcg_zero, rd, 1, MO_64);
75
- tcg_temp_free_i64(tcg_zero);
76
-}
77
-
78
/* Store from vector register to memory */
79
static void do_vec_st(DisasContext *s, int srcidx, int element,
80
TCGv_i64 tcg_addr, int size)
81
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
82
/* For non-quad operations, setting a slice of the low
83
* 64 bits of the register clears the high 64 bits (in
84
* the ARM ARM pseudocode this is implicit in the fact
85
- * that 'rval' is a 64 bit wide variable). We optimize
86
- * by noticing that we only need to do this the first
87
- * time we touch a register.
88
+ * that 'rval' is a 64 bit wide variable).
89
+ * For quad operations, we might still need to zero the
90
+ * high bits of SVE. We optimize by noticing that we only
91
+ * need to do this the first time we touch a register.
92
*/
93
- if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
94
- clear_vec_high(s, tt);
95
+ if (e == 0 && (r == 0 || xs == selem - 1)) {
96
+ clear_vec_high(s, is_q, tt);
97
}
98
}
99
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
100
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
101
write_vec_element(s, tcg_tmp, rt, 0, MO_64);
102
if (is_q) {
103
write_vec_element(s, tcg_tmp, rt, 1, MO_64);
104
- } else {
105
- clear_vec_high(s, rt);
106
}
107
tcg_temp_free_i64(tcg_tmp);
108
+ clear_vec_high(s, is_q, rt);
109
} else {
110
/* Load/store one element per register */
111
if (is_load) {
112
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
113
}
114
115
if (!is_q) {
116
- clear_vec_high(s, rd);
117
write_vec_element(s, tcg_final, rd, 0, MO_64);
118
} else {
119
write_vec_element(s, tcg_final, rd, 1, MO_64);
120
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
121
tcg_temp_free_i64(tcg_rd);
122
tcg_temp_free_i32(tcg_rd_narrowed);
123
tcg_temp_free_i64(tcg_final);
124
- return;
125
+
126
+ clear_vec_high(s, is_q, rd);
127
}
128
129
/* SQSHLU, UQSHL, SQSHL: saturating left shifts */
130
@@ -XXX,XX +XXX,XX @@ static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
131
tcg_temp_free_i64(tcg_op);
132
}
133
tcg_temp_free_i64(tcg_shift);
134
-
135
- if (!is_q) {
136
- clear_vec_high(s, rd);
137
- }
138
+ clear_vec_high(s, is_q, rd);
139
} else {
140
TCGv_i32 tcg_shift = tcg_const_i32(shift);
141
static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
142
@@ -XXX,XX +XXX,XX @@ static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
143
}
144
tcg_temp_free_i32(tcg_shift);
145
146
- if (!is_q && !scalar) {
147
- clear_vec_high(s, rd);
148
+ if (!scalar) {
149
+ clear_vec_high(s, is_q, rd);
150
}
151
}
44
}
152
}
45
}
153
@@ -XXX,XX +XXX,XX @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
154
}
155
}
156
157
- if (!is_double && elements == 2) {
158
- clear_vec_high(s, rd);
159
- }
160
-
161
tcg_temp_free_i64(tcg_int);
162
tcg_temp_free_ptr(tcg_fpst);
163
tcg_temp_free_i32(tcg_shift);
164
+
165
+ clear_vec_high(s, elements << size == 16, rd);
166
}
167
168
/* UCVTF/SCVTF - Integer to FP conversion */
169
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
170
write_vec_element(s, tcg_op, rd, pass, MO_64);
171
tcg_temp_free_i64(tcg_op);
172
}
173
- if (!is_q) {
174
- clear_vec_high(s, rd);
175
- }
176
+ clear_vec_high(s, is_q, rd);
177
} else {
178
int maxpass = is_scalar ? 1 : is_q ? 4 : 2;
179
for (pass = 0; pass < maxpass; pass++) {
180
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
181
}
182
tcg_temp_free_i32(tcg_op);
183
}
184
- if (!is_q && !is_scalar) {
185
- clear_vec_high(s, rd);
186
+ if (!is_scalar) {
187
+ clear_vec_high(s, is_q, rd);
188
}
189
}
190
191
@@ -XXX,XX +XXX,XX @@ static void handle_3same_float(DisasContext *s, int size, int elements,
192
193
tcg_temp_free_ptr(fpst);
194
195
- if ((elements << size) < 4) {
196
- /* scalar, or non-quad vector op */
197
- clear_vec_high(s, rd);
198
- }
199
+ clear_vec_high(s, elements * (size ? 8 : 4) > 8, rd);
200
}
201
202
/* AdvSIMD scalar three same
203
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
204
}
205
write_vec_element(s, tcg_res, rd, pass, MO_64);
206
}
207
- if (is_scalar) {
208
- clear_vec_high(s, rd);
209
- }
210
-
211
tcg_temp_free_i64(tcg_res);
212
tcg_temp_free_i64(tcg_zero);
213
tcg_temp_free_i64(tcg_op);
214
+
215
+ clear_vec_high(s, !is_scalar, rd);
216
} else {
217
TCGv_i32 tcg_op = tcg_temp_new_i32();
218
TCGv_i32 tcg_zero = tcg_const_i32(0);
219
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
220
tcg_temp_free_i32(tcg_res);
221
tcg_temp_free_i32(tcg_zero);
222
tcg_temp_free_i32(tcg_op);
223
- if (!is_q && !is_scalar) {
224
- clear_vec_high(s, rd);
225
+ if (!is_scalar) {
226
+ clear_vec_high(s, is_q, rd);
227
}
228
}
229
230
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
231
}
232
write_vec_element(s, tcg_res, rd, pass, MO_64);
233
}
234
- if (is_scalar) {
235
- clear_vec_high(s, rd);
236
- }
237
-
238
tcg_temp_free_i64(tcg_res);
239
tcg_temp_free_i64(tcg_op);
240
+ clear_vec_high(s, !is_scalar, rd);
241
} else {
242
TCGv_i32 tcg_op = tcg_temp_new_i32();
243
TCGv_i32 tcg_res = tcg_temp_new_i32();
244
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
245
}
246
tcg_temp_free_i32(tcg_res);
247
tcg_temp_free_i32(tcg_op);
248
- if (!is_q && !is_scalar) {
249
- clear_vec_high(s, rd);
250
+ if (!is_scalar) {
251
+ clear_vec_high(s, is_q, rd);
252
}
253
}
254
tcg_temp_free_ptr(fpst);
255
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_narrow(DisasContext *s, bool scalar,
256
write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
257
tcg_temp_free_i32(tcg_res[pass]);
258
}
259
- if (!is_q) {
260
- clear_vec_high(s, rd);
261
- }
262
+ clear_vec_high(s, is_q, rd);
263
}
264
265
/* Remaining saturating accumulating ops */
266
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
267
}
268
write_vec_element(s, tcg_rd, rd, pass, MO_64);
269
}
270
- if (is_scalar) {
271
- clear_vec_high(s, rd);
272
- }
273
-
274
tcg_temp_free_i64(tcg_rd);
275
tcg_temp_free_i64(tcg_rn);
276
+ clear_vec_high(s, !is_scalar, rd);
277
} else {
278
TCGv_i32 tcg_rn = tcg_temp_new_i32();
279
TCGv_i32 tcg_rd = tcg_temp_new_i32();
280
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
281
}
282
write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
283
}
284
-
285
- if (!is_q) {
286
- clear_vec_high(s, rd);
287
- }
288
-
289
tcg_temp_free_i32(tcg_rd);
290
tcg_temp_free_i32(tcg_rn);
291
+ clear_vec_high(s, is_q, rd);
292
}
293
}
294
295
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
296
tcg_temp_free_i64(tcg_round);
297
298
done:
299
- if (!is_q) {
300
- clear_vec_high(s, rd);
301
- }
302
+ clear_vec_high(s, is_q, rd);
303
}
304
305
static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
306
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
307
}
308
309
if (!is_q) {
310
- clear_vec_high(s, rd);
311
write_vec_element(s, tcg_final, rd, 0, MO_64);
312
} else {
313
write_vec_element(s, tcg_final, rd, 1, MO_64);
314
}
315
-
316
if (round) {
317
tcg_temp_free_i64(tcg_round);
318
}
319
tcg_temp_free_i64(tcg_rn);
320
tcg_temp_free_i64(tcg_rd);
321
tcg_temp_free_i64(tcg_final);
322
- return;
323
+
324
+ clear_vec_high(s, is_q, rd);
325
}
326
327
328
@@ -XXX,XX +XXX,XX @@ static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
329
write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
330
tcg_temp_free_i32(tcg_res[pass]);
331
}
332
- if (!is_q) {
333
- clear_vec_high(s, rd);
334
- }
335
+ clear_vec_high(s, is_q, rd);
336
}
337
338
static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
339
@@ -XXX,XX +XXX,XX @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
340
write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
341
tcg_temp_free_i32(tcg_res[pass]);
342
}
343
- if (!is_q) {
344
- clear_vec_high(s, rd);
345
- }
346
+ clear_vec_high(s, is_q, rd);
347
}
348
349
if (fpst) {
350
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
351
tcg_temp_free_i32(tcg_op2);
352
}
353
}
354
-
355
- if (!is_q) {
356
- clear_vec_high(s, rd);
357
- }
358
+ clear_vec_high(s, is_q, rd);
359
}
360
361
/* AdvSIMD three same
362
@@ -XXX,XX +XXX,XX @@ static void handle_rev(DisasContext *s, int opcode, bool u,
363
write_vec_element(s, tcg_tmp, rd, i, grp_size);
364
tcg_temp_free_i64(tcg_tmp);
365
}
366
- if (!is_q) {
367
- clear_vec_high(s, rd);
368
- }
369
+ clear_vec_high(s, is_q, rd);
370
} else {
371
int revmask = (1 << grp_size) - 1;
372
int esize = 8 << size;
373
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
374
tcg_temp_free_i32(tcg_op);
375
}
376
}
377
- if (!is_q) {
378
- clear_vec_high(s, rd);
379
- }
380
+ clear_vec_high(s, is_q, rd);
381
382
if (need_rmode) {
383
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
384
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
385
tcg_temp_free_i64(tcg_res);
386
}
387
388
- if (is_scalar) {
389
- clear_vec_high(s, rd);
390
- }
391
-
392
tcg_temp_free_i64(tcg_idx);
393
+ clear_vec_high(s, !is_scalar, rd);
394
} else if (!is_long) {
395
/* 32 bit floating point, or 16 or 32 bit integer.
396
* For the 16 bit scalar case we use the usual Neon helpers and
397
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
398
}
399
400
tcg_temp_free_i32(tcg_idx);
401
-
402
- if (!is_q) {
403
- clear_vec_high(s, rd);
404
- }
405
+ clear_vec_high(s, is_q, rd);
406
} else {
407
/* long ops: 16x16->32 or 32x32->64 */
408
TCGv_i64 tcg_res[2];
409
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
410
}
411
tcg_temp_free_i64(tcg_idx);
412
413
- if (is_scalar) {
414
- clear_vec_high(s, rd);
415
- }
416
+ clear_vec_high(s, !is_scalar, rd);
417
} else {
418
TCGv_i32 tcg_idx = tcg_temp_new_i32();
419
46
420
--
47
--
421
2.16.1
48
2.17.1
422
49
423
50
diff view generated by jsdifflib
1
For M profile cores, cache maintenance operations are done by
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
writing to special registers in the system register space.
3
For QEMU, cache operations are always NOPs, since we don't
4
implement the cache. Implementing these explicitly avoids
5
a spurious LOG_GUEST_ERROR when the guest uses them.
6
2
3
hw_error() finally calls abort(), but there is no need to abort here.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20180624040609.17572-14-f4bug@amsat.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180209165810.6668-4-peter.maydell@linaro.org
10
---
9
---
11
hw/intc/armv7m_nvic.c | 12 ++++++++++++
10
hw/net/smc91c111.c | 9 +++++++--
12
1 file changed, 12 insertions(+)
11
1 file changed, 7 insertions(+), 2 deletions(-)
13
12
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
15
--- a/hw/net/smc91c111.c
17
+++ b/hw/intc/armv7m_nvic.c
16
+++ b/hw/net/smc91c111.c
18
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/sysbus.h"
19
#include "net/net.h"
20
#include "hw/devices.h"
21
+#include "qemu/log.h"
22
/* For crc32 */
23
#include <zlib.h>
24
25
@@ -XXX,XX +XXX,XX @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
19
}
26
}
20
break;
27
break;
21
}
28
}
22
+ case 0xf50: /* ICIALLU */
29
- hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset);
23
+ case 0xf58: /* ICIMVAU */
30
+ qemu_log_mask(LOG_GUEST_ERROR, "smc91c111_write(bank:%d) Illegal register"
24
+ case 0xf5c: /* DCIMVAC */
31
+ " 0x%" HWADDR_PRIx " = 0x%x\n",
25
+ case 0xf60: /* DCISW */
32
+ s->bank, offset, value);
26
+ case 0xf64: /* DCCMVAU */
33
}
27
+ case 0xf68: /* DCCMVAC */
34
28
+ case 0xf6c: /* DCCSW */
35
static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
29
+ case 0xf70: /* DCCIMVAC */
36
@@ -XXX,XX +XXX,XX @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
30
+ case 0xf74: /* DCCISW */
37
}
31
+ case 0xf78: /* BPIALL */
38
break;
32
+ /* Cache and branch predictor maintenance: for QEMU these always NOP */
39
}
33
+ break;
40
- hw_error("smc91c111_read: Bad reg %d:%x\n", s->bank, (int)offset);
34
default:
41
+ qemu_log_mask(LOG_GUEST_ERROR, "smc91c111_read(bank:%d) Illegal register"
35
bad_offset:
42
+ " 0x%" HWADDR_PRIx "\n",
36
qemu_log_mask(LOG_GUEST_ERROR,
43
+ s->bank, offset);
44
return 0;
45
}
46
37
--
47
--
38
2.16.1
48
2.17.1
39
49
40
50
diff view generated by jsdifflib
1
In many of the NVIC registers relating to interrupts, we
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
have to convert from a byte offset within a register set
3
into the number of the first interrupt which is affected.
4
We were getting this wrong for:
5
* reads of NVIC_ISPR<n>, NVIC_ISER<n>, NVIC_ICPR<n>, NVIC_ICER<n>,
6
NVIC_IABR<n> -- in all these cases we were missing the "* 8"
7
needed to convert from the byte offset to the interrupt number
8
(since all these registers use one bit per interrupt)
9
* writes of NVIC_IPR<n> had the opposite problem of a spurious
10
"* 8" (since these registers use one byte per interrupt)
11
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Message-id: 20180624040609.17572-15-f4bug@amsat.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20180209165810.6668-9-peter.maydell@linaro.org
15
---
7
---
16
hw/intc/armv7m_nvic.c | 8 ++++----
8
hw/net/smc91c111.c | 12 ++++++++----
17
1 file changed, 4 insertions(+), 4 deletions(-)
9
1 file changed, 8 insertions(+), 4 deletions(-)
18
10
19
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
11
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/armv7m_nvic.c
13
--- a/hw/net/smc91c111.c
22
+++ b/hw/intc/armv7m_nvic.c
14
+++ b/hw/net/smc91c111.c
23
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
15
@@ -XXX,XX +XXX,XX @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
24
/* fall through */
16
SET_HIGH(gpr, value);
25
case 0x180 ... 0x1bf: /* NVIC Clear enable */
17
return;
26
val = 0;
18
case 12: /* Control */
27
- startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
19
- if (value & 1)
28
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ; /* vector # */
20
- fprintf(stderr, "smc91c111:EEPROM store not implemented\n");
29
21
- if (value & 2)
30
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
22
- fprintf(stderr, "smc91c111:EEPROM reload not implemented\n");
31
if (s->vectors[startvec + i].enabled &&
23
+ if (value & 1) {
32
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
24
+ qemu_log_mask(LOG_UNIMP,
33
/* fall through */
25
+ "smc91c111: EEPROM store not implemented\n");
34
case 0x280 ... 0x2bf: /* NVIC Clear pend */
26
+ }
35
val = 0;
27
+ if (value & 2) {
36
- startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
28
+ qemu_log_mask(LOG_UNIMP,
37
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
29
+ "smc91c111: EEPROM reload not implemented\n");
38
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
30
+ }
39
if (s->vectors[startvec + i].pending &&
31
value &= ~3;
40
(attrs.secure || s->itns[startvec + i])) {
32
SET_LOW(ctr, value);
41
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
33
return;
42
break;
43
case 0x300 ... 0x33f: /* NVIC Active */
44
val = 0;
45
- startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
46
+ startvec = 8 * (offset - 0x300) + NVIC_FIRST_IRQ; /* vector # */
47
48
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
49
if (s->vectors[startvec + i].active &&
50
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
51
case 0x300 ... 0x33f: /* NVIC Active */
52
return MEMTX_OK; /* R/O */
53
case 0x400 ... 0x5ef: /* NVIC Priority */
54
- startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
55
+ startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
56
57
for (i = 0; i < size && startvec + i < s->num_irq; i++) {
58
if (attrs.secure || s->itns[startvec + i]) {
59
--
34
--
60
2.16.1
35
2.17.1
61
36
62
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Nothing in either register affects the TB.
3
Missed in df3692e04b2.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20180211205848.4568-4-richard.henderson@linaro.org
6
Message-id: 20180624040609.17572-16-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/helper.c | 4 ++--
10
hw/arm/stellaris.c | 2 +-
11
1 file changed, 2 insertions(+), 2 deletions(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
15
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/helper.c
16
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
17
@@ -XXX,XX +XXX,XX @@ static void gptm_write(void *opaque, hwaddr offset,
18
.writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
18
break;
19
{ .name = "FPCR", .state = ARM_CP_STATE_AA64,
19
default:
20
.opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
20
qemu_log_mask(LOG_GUEST_ERROR,
21
- .access = PL0_RW, .type = ARM_CP_FPU,
21
- "GPTM: read at bad offset 0x%x\n", (int)offset);
22
+ .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END,
22
+ "GPTM: write at bad offset 0x%x\n", (int)offset);
23
.readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
23
}
24
{ .name = "FPSR", .state = ARM_CP_STATE_AA64,
24
gptm_update_irq(s);
25
.opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
25
}
26
- .access = PL0_RW, .type = ARM_CP_FPU,
27
+ .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END,
28
.readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
29
{ .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
30
.opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
31
--
26
--
32
2.16.1
27
2.17.1
33
28
34
29
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Because they are ARM_CP_STATE_AA64, ARM_CP_64BIT is implied.
3
Suggested-by: Thomas Huth <thuth@redhat.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180624040609.17572-17-f4bug@amsat.org
6
Message-id: 20180211205848.4568-2-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
8
---
10
target/arm/helper.c | 8 ++++----
9
hw/arm/stellaris.c | 6 ++++--
11
1 file changed, 4 insertions(+), 4 deletions(-)
10
1 file changed, 4 insertions(+), 2 deletions(-)
12
11
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
14
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/helper.c
15
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
16
@@ -XXX,XX +XXX,XX @@ static uint64_t gptm_read(void *opaque, hwaddr offset,
18
static const ARMCPRegInfo zcr_el1_reginfo = {
17
return 0;
19
.name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
18
default:
20
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
19
qemu_log_mask(LOG_GUEST_ERROR,
21
- .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
20
- "GPTM: read at bad offset 0x%x\n", (int)offset);
22
+ .access = PL1_RW, .accessfn = zcr_access,
21
+ "GPTM: read at bad offset 0x02%" HWADDR_PRIx "\n",
23
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
22
+ offset);
24
.writefn = zcr_write, .raw_writefn = raw_write
23
return 0;
25
};
24
}
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el1_reginfo = {
25
}
27
static const ARMCPRegInfo zcr_el2_reginfo = {
26
@@ -XXX,XX +XXX,XX @@ static void gptm_write(void *opaque, hwaddr offset,
28
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
27
break;
29
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
28
default:
30
- .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
29
qemu_log_mask(LOG_GUEST_ERROR,
31
+ .access = PL2_RW, .accessfn = zcr_access,
30
- "GPTM: write at bad offset 0x%x\n", (int)offset);
32
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
31
+ "GPTM: write at bad offset 0x02%" HWADDR_PRIx "\n",
33
.writefn = zcr_write, .raw_writefn = raw_write
32
+ offset);
34
};
33
}
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el2_reginfo = {
34
gptm_update_irq(s);
36
static const ARMCPRegInfo zcr_no_el2_reginfo = {
35
}
37
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
38
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
39
- .access = PL2_RW, .type = ARM_CP_64BIT,
40
+ .access = PL2_RW,
41
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
42
};
43
44
static const ARMCPRegInfo zcr_el3_reginfo = {
45
.name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
46
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
47
- .access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
48
+ .access = PL3_RW, .accessfn = zcr_access,
49
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
50
.writefn = zcr_write, .raw_writefn = raw_write
51
};
52
--
36
--
53
2.16.1
37
2.17.1
54
38
55
39
diff view generated by jsdifflib
1
The Coprocessor Power Control Register (CPPWR) is new in v8M.
1
Add support for MMU protection regions that are smaller than
2
It allows software to control whether coprocessors are allowed
2
TARGET_PAGE_SIZE. We do this by marking the TLB entry for those
3
to power down and lose their state. QEMU doesn't have any
3
pages with a flag TLB_RECHECK. This flag causes us to always
4
notion of power control, so we choose the IMPDEF option of
4
take the slow-path for accesses. In the slow path we can then
5
making the whole register RAZ/WI (indicating that no coprocessors
5
special case them to always call tlb_fill() again, so we have
6
can ever power down and lose state).
6
the correct information for the exact address being accessed.
7
8
This change allows us to handle reading and writing from small
9
regions; we cannot deal with execution from the small region.
7
10
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180209165810.6668-5-peter.maydell@linaro.org
13
Message-id: 20180620130619.11362-2-peter.maydell@linaro.org
11
---
14
---
12
hw/intc/armv7m_nvic.c | 14 ++++++++++++++
15
accel/tcg/softmmu_template.h | 24 ++++---
13
1 file changed, 14 insertions(+)
16
include/exec/cpu-all.h | 5 +-
14
17
accel/tcg/cputlb.c | 131 +++++++++++++++++++++++++++++------
15
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
18
3 files changed, 130 insertions(+), 30 deletions(-)
19
20
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/armv7m_nvic.c
22
--- a/accel/tcg/softmmu_template.h
18
+++ b/hw/intc/armv7m_nvic.c
23
+++ b/accel/tcg/softmmu_template.h
19
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
24
@@ -XXX,XX +XXX,XX @@
20
switch (offset) {
25
static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
21
case 4: /* Interrupt Control Type. */
26
size_t mmu_idx, size_t index,
22
return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
27
target_ulong addr,
23
+ case 0xc: /* CPPWR */
28
- uintptr_t retaddr)
24
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
29
+ uintptr_t retaddr,
25
+ goto bad_offset;
30
+ bool recheck)
31
{
32
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
33
- return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, DATA_SIZE);
34
+ return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, recheck,
35
+ DATA_SIZE);
36
}
37
#endif
38
39
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
40
41
/* ??? Note that the io helpers always read data in the target
42
byte ordering. We should push the LE/BE request down into io. */
43
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr);
44
+ res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
45
+ tlb_addr & TLB_RECHECK);
46
res = TGT_LE(res);
47
return res;
48
}
49
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
50
51
/* ??? Note that the io helpers always read data in the target
52
byte ordering. We should push the LE/BE request down into io. */
53
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr);
54
+ res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
55
+ tlb_addr & TLB_RECHECK);
56
res = TGT_BE(res);
57
return res;
58
}
59
@@ -XXX,XX +XXX,XX @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
60
size_t mmu_idx, size_t index,
61
DATA_TYPE val,
62
target_ulong addr,
63
- uintptr_t retaddr)
64
+ uintptr_t retaddr,
65
+ bool recheck)
66
{
67
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
68
- return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, DATA_SIZE);
69
+ return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
70
+ recheck, DATA_SIZE);
71
}
72
73
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
74
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
75
/* ??? Note that the io helpers always read data in the target
76
byte ordering. We should push the LE/BE request down into io. */
77
val = TGT_LE(val);
78
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr);
79
+ glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr,
80
+ retaddr, tlb_addr & TLB_RECHECK);
81
return;
82
}
83
84
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
85
/* ??? Note that the io helpers always read data in the target
86
byte ordering. We should push the LE/BE request down into io. */
87
val = TGT_BE(val);
88
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr);
89
+ glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr,
90
+ tlb_addr & TLB_RECHECK);
91
return;
92
}
93
94
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
95
index XXXXXXX..XXXXXXX 100644
96
--- a/include/exec/cpu-all.h
97
+++ b/include/exec/cpu-all.h
98
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
99
#define TLB_NOTDIRTY (1 << (TARGET_PAGE_BITS - 2))
100
/* Set if TLB entry is an IO callback. */
101
#define TLB_MMIO (1 << (TARGET_PAGE_BITS - 3))
102
+/* Set if TLB entry must have MMU lookup repeated for every access */
103
+#define TLB_RECHECK (1 << (TARGET_PAGE_BITS - 4))
104
105
/* Use this mask to check interception with an alignment mask
106
* in a TCG backend.
107
*/
108
-#define TLB_FLAGS_MASK (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO)
109
+#define TLB_FLAGS_MASK (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO \
110
+ | TLB_RECHECK)
111
112
void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
113
void dump_opcount_info(FILE *f, fprintf_function cpu_fprintf);
114
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/accel/tcg/cputlb.c
117
+++ b/accel/tcg/cputlb.c
118
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
119
target_ulong code_address;
120
uintptr_t addend;
121
CPUTLBEntry *te, *tv, tn;
122
- hwaddr iotlb, xlat, sz;
123
+ hwaddr iotlb, xlat, sz, paddr_page;
124
+ target_ulong vaddr_page;
125
unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE;
126
int asidx = cpu_asidx_from_attrs(cpu, attrs);
127
128
assert_cpu_is_self(cpu);
129
- assert(size >= TARGET_PAGE_SIZE);
130
- if (size != TARGET_PAGE_SIZE) {
131
- tlb_add_large_page(env, vaddr, size);
132
- }
133
134
- sz = size;
135
- section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz,
136
- attrs, &prot);
137
+ if (size < TARGET_PAGE_SIZE) {
138
+ sz = TARGET_PAGE_SIZE;
139
+ } else {
140
+ if (size > TARGET_PAGE_SIZE) {
141
+ tlb_add_large_page(env, vaddr, size);
26
+ }
142
+ }
27
+ /* We make the IMPDEF choice that nothing can ever go into a
143
+ sz = size;
28
+ * non-retentive power state, which allows us to RAZ/WI this.
144
+ }
29
+ */
145
+ vaddr_page = vaddr & TARGET_PAGE_MASK;
30
+ return 0;
146
+ paddr_page = paddr & TARGET_PAGE_MASK;
31
case 0x380 ... 0x3bf: /* NVIC_ITNS<n> */
147
+
32
{
148
+ section = address_space_translate_for_iotlb(cpu, asidx, paddr_page,
33
int startvec = 8 * (offset - 0x380) + NVIC_FIRST_IRQ;
149
+ &xlat, &sz, attrs, &prot);
34
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
150
assert(sz >= TARGET_PAGE_SIZE);
35
ARMCPU *cpu = s->cpu;
151
36
152
tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
37
switch (offset) {
153
" prot=%x idx=%d\n",
38
+ case 0xc: /* CPPWR */
154
vaddr, paddr, prot, mmu_idx);
39
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
155
40
+ goto bad_offset;
156
- address = vaddr;
157
- if (!memory_region_is_ram(section->mr) && !memory_region_is_romd(section->mr)) {
158
+ address = vaddr_page;
159
+ if (size < TARGET_PAGE_SIZE) {
160
+ /*
161
+ * Slow-path the TLB entries; we will repeat the MMU check and TLB
162
+ * fill on every access.
163
+ */
164
+ address |= TLB_RECHECK;
165
+ }
166
+ if (!memory_region_is_ram(section->mr) &&
167
+ !memory_region_is_romd(section->mr)) {
168
/* IO memory case */
169
address |= TLB_MMIO;
170
addend = 0;
171
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
172
}
173
174
code_address = address;
175
- iotlb = memory_region_section_get_iotlb(cpu, section, vaddr, paddr, xlat,
176
- prot, &address);
177
+ iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
178
+ paddr_page, xlat, prot, &address);
179
180
- index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
181
+ index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
182
te = &env->tlb_table[mmu_idx][index];
183
/* do not discard the translation in te, evict it into a victim tlb */
184
tv = &env->tlb_v_table[mmu_idx][vidx];
185
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
186
* TARGET_PAGE_BITS, and either
187
* + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or ROM)
188
* + the offset within section->mr of the page base (otherwise)
189
- * We subtract the vaddr (which is page aligned and thus won't
190
+ * We subtract the vaddr_page (which is page aligned and thus won't
191
* disturb the low bits) to give an offset which can be added to the
192
* (non-page-aligned) vaddr of the eventual memory access to get
193
* the MemoryRegion offset for the access. Note that the vaddr we
194
* subtract here is that of the page base, and not the same as the
195
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
196
*/
197
- env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
198
+ env->iotlb[mmu_idx][index].addr = iotlb - vaddr_page;
199
env->iotlb[mmu_idx][index].attrs = attrs;
200
201
/* Now calculate the new entry */
202
- tn.addend = addend - vaddr;
203
+ tn.addend = addend - vaddr_page;
204
if (prot & PAGE_READ) {
205
tn.addr_read = address;
206
} else {
207
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
208
tn.addr_write = address | TLB_MMIO;
209
} else if (memory_region_is_ram(section->mr)
210
&& cpu_physical_memory_is_clean(
211
- memory_region_get_ram_addr(section->mr) + xlat)) {
212
+ memory_region_get_ram_addr(section->mr) + xlat)) {
213
tn.addr_write = address | TLB_NOTDIRTY;
214
} else {
215
tn.addr_write = address;
216
@@ -XXX,XX +XXX,XX @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
217
218
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
219
int mmu_idx,
220
- target_ulong addr, uintptr_t retaddr, int size)
221
+ target_ulong addr, uintptr_t retaddr,
222
+ bool recheck, int size)
223
{
224
CPUState *cpu = ENV_GET_CPU(env);
225
hwaddr mr_offset;
226
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
227
bool locked = false;
228
MemTxResult r;
229
230
+ if (recheck) {
231
+ /*
232
+ * This is a TLB_RECHECK access, where the MMU protection
233
+ * covers a smaller range than a target page, and we must
234
+ * repeat the MMU check here. This tlb_fill() call might
235
+ * longjump out if this access should cause a guest exception.
236
+ */
237
+ int index;
238
+ target_ulong tlb_addr;
239
+
240
+ tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
241
+
242
+ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
243
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
244
+ if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
245
+ /* RAM access */
246
+ uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
247
+
248
+ return ldn_p((void *)haddr, size);
41
+ }
249
+ }
42
+ /* Make the IMPDEF choice to RAZ/WI this. */
250
+ /* Fall through for handling IO accesses */
43
+ break;
251
+ }
44
case 0x380 ... 0x3bf: /* NVIC_ITNS<n> */
252
+
45
{
253
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
46
int startvec = 8 * (offset - 0x380) + NVIC_FIRST_IRQ;
254
mr = section->mr;
255
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
256
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
257
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
258
int mmu_idx,
259
uint64_t val, target_ulong addr,
260
- uintptr_t retaddr, int size)
261
+ uintptr_t retaddr, bool recheck, int size)
262
{
263
CPUState *cpu = ENV_GET_CPU(env);
264
hwaddr mr_offset;
265
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
266
bool locked = false;
267
MemTxResult r;
268
269
+ if (recheck) {
270
+ /*
271
+ * This is a TLB_RECHECK access, where the MMU protection
272
+ * covers a smaller range than a target page, and we must
273
+ * repeat the MMU check here. This tlb_fill() call might
274
+ * longjump out if this access should cause a guest exception.
275
+ */
276
+ int index;
277
+ target_ulong tlb_addr;
278
+
279
+ tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
280
+
281
+ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
282
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
283
+ if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
284
+ /* RAM access */
285
+ uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
286
+
287
+ stn_p((void *)haddr, size, val);
288
+ return;
289
+ }
290
+ /* Fall through for handling IO accesses */
291
+ }
292
+
293
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
294
mr = section->mr;
295
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
296
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
297
tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
298
}
299
}
300
+
301
+ if (unlikely(env->tlb_table[mmu_idx][index].addr_code & TLB_RECHECK)) {
302
+ /*
303
+ * This is a TLB_RECHECK access, where the MMU protection
304
+ * covers a smaller range than a target page, and we must
305
+ * repeat the MMU check here. This tlb_fill() call might
306
+ * longjump out if this access should cause a guest exception.
307
+ */
308
+ int index;
309
+ target_ulong tlb_addr;
310
+
311
+ tlb_fill(cpu, addr, 0, MMU_INST_FETCH, mmu_idx, 0);
312
+
313
+ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
314
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_code;
315
+ if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
316
+ /* RAM access. We can't handle this, so for now just stop */
317
+ cpu_abort(cpu, "Unable to handle guest executing from RAM within "
318
+ "a small MPU region at 0x" TARGET_FMT_lx, addr);
319
+ }
320
+ /*
321
+ * Fall through to handle IO accesses (which will almost certainly
322
+ * also result in failure)
323
+ */
324
+ }
325
+
326
iotlbentry = &env->iotlb[mmu_idx][index];
327
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
328
mr = section->mr;
329
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
330
tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
331
}
332
333
- /* Notice an IO access */
334
- if (unlikely(tlb_addr & TLB_MMIO)) {
335
+ /* Notice an IO access or a needs-MMU-lookup access */
336
+ if (unlikely(tlb_addr & (TLB_MMIO | TLB_RECHECK))) {
337
/* There's really nothing that can be done to
338
support this apart from stop-the-world. */
339
goto stop_the_world;
47
--
340
--
48
2.16.1
341
2.17.1
49
342
50
343
diff view generated by jsdifflib
1
The v8M architecture includes hardware support for enforcing
1
We want to handle small MPU region sizes for ARMv7M. To do this,
2
stack pointer limits. We don't implement this behaviour yet,
2
make get_phys_addr_pmsav7() set the page size to the region
3
but provide the MSPLIM and PSPLIM stack pointer limit registers
3
size if it is less that TARGET_PAGE_SIZE, rather than working
4
as reads-as-written, so that when we do implement the checks
4
only in TARGET_PAGE_SIZE chunks.
5
in future this won't break guest migration.
5
6
Since the core TCG code con't handle execution from small
7
MPU regions, we strip the exec permission from them so that
8
any execution attempts will cause an MPU exception, rather
9
than allowing it to end up with a cpu_abort() in
10
get_page_addr_code().
11
12
(The previous code's intention was to make any small page be
13
treated as having no permissions, but unfortunately errors
14
in the implementation meant that it didn't behave that way.
15
It's possible that some binaries using small regions were
16
accidentally working with our old behaviour and won't now.)
6
17
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180209165810.6668-12-peter.maydell@linaro.org
20
Message-id: 20180620130619.11362-3-peter.maydell@linaro.org
10
---
21
---
11
target/arm/cpu.h | 2 ++
22
target/arm/helper.c | 37 ++++++++++++++++++++++++++-----------
12
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
23
1 file changed, 26 insertions(+), 11 deletions(-)
13
target/arm/machine.c | 21 +++++++++++++++++++++
14
3 files changed, 69 insertions(+)
15
24
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
21
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
22
uint32_t csselr[M_REG_NUM_BANKS];
23
uint32_t scr[M_REG_NUM_BANKS];
24
+ uint32_t msplim[M_REG_NUM_BANKS];
25
+ uint32_t psplim[M_REG_NUM_BANKS];
26
} v7m;
27
28
/* Information associated with an exception about to be taken:
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper.c
27
--- a/target/arm/helper.c
32
+++ b/target/arm/helper.c
28
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
29
@@ -XXX,XX +XXX,XX @@ static inline bool m_is_system_region(CPUARMState *env, uint32_t address)
34
return 0;
30
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
31
MMUAccessType access_type, ARMMMUIdx mmu_idx,
32
hwaddr *phys_ptr, int *prot,
33
+ target_ulong *page_size,
34
ARMMMUFaultInfo *fi)
35
{
36
ARMCPU *cpu = arm_env_get_cpu(env);
37
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
38
bool is_user = regime_is_user(env, mmu_idx);
39
40
*phys_ptr = address;
41
+ *page_size = TARGET_PAGE_SIZE;
42
*prot = 0;
43
44
if (regime_translation_disabled(env, mmu_idx) ||
45
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
46
rsize++;
47
}
35
}
48
}
36
return env->v7m.other_ss_psp;
49
- if (rsize < TARGET_PAGE_BITS) {
37
+ case 0x8a: /* MSPLIM_NS */
50
- qemu_log_mask(LOG_UNIMP,
38
+ if (!env->v7m.secure) {
51
- "DRSR[%d]: No support for MPU (sub)region size of"
39
+ return 0;
52
- " %" PRIu32 " bytes. Minimum is %d.\n",
53
- n, (1 << rsize), TARGET_PAGE_SIZE);
54
- continue;
55
- }
56
if (srdis) {
57
continue;
58
}
59
+ if (rsize < TARGET_PAGE_BITS) {
60
+ *page_size = 1 << rsize;
40
+ }
61
+ }
41
+ return env->v7m.msplim[M_REG_NS];
62
break;
42
+ case 0x8b: /* PSPLIM_NS */
63
}
43
+ if (!env->v7m.secure) {
64
44
+ return 0;
65
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
45
+ }
66
46
+ return env->v7m.psplim[M_REG_NS];
67
fi->type = ARMFault_Permission;
47
case 0x90: /* PRIMASK_NS */
68
fi->level = 1;
48
if (!env->v7m.secure) {
69
+ /*
49
return 0;
70
+ * Core QEMU code can't handle execution from small pages yet, so
50
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
71
+ * don't try it. This way we'll get an MPU exception, rather than
51
return v7m_using_psp(env) ? env->v7m.other_sp : env->regs[13];
72
+ * eventually causing QEMU to exit in get_page_addr_code().
52
case 9: /* PSP */
73
+ */
53
return v7m_using_psp(env) ? env->regs[13] : env->v7m.other_sp;
74
+ if (*page_size < TARGET_PAGE_SIZE && (*prot & PAGE_EXEC)) {
54
+ case 10: /* MSPLIM */
75
+ qemu_log_mask(LOG_UNIMP,
55
+ if (!arm_feature(env, ARM_FEATURE_V8)) {
76
+ "MPU: No support for execution from regions "
56
+ goto bad_reg;
77
+ "smaller than 1K\n");
78
+ *prot &= ~PAGE_EXEC;
79
+ }
80
return !(*prot & (1 << access_type));
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
84
} else if (arm_feature(env, ARM_FEATURE_V7)) {
85
/* PMSAv7 */
86
ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
87
- phys_ptr, prot, fi);
88
+ phys_ptr, prot, page_size, fi);
89
} else {
90
/* Pre-v7 MPU */
91
ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
92
@@ -XXX,XX +XXX,XX @@ bool arm_tlb_fill(CPUState *cs, vaddr address,
93
core_to_arm_mmu_idx(env, mmu_idx), &phys_addr,
94
&attrs, &prot, &page_size, fi, NULL);
95
if (!ret) {
96
- /* Map a single [sub]page. */
97
- phys_addr &= TARGET_PAGE_MASK;
98
- address &= TARGET_PAGE_MASK;
99
+ /*
100
+ * Map a single [sub]page. Regions smaller than our declared
101
+ * target page size are handled specially, so for those we
102
+ * pass in the exact addresses.
103
+ */
104
+ if (page_size >= TARGET_PAGE_SIZE) {
105
+ phys_addr &= TARGET_PAGE_MASK;
106
+ address &= TARGET_PAGE_MASK;
57
+ }
107
+ }
58
+ return env->v7m.msplim[env->v7m.secure];
108
tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
59
+ case 11: /* PSPLIM */
109
prot, mmu_idx, page_size);
60
+ if (!arm_feature(env, ARM_FEATURE_V8)) {
61
+ goto bad_reg;
62
+ }
63
+ return env->v7m.psplim[env->v7m.secure];
64
case 16: /* PRIMASK */
65
return env->v7m.primask[env->v7m.secure];
66
case 17: /* BASEPRI */
67
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
68
case 19: /* FAULTMASK */
69
return env->v7m.faultmask[env->v7m.secure];
70
default:
71
+ bad_reg:
72
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
73
" register %d\n", reg);
74
return 0;
110
return 0;
75
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
76
}
77
env->v7m.other_ss_psp = val;
78
return;
79
+ case 0x8a: /* MSPLIM_NS */
80
+ if (!env->v7m.secure) {
81
+ return;
82
+ }
83
+ env->v7m.msplim[M_REG_NS] = val & ~7;
84
+ return;
85
+ case 0x8b: /* PSPLIM_NS */
86
+ if (!env->v7m.secure) {
87
+ return;
88
+ }
89
+ env->v7m.psplim[M_REG_NS] = val & ~7;
90
+ return;
91
case 0x90: /* PRIMASK_NS */
92
if (!env->v7m.secure) {
93
return;
94
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
95
env->v7m.other_sp = val;
96
}
97
break;
98
+ case 10: /* MSPLIM */
99
+ if (!arm_feature(env, ARM_FEATURE_V8)) {
100
+ goto bad_reg;
101
+ }
102
+ env->v7m.msplim[env->v7m.secure] = val & ~7;
103
+ break;
104
+ case 11: /* PSPLIM */
105
+ if (!arm_feature(env, ARM_FEATURE_V8)) {
106
+ goto bad_reg;
107
+ }
108
+ env->v7m.psplim[env->v7m.secure] = val & ~7;
109
+ break;
110
case 16: /* PRIMASK */
111
env->v7m.primask[env->v7m.secure] = val & 1;
112
break;
113
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
114
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
115
break;
116
default:
117
+ bad_reg:
118
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
119
" register %d\n", reg);
120
return;
121
diff --git a/target/arm/machine.c b/target/arm/machine.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/target/arm/machine.c
124
+++ b/target/arm/machine.c
125
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_other_sp = {
126
}
127
};
128
129
+static bool m_v8m_needed(void *opaque)
130
+{
131
+ ARMCPU *cpu = opaque;
132
+ CPUARMState *env = &cpu->env;
133
+
134
+ return arm_feature(env, ARM_FEATURE_M) && arm_feature(env, ARM_FEATURE_V8);
135
+}
136
+
137
+static const VMStateDescription vmstate_m_v8m = {
138
+ .name = "cpu/m/v8m",
139
+ .version_id = 1,
140
+ .minimum_version_id = 1,
141
+ .needed = m_v8m_needed,
142
+ .fields = (VMStateField[]) {
143
+ VMSTATE_UINT32_ARRAY(env.v7m.msplim, ARMCPU, M_REG_NUM_BANKS),
144
+ VMSTATE_UINT32_ARRAY(env.v7m.psplim, ARMCPU, M_REG_NUM_BANKS),
145
+ VMSTATE_END_OF_LIST()
146
+ }
147
+};
148
+
149
static const VMStateDescription vmstate_m = {
150
.name = "cpu/m",
151
.version_id = 4,
152
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
153
&vmstate_m_csselr,
154
&vmstate_m_scr,
155
&vmstate_m_other_sp,
156
+ &vmstate_m_v8m,
157
NULL
158
}
159
};
160
--
111
--
161
2.16.1
112
2.17.1
162
113
163
114
diff view generated by jsdifflib
1
In commit 50f11062d4c896 we added support for MSR/MRS access
1
Allow ARMv8M to handle small MPU and SAU region sizes, by making
2
to the NS banked special registers, but we forgot to implement
2
get_phys_add_pmsav8() set the page size to the 1 if the MPU or
3
the support for writing to CONTROL_NS. Correct the omission.
3
SAU region covers less than a TARGET_PAGE_SIZE.
4
5
We choose to use a size of 1 because it makes no difference to
6
the core code, and avoids having to track both the base and
7
limit for SAU and MPU and then convert into an artificially
8
restricted "page size" that the core code will then ignore.
9
10
Since the core TCG code can't handle execution from small
11
MPU regions, we strip the exec permission from them so that
12
any execution attempts will cause an MPU exception, rather
13
than allowing it to end up with a cpu_abort() in
14
get_page_addr_code().
15
16
(The previous code's intention was to make any small page be
17
treated as having no permissions, but unfortunately errors
18
in the implementation meant that it didn't behave that way.
19
It's possible that some binaries using small regions were
20
accidentally working with our old behaviour and won't now.)
21
22
We also retain an existing bug, where we ignored the possibility
23
that the SAU region might not cover the entire page, in the
24
case of executable regions. This is necessary because some
25
currently-working guest code images rely on being able to
26
execute from addresses which are covered by a page-sized
27
MPU region but a smaller SAU region. We can remove this
28
workaround if we ever support execution from small regions.
4
29
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180209165810.6668-8-peter.maydell@linaro.org
32
Message-id: 20180620130619.11362-4-peter.maydell@linaro.org
8
---
33
---
9
target/arm/helper.c | 10 ++++++++++
34
target/arm/helper.c | 78 ++++++++++++++++++++++++++++++++-------------
10
1 file changed, 10 insertions(+)
35
1 file changed, 55 insertions(+), 23 deletions(-)
11
36
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
37
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
39
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
40
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
41
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
42
43
/* Security attributes for an address, as returned by v8m_security_lookup. */
44
typedef struct V8M_SAttributes {
45
+ bool subpage; /* true if these attrs don't cover the whole TARGET_PAGE */
46
bool ns;
47
bool nsc;
48
uint8_t sregion;
49
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
50
int r;
51
bool idau_exempt = false, idau_ns = true, idau_nsc = true;
52
int idau_region = IREGION_NOTVALID;
53
+ uint32_t addr_page_base = address & TARGET_PAGE_MASK;
54
+ uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
55
56
if (cpu->idau) {
57
IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
58
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
59
uint32_t limit = env->sau.rlar[r] | 0x1f;
60
61
if (base <= address && limit >= address) {
62
+ if (base > addr_page_base || limit < addr_page_limit) {
63
+ sattrs->subpage = true;
64
+ }
65
if (sattrs->srvalid) {
66
/* If we hit in more than one region then we must report
67
* as Secure, not NS-Callable, with no valid region
68
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
69
static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
70
MMUAccessType access_type, ARMMMUIdx mmu_idx,
71
hwaddr *phys_ptr, MemTxAttrs *txattrs,
72
- int *prot, ARMMMUFaultInfo *fi, uint32_t *mregion)
73
+ int *prot, bool *is_subpage,
74
+ ARMMMUFaultInfo *fi, uint32_t *mregion)
75
{
76
/* Perform a PMSAv8 MPU lookup (without also doing the SAU check
77
* that a full phys-to-virt translation does).
78
* mregion is (if not NULL) set to the region number which matched,
79
* or -1 if no region number is returned (MPU off, address did not
80
* hit a region, address hit in multiple regions).
81
+ * We set is_subpage to true if the region hit doesn't cover the
82
+ * entire TARGET_PAGE the address is within.
83
*/
84
ARMCPU *cpu = arm_env_get_cpu(env);
85
bool is_user = regime_is_user(env, mmu_idx);
86
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
87
int n;
88
int matchregion = -1;
89
bool hit = false;
90
+ uint32_t addr_page_base = address & TARGET_PAGE_MASK;
91
+ uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
92
93
+ *is_subpage = false;
94
*phys_ptr = address;
95
*prot = 0;
96
if (mregion) {
97
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
98
continue;
17
}
99
}
18
env->v7m.faultmask[M_REG_NS] = val & 1;
100
19
return;
101
+ if (base > addr_page_base || limit < addr_page_limit) {
20
+ case 0x94: /* CONTROL_NS */
102
+ *is_subpage = true;
21
+ if (!env->v7m.secure) {
22
+ return;
23
+ }
103
+ }
24
+ write_v7m_control_spsel_for_secstate(env,
104
+
25
+ val & R_V7M_CONTROL_SPSEL_MASK,
105
if (hit) {
26
+ M_REG_NS);
106
/* Multiple regions match -- always a failure (unlike
27
+ env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
107
* PMSAv7 where highest-numbered-region wins)
28
+ env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
108
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
29
+ return;
109
30
case 0x98: /* SP_NS */
110
matchregion = n;
31
{
111
hit = true;
32
/* This gives the non-secure SP selected based on whether we're
112
-
113
- if (base & ~TARGET_PAGE_MASK) {
114
- qemu_log_mask(LOG_UNIMP,
115
- "MPU_RBAR[%d]: No support for MPU region base"
116
- "address of 0x%" PRIx32 ". Minimum alignment is "
117
- "%d\n",
118
- n, base, TARGET_PAGE_BITS);
119
- continue;
120
- }
121
- if ((limit + 1) & ~TARGET_PAGE_MASK) {
122
- qemu_log_mask(LOG_UNIMP,
123
- "MPU_RBAR[%d]: No support for MPU region limit"
124
- "address of 0x%" PRIx32 ". Minimum alignment is "
125
- "%d\n",
126
- n, limit, TARGET_PAGE_BITS);
127
- continue;
128
- }
129
}
130
}
131
132
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
133
134
fi->type = ARMFault_Permission;
135
fi->level = 1;
136
+ /*
137
+ * Core QEMU code can't handle execution from small pages yet, so
138
+ * don't try it. This means any attempted execution will generate
139
+ * an MPU exception, rather than eventually causing QEMU to exit in
140
+ * get_page_addr_code().
141
+ */
142
+ if (*is_subpage && (*prot & PAGE_EXEC)) {
143
+ qemu_log_mask(LOG_UNIMP,
144
+ "MPU: No support for execution from regions "
145
+ "smaller than 1K\n");
146
+ *prot &= ~PAGE_EXEC;
147
+ }
148
return !(*prot & (1 << access_type));
149
}
150
151
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
152
static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
153
MMUAccessType access_type, ARMMMUIdx mmu_idx,
154
hwaddr *phys_ptr, MemTxAttrs *txattrs,
155
- int *prot, ARMMMUFaultInfo *fi)
156
+ int *prot, target_ulong *page_size,
157
+ ARMMMUFaultInfo *fi)
158
{
159
uint32_t secure = regime_is_secure(env, mmu_idx);
160
V8M_SAttributes sattrs = {};
161
+ bool ret;
162
+ bool mpu_is_subpage;
163
164
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
165
v8m_security_lookup(env, address, access_type, mmu_idx, &sattrs);
166
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
167
} else {
168
fi->type = ARMFault_QEMU_SFault;
169
}
170
+ *page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE;
171
*phys_ptr = address;
172
*prot = 0;
173
return true;
174
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
175
* for M_FAKE_FSR_SFAULT in arm_v7m_cpu_do_interrupt().
176
*/
177
fi->type = ARMFault_QEMU_SFault;
178
+ *page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE;
179
*phys_ptr = address;
180
*prot = 0;
181
return true;
182
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
183
}
184
}
185
186
- return pmsav8_mpu_lookup(env, address, access_type, mmu_idx, phys_ptr,
187
- txattrs, prot, fi, NULL);
188
+ ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, phys_ptr,
189
+ txattrs, prot, &mpu_is_subpage, fi, NULL);
190
+ /*
191
+ * TODO: this is a temporary hack to ignore the fact that the SAU region
192
+ * is smaller than a page if this is an executable region. We never
193
+ * supported small MPU regions, but we did (accidentally) allow small
194
+ * SAU regions, and if we now made small SAU regions not be executable
195
+ * then this would break previously working guest code. We can't
196
+ * remove this until/unless we implement support for execution from
197
+ * small regions.
198
+ */
199
+ if (*prot & PAGE_EXEC) {
200
+ sattrs.subpage = false;
201
+ }
202
+ *page_size = sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE;
203
+ return ret;
204
}
205
206
static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
207
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
208
if (arm_feature(env, ARM_FEATURE_V8)) {
209
/* PMSAv8 */
210
ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx,
211
- phys_ptr, attrs, prot, fi);
212
+ phys_ptr, attrs, prot, page_size, fi);
213
} else if (arm_feature(env, ARM_FEATURE_V7)) {
214
/* PMSAv7 */
215
ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
216
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
217
uint32_t mregion;
218
bool targetpriv;
219
bool targetsec = env->v7m.secure;
220
+ bool is_subpage;
221
222
/* Work out what the security state and privilege level we're
223
* interested in is...
224
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
225
if (arm_current_el(env) != 0 || alt) {
226
/* We can ignore the return value as prot is always set */
227
pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx,
228
- &phys_addr, &attrs, &prot, &fi, &mregion);
229
+ &phys_addr, &attrs, &prot, &is_subpage,
230
+ &fi, &mregion);
231
if (mregion == -1) {
232
mrvalid = false;
233
mregion = 0;
33
--
234
--
34
2.16.1
235
2.17.1
35
236
36
237
diff view generated by jsdifflib
New patch
1
1
From: Jia He <hejianet@gmail.com>
2
3
In case the STE's config is "Bypass" we currently don't set the
4
IOMMUTLBEntry perm flags and the access does not succeed. Also
5
if the config is 0b0xx (Aborted/Reserved), decode_ste and
6
smmuv3_decode_config currently returns -EINVAL and we don't enter
7
the expected code path: we record an event whereas we should not.
8
9
This patch fixes those bugs and simplifies the error handling.
10
decode_ste and smmuv3_decode_config now return 0 if aborted or
11
bypassed config was found. Only bad config info produces negative
12
error values. In smmuv3_translate we more clearly differentiate
13
errors, bypass/smmu disabled, aborted and success cases. Also
14
trace points are differentiated.
15
16
Fixes: 9bde7f0674fe ("hw/arm/smmuv3: Implement translate callback")
17
Reported-by: jia.he@hxt-semitech.com
18
Signed-off-by: jia.he@hxt-semitech.com
19
Signed-off-by: Eric Auger <eric.auger@redhat.com>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 1529653501-15358-2-git-send-email-eric.auger@redhat.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/arm/smmuv3-internal.h | 12 ++++-
25
hw/arm/smmuv3.c | 96 +++++++++++++++++++++++++++-------------
26
hw/arm/trace-events | 7 +--
27
3 files changed, 80 insertions(+), 35 deletions(-)
28
29
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/smmuv3-internal.h
32
+++ b/hw/arm/smmuv3-internal.h
33
@@ -XXX,XX +XXX,XX @@
34
35
#include "hw/arm/smmu-common.h"
36
37
+typedef enum SMMUTranslationStatus {
38
+ SMMU_TRANS_DISABLE,
39
+ SMMU_TRANS_ABORT,
40
+ SMMU_TRANS_BYPASS,
41
+ SMMU_TRANS_ERROR,
42
+ SMMU_TRANS_SUCCESS,
43
+} SMMUTranslationStatus;
44
+
45
/* MMIO Registers */
46
47
REG32(IDR0, 0x0)
48
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
49
/* Events */
50
51
typedef enum SMMUEventType {
52
- SMMU_EVT_OK = 0x00,
53
+ SMMU_EVT_NONE = 0x00,
54
SMMU_EVT_F_UUT ,
55
SMMU_EVT_C_BAD_STREAMID ,
56
SMMU_EVT_F_STE_FETCH ,
57
@@ -XXX,XX +XXX,XX @@ typedef enum SMMUEventType {
58
} SMMUEventType;
59
60
static const char *event_stringify[] = {
61
- [SMMU_EVT_OK] = "SMMU_EVT_OK",
62
+ [SMMU_EVT_NONE] = "no recorded event",
63
[SMMU_EVT_F_UUT] = "SMMU_EVT_F_UUT",
64
[SMMU_EVT_C_BAD_STREAMID] = "SMMU_EVT_C_BAD_STREAMID",
65
[SMMU_EVT_F_STE_FETCH] = "SMMU_EVT_F_STE_FETCH",
66
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/smmuv3.c
69
+++ b/hw/arm/smmuv3.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/qdev-core.h"
72
#include "hw/pci/pci.h"
73
#include "exec/address-spaces.h"
74
+#include "cpu.h"
75
#include "trace.h"
76
#include "qemu/log.h"
77
#include "qemu/error-report.h"
78
@@ -XXX,XX +XXX,XX @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
79
EVT_SET_SID(&evt, info->sid);
80
81
switch (info->type) {
82
- case SMMU_EVT_OK:
83
+ case SMMU_EVT_NONE:
84
return;
85
case SMMU_EVT_F_UUT:
86
EVT_SET_SSID(&evt, info->u.f_uut.ssid);
87
@@ -XXX,XX +XXX,XX @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
88
return 0;
89
}
90
91
-/* Returns <0 if the caller has no need to continue the translation */
92
+/* Returns < 0 in case of invalid STE, 0 otherwise */
93
static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
94
STE *ste, SMMUEventInfo *event)
95
{
96
uint32_t config;
97
- int ret = -EINVAL;
98
99
if (!STE_VALID(ste)) {
100
goto bad_ste;
101
@@ -XXX,XX +XXX,XX @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
102
config = STE_CONFIG(ste);
103
104
if (STE_CFG_ABORT(config)) {
105
- cfg->aborted = true; /* abort but don't record any event */
106
- return ret;
107
+ cfg->aborted = true;
108
+ return 0;
109
}
110
111
if (STE_CFG_BYPASS(config)) {
112
cfg->bypassed = true;
113
- return ret;
114
+ return 0;
115
}
116
117
if (STE_CFG_S2_ENABLED(config)) {
118
@@ -XXX,XX +XXX,XX @@ bad_cd:
119
* the different configuration decoding steps
120
* @event: must be zero'ed by the caller
121
*
122
- * return < 0 if the translation needs to be aborted (@event is filled
123
+ * return < 0 in case of config decoding error (@event is filled
124
* accordingly). Return 0 otherwise.
125
*/
126
static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
127
@@ -XXX,XX +XXX,XX @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
128
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
129
uint32_t sid = smmu_get_sid(sdev);
130
SMMUv3State *s = sdev->smmu;
131
- int ret = -EINVAL;
132
+ int ret;
133
STE ste;
134
CD cd;
135
136
- if (smmu_find_ste(s, sid, &ste, event)) {
137
+ ret = smmu_find_ste(s, sid, &ste, event);
138
+ if (ret) {
139
return ret;
140
}
141
142
- if (decode_ste(s, cfg, &ste, event)) {
143
+ ret = decode_ste(s, cfg, &ste, event);
144
+ if (ret) {
145
return ret;
146
}
147
148
- if (smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event)) {
149
+ if (cfg->aborted || cfg->bypassed) {
150
+ return 0;
151
+ }
152
+
153
+ ret = smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event);
154
+ if (ret) {
155
return ret;
156
}
157
158
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
159
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
160
SMMUv3State *s = sdev->smmu;
161
uint32_t sid = smmu_get_sid(sdev);
162
- SMMUEventInfo event = {.type = SMMU_EVT_OK, .sid = sid};
163
+ SMMUEventInfo event = {.type = SMMU_EVT_NONE, .sid = sid};
164
SMMUPTWEventInfo ptw_info = {};
165
+ SMMUTranslationStatus status;
166
SMMUTransCfg cfg = {};
167
IOMMUTLBEntry entry = {
168
.target_as = &address_space_memory,
169
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
170
.addr_mask = ~(hwaddr)0,
171
.perm = IOMMU_NONE,
172
};
173
- int ret = 0;
174
175
if (!smmu_enabled(s)) {
176
- goto out;
177
+ status = SMMU_TRANS_DISABLE;
178
+ goto epilogue;
179
}
180
181
- ret = smmuv3_decode_config(mr, &cfg, &event);
182
- if (ret) {
183
- goto out;
184
+ if (smmuv3_decode_config(mr, &cfg, &event)) {
185
+ status = SMMU_TRANS_ERROR;
186
+ goto epilogue;
187
}
188
189
if (cfg.aborted) {
190
- goto out;
191
+ status = SMMU_TRANS_ABORT;
192
+ goto epilogue;
193
}
194
195
- ret = smmu_ptw(&cfg, addr, flag, &entry, &ptw_info);
196
- if (ret) {
197
+ if (cfg.bypassed) {
198
+ status = SMMU_TRANS_BYPASS;
199
+ goto epilogue;
200
+ }
201
+
202
+ if (smmu_ptw(&cfg, addr, flag, &entry, &ptw_info)) {
203
switch (ptw_info.type) {
204
case SMMU_PTW_ERR_WALK_EABT:
205
event.type = SMMU_EVT_F_WALK_EABT;
206
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
207
default:
208
g_assert_not_reached();
209
}
210
+ status = SMMU_TRANS_ERROR;
211
+ } else {
212
+ status = SMMU_TRANS_SUCCESS;
213
}
214
-out:
215
- if (ret) {
216
- qemu_log_mask(LOG_GUEST_ERROR,
217
- "%s translation failed for iova=0x%"PRIx64"(%d)\n",
218
- mr->parent_obj.name, addr, ret);
219
- entry.perm = IOMMU_NONE;
220
- smmuv3_record_event(s, &event);
221
- } else if (!cfg.aborted) {
222
+
223
+epilogue:
224
+ switch (status) {
225
+ case SMMU_TRANS_SUCCESS:
226
entry.perm = flag;
227
- trace_smmuv3_translate(mr->parent_obj.name, sid, addr,
228
- entry.translated_addr, entry.perm);
229
+ trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr,
230
+ entry.translated_addr, entry.perm);
231
+ break;
232
+ case SMMU_TRANS_DISABLE:
233
+ entry.perm = flag;
234
+ entry.addr_mask = ~TARGET_PAGE_MASK;
235
+ trace_smmuv3_translate_disable(mr->parent_obj.name, sid, addr,
236
+ entry.perm);
237
+ break;
238
+ case SMMU_TRANS_BYPASS:
239
+ entry.perm = flag;
240
+ entry.addr_mask = ~TARGET_PAGE_MASK;
241
+ trace_smmuv3_translate_bypass(mr->parent_obj.name, sid, addr,
242
+ entry.perm);
243
+ break;
244
+ case SMMU_TRANS_ABORT:
245
+ /* no event is recorded on abort */
246
+ trace_smmuv3_translate_abort(mr->parent_obj.name, sid, addr,
247
+ entry.perm);
248
+ break;
249
+ case SMMU_TRANS_ERROR:
250
+ qemu_log_mask(LOG_GUEST_ERROR,
251
+ "%s translation failed for iova=0x%"PRIx64"(%s)\n",
252
+ mr->parent_obj.name, addr, smmu_event_string(event.type));
253
+ smmuv3_record_event(s, &event);
254
+ break;
255
}
256
257
return entry;
258
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
259
index XXXXXXX..XXXXXXX 100644
260
--- a/hw/arm/trace-events
261
+++ b/hw/arm/trace-events
262
@@ -XXX,XX +XXX,XX @@ smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
263
smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
264
smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
265
smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
266
-smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass iova:0x%"PRIx64" is_write=%d"
267
-smmuv3_translate_in(uint16_t sid, int pci_bus_num, uint64_t strtab_base) "SID:0x%x bus:%d strtab_base:0x%"PRIx64
268
+smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
269
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d STE bypass iova:0x%"PRIx64" is_write=%d"
270
+smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d abort on iova:0x%"PRIx64" is_write=%d"
271
+smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
272
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
273
-smmuv3_translate(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
274
smmuv3_decode_cd(uint32_t oas) "oas=%d"
275
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d"
276
--
277
2.17.1
278
279
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
This also makes sure that we get the correct ordering of
3
Let's cache config data to avoid fetching and parsing STE/CD
4
SVE vs FP exceptions.
4
structures on each translation. We invalidate them on data structure
5
5
invalidation commands.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
7
Message-id: 20180211205848.4568-5-richard.henderson@linaro.org
7
We put in place a per-smmu mutex to protect the config cache. This
8
will be useful too to protect the IOTLB cache. The caches can be
9
accessed without BQL, ie. in IO dataplane. The same kind of mutex was
10
put in place in the intel viommu.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 1529653501-15358-3-git-send-email-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
16
---
11
target/arm/cpu.h | 3 ++-
17
include/hw/arm/smmu-common.h | 5 ++
12
target/arm/internals.h | 6 ++++++
18
include/hw/arm/smmuv3.h | 1 +
13
target/arm/helper.c | 22 ++++------------------
19
hw/arm/smmu-common.c | 24 ++++++-
14
target/arm/translate-a64.c | 16 ++++++++++++++++
20
hw/arm/smmuv3.c | 135 +++++++++++++++++++++++++++++++++--
15
4 files changed, 28 insertions(+), 19 deletions(-)
21
hw/arm/trace-events | 6 ++
16
22
5 files changed, 164 insertions(+), 7 deletions(-)
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
18
index XXXXXXX..XXXXXXX 100644
24
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
19
--- a/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
20
+++ b/target/arm/cpu.h
26
--- a/include/hw/arm/smmu-common.h
21
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
27
+++ b/include/hw/arm/smmu-common.h
22
#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
28
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUDevice {
23
#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
29
int devfn;
24
#define ARM_CP_FPU 0x1000
30
IOMMUMemoryRegion iommu;
25
+#define ARM_CP_SVE 0x2000
31
AddressSpace as;
26
/* Used only as a terminator for ARMCPRegInfo lists */
32
+ uint32_t cfg_cache_hits;
27
#define ARM_CP_SENTINEL 0xffff
33
+ uint32_t cfg_cache_misses;
28
/* Mask of only the flag bits in a type field */
34
} SMMUDevice;
29
-#define ARM_CP_FLAG_MASK 0x10ff
35
30
+#define ARM_CP_FLAG_MASK 0x30ff
36
typedef struct SMMUNotifierNode {
31
37
@@ -XXX,XX +XXX,XX @@ int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
32
/* Valid values for ARMCPRegInfo state field, indicating which of
38
*/
33
* the AArch32 and AArch64 execution states this register is visible in.
39
SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
40
35
index XXXXXXX..XXXXXXX 100644
41
+/* Return the iommu mr associated to @sid, or NULL if none */
36
--- a/target/arm/internals.h
42
+IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
37
+++ b/target/arm/internals.h
43
+
38
@@ -XXX,XX +XXX,XX @@ enum arm_exception_class {
44
#endif /* HW_ARM_SMMU_COMMON */
39
EC_AA64_HVC = 0x16,
45
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
40
EC_AA64_SMC = 0x17,
46
index XXXXXXX..XXXXXXX 100644
41
EC_SYSTEMREGISTERTRAP = 0x18,
47
--- a/include/hw/arm/smmuv3.h
42
+ EC_SVEACCESSTRAP = 0x19,
48
+++ b/include/hw/arm/smmuv3.h
43
EC_INSNABORT = 0x20,
49
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUv3State {
44
EC_INSNABORT_SAME_EL = 0x21,
50
SMMUQueue eventq, cmdq;
45
EC_PCALIGNMENT = 0x22,
51
46
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
52
qemu_irq irq[4];
47
| (cv << 24) | (cond << 20);
53
+ QemuMutex mutex;
54
} SMMUv3State;
55
56
typedef enum {
57
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/smmu-common.c
60
+++ b/hw/arm/smmu-common.c
61
@@ -XXX,XX +XXX,XX @@ static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
62
return &sdev->as;
48
}
63
}
49
64
50
+static inline uint32_t syn_sve_access_trap(void)
65
+IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
51
+{
66
+{
52
+ return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
67
+ uint8_t bus_n, devfn;
68
+ SMMUPciBus *smmu_bus;
69
+ SMMUDevice *smmu;
70
+
71
+ bus_n = PCI_BUS_NUM(sid);
72
+ smmu_bus = smmu_find_smmu_pcibus(s, bus_n);
73
+ if (smmu_bus) {
74
+ devfn = sid & 0x7;
75
+ smmu = smmu_bus->pbdev[devfn];
76
+ if (smmu) {
77
+ return &smmu->iommu;
78
+ }
79
+ }
80
+ return NULL;
53
+}
81
+}
54
+
82
+
55
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
83
static void smmu_base_realize(DeviceState *dev, Error **errp)
56
{
84
{
57
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
85
SMMUState *s = ARM_SMMU(dev);
58
diff --git a/target/arm/helper.c b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
59
index XXXXXXX..XXXXXXX 100644
87
error_propagate(errp, local_err);
60
--- a/target/arm/helper.c
88
return;
61
+++ b/target/arm/helper.c
89
}
62
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
90
-
63
return 0;
91
+ s->configs = g_hash_table_new_full(NULL, NULL, NULL, g_free);
92
s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
93
94
if (s->primary_bus) {
95
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
96
97
static void smmu_base_reset(DeviceState *dev)
98
{
99
- /* will be filled later on */
100
+ SMMUState *s = ARM_SMMU(dev);
101
+
102
+ g_hash_table_remove_all(s->configs);
64
}
103
}
65
104
66
-static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
105
static Property smmu_dev_properties[] = {
67
- bool isread)
106
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
68
-{
107
index XXXXXXX..XXXXXXX 100644
69
- switch (sve_exception_el(env)) {
108
--- a/hw/arm/smmuv3.c
70
- case 3:
109
+++ b/hw/arm/smmuv3.c
71
- return CP_ACCESS_TRAP_EL3;
110
@@ -XXX,XX +XXX,XX @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
72
- case 2:
111
return decode_cd(cfg, &cd, event);
73
- return CP_ACCESS_TRAP_EL2;
112
}
74
- case 1:
113
75
- return CP_ACCESS_TRAP;
114
+/**
76
- }
115
+ * smmuv3_get_config - Look up for a cached copy of configuration data for
77
- return CP_ACCESS_OK;
116
+ * @sdev and on cache miss performs a configuration structure decoding from
78
-}
117
+ * guest RAM.
79
-
118
+ *
80
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
119
+ * @sdev: SMMUDevice handle
81
uint64_t value)
120
+ * @event: output event info
121
+ *
122
+ * The configuration cache contains data resulting from both STE and CD
123
+ * decoding under the form of an SMMUTransCfg struct. The hash table is indexed
124
+ * by the SMMUDevice handle.
125
+ */
126
+static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *event)
127
+{
128
+ SMMUv3State *s = sdev->smmu;
129
+ SMMUState *bc = &s->smmu_state;
130
+ SMMUTransCfg *cfg;
131
+
132
+ cfg = g_hash_table_lookup(bc->configs, sdev);
133
+ if (cfg) {
134
+ sdev->cfg_cache_hits++;
135
+ trace_smmuv3_config_cache_hit(smmu_get_sid(sdev),
136
+ sdev->cfg_cache_hits, sdev->cfg_cache_misses,
137
+ 100 * sdev->cfg_cache_hits /
138
+ (sdev->cfg_cache_hits + sdev->cfg_cache_misses));
139
+ } else {
140
+ sdev->cfg_cache_misses++;
141
+ trace_smmuv3_config_cache_miss(smmu_get_sid(sdev),
142
+ sdev->cfg_cache_hits, sdev->cfg_cache_misses,
143
+ 100 * sdev->cfg_cache_hits /
144
+ (sdev->cfg_cache_hits + sdev->cfg_cache_misses));
145
+ cfg = g_new0(SMMUTransCfg, 1);
146
+
147
+ if (!smmuv3_decode_config(&sdev->iommu, cfg, event)) {
148
+ g_hash_table_insert(bc->configs, sdev, cfg);
149
+ } else {
150
+ g_free(cfg);
151
+ cfg = NULL;
152
+ }
153
+ }
154
+ return cfg;
155
+}
156
+
157
+static void smmuv3_flush_config(SMMUDevice *sdev)
158
+{
159
+ SMMUv3State *s = sdev->smmu;
160
+ SMMUState *bc = &s->smmu_state;
161
+
162
+ trace_smmuv3_config_cache_inv(smmu_get_sid(sdev));
163
+ g_hash_table_remove(bc->configs, sdev);
164
+}
165
+
166
static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
167
IOMMUAccessFlags flag, int iommu_idx)
82
{
168
{
83
@@ -XXX,XX +XXX,XX @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
169
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
84
static const ARMCPRegInfo zcr_el1_reginfo = {
170
SMMUEventInfo event = {.type = SMMU_EVT_NONE, .sid = sid};
85
.name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
171
SMMUPTWEventInfo ptw_info = {};
86
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
172
SMMUTranslationStatus status;
87
- .access = PL1_RW, .accessfn = zcr_access,
173
- SMMUTransCfg cfg = {};
88
+ .access = PL1_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
174
+ SMMUTransCfg *cfg = NULL;
89
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
175
IOMMUTLBEntry entry = {
90
.writefn = zcr_write, .raw_writefn = raw_write
176
.target_as = &address_space_memory,
91
};
177
.iova = addr,
92
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el1_reginfo = {
178
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
93
static const ARMCPRegInfo zcr_el2_reginfo = {
179
.perm = IOMMU_NONE,
94
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
180
};
95
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
181
96
- .access = PL2_RW, .accessfn = zcr_access,
182
+ qemu_mutex_lock(&s->mutex);
97
+ .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
183
+
98
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
184
if (!smmu_enabled(s)) {
99
.writefn = zcr_write, .raw_writefn = raw_write
185
status = SMMU_TRANS_DISABLE;
100
};
186
goto epilogue;
101
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el2_reginfo = {
187
}
102
static const ARMCPRegInfo zcr_no_el2_reginfo = {
188
103
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
189
- if (smmuv3_decode_config(mr, &cfg, &event)) {
104
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
190
+ cfg = smmuv3_get_config(sdev, &event);
105
- .access = PL2_RW,
191
+ if (!cfg) {
106
+ .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
192
status = SMMU_TRANS_ERROR;
107
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
193
goto epilogue;
108
};
194
}
109
195
110
static const ARMCPRegInfo zcr_el3_reginfo = {
196
- if (cfg.aborted) {
111
.name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
197
+ if (cfg->aborted) {
112
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
198
status = SMMU_TRANS_ABORT;
113
- .access = PL3_RW, .accessfn = zcr_access,
199
goto epilogue;
114
+ .access = PL3_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
200
}
115
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
201
116
.writefn = zcr_write, .raw_writefn = raw_write
202
- if (cfg.bypassed) {
117
};
203
+ if (cfg->bypassed) {
118
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
204
status = SMMU_TRANS_BYPASS;
119
index XXXXXXX..XXXXXXX 100644
205
goto epilogue;
120
--- a/target/arm/translate-a64.c
206
}
121
+++ b/target/arm/translate-a64.c
207
122
@@ -XXX,XX +XXX,XX @@ static inline bool fp_access_check(DisasContext *s)
208
- if (smmu_ptw(&cfg, addr, flag, &entry, &ptw_info)) {
123
return false;
209
+ if (smmu_ptw(cfg, addr, flag, &entry, &ptw_info)) {
124
}
210
switch (ptw_info.type) {
125
211
case SMMU_PTW_ERR_WALK_EABT:
126
+/* Check that SVE access is enabled. If it is, return true.
212
event.type = SMMU_EVT_F_WALK_EABT;
127
+ * If not, emit code to generate an appropriate exception and return false.
213
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
128
+ */
214
}
129
+static inline bool sve_access_check(DisasContext *s)
215
130
+{
216
epilogue:
131
+ if (s->sve_excp_el) {
217
+ qemu_mutex_unlock(&s->mutex);
132
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_sve_access_trap(),
218
switch (status) {
133
+ s->sve_excp_el);
219
case SMMU_TRANS_SUCCESS:
134
+ return false;
220
entry.perm = flag;
135
+ }
221
@@ -XXX,XX +XXX,XX @@ epilogue:
136
+ return true;
222
137
+}
223
static int smmuv3_cmdq_consume(SMMUv3State *s)
138
+
224
{
139
/*
225
+ SMMUState *bs = ARM_SMMU(s);
140
* This utility function is for doing register extension with an
226
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
141
* optional shift. You will likely want to pass a temporary for the
227
SMMUQueue *q = &s->cmdq;
142
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
228
SMMUCommandType type = 0;
143
default:
229
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
144
break;
230
145
}
231
trace_smmuv3_cmdq_opcode(smmu_cmd_string(type));
146
+ if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
232
147
+ return;
233
+ qemu_mutex_lock(&s->mutex);
148
+ }
234
switch (type) {
149
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
235
case SMMU_CMD_SYNC:
236
if (CMD_SYNC_CS(&cmd) & CMD_SYNC_SIG_IRQ) {
237
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
238
break;
239
case SMMU_CMD_PREFETCH_CONFIG:
240
case SMMU_CMD_PREFETCH_ADDR:
241
+ break;
242
case SMMU_CMD_CFGI_STE:
243
+ {
244
+ uint32_t sid = CMD_SID(&cmd);
245
+ IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, sid);
246
+ SMMUDevice *sdev;
247
+
248
+ if (CMD_SSEC(&cmd)) {
249
+ cmd_error = SMMU_CERROR_ILL;
250
+ break;
251
+ }
252
+
253
+ if (!mr) {
254
+ break;
255
+ }
256
+
257
+ trace_smmuv3_cmdq_cfgi_ste(sid);
258
+ sdev = container_of(mr, SMMUDevice, iommu);
259
+ smmuv3_flush_config(sdev);
260
+
261
+ break;
262
+ }
263
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
264
+ {
265
+ uint32_t start = CMD_SID(&cmd), end, i;
266
+ uint8_t range = CMD_STE_RANGE(&cmd);
267
+
268
+ if (CMD_SSEC(&cmd)) {
269
+ cmd_error = SMMU_CERROR_ILL;
270
+ break;
271
+ }
272
+
273
+ end = start + (1 << (range + 1)) - 1;
274
+ trace_smmuv3_cmdq_cfgi_ste_range(start, end);
275
+
276
+ for (i = start; i <= end; i++) {
277
+ IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
278
+ SMMUDevice *sdev;
279
+
280
+ if (!mr) {
281
+ continue;
282
+ }
283
+ sdev = container_of(mr, SMMUDevice, iommu);
284
+ smmuv3_flush_config(sdev);
285
+ }
286
+ break;
287
+ }
288
case SMMU_CMD_CFGI_CD:
289
case SMMU_CMD_CFGI_CD_ALL:
290
+ {
291
+ uint32_t sid = CMD_SID(&cmd);
292
+ IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, sid);
293
+ SMMUDevice *sdev;
294
+
295
+ if (CMD_SSEC(&cmd)) {
296
+ cmd_error = SMMU_CERROR_ILL;
297
+ break;
298
+ }
299
+
300
+ if (!mr) {
301
+ break;
302
+ }
303
+
304
+ trace_smmuv3_cmdq_cfgi_cd(sid);
305
+ sdev = container_of(mr, SMMUDevice, iommu);
306
+ smmuv3_flush_config(sdev);
307
+ break;
308
+ }
309
case SMMU_CMD_TLBI_NH_ALL:
310
case SMMU_CMD_TLBI_NH_ASID:
311
case SMMU_CMD_TLBI_NH_VA:
312
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
313
"Illegal command type: %d\n", CMD_TYPE(&cmd));
314
break;
315
}
316
+ qemu_mutex_unlock(&s->mutex);
317
if (cmd_error) {
318
break;
319
}
320
@@ -XXX,XX +XXX,XX @@ static void smmu_realize(DeviceState *d, Error **errp)
150
return;
321
return;
151
}
322
}
323
324
+ qemu_mutex_init(&s->mutex);
325
+
326
memory_region_init_io(&sys->iomem, OBJECT(s),
327
&smmu_mem_ops, sys, TYPE_ARM_SMMUV3, 0x20000);
328
329
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
330
index XXXXXXX..XXXXXXX 100644
331
--- a/hw/arm/trace-events
332
+++ b/hw/arm/trace-events
333
@@ -XXX,XX +XXX,XX @@ smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t tr
334
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
335
smmuv3_decode_cd(uint32_t oas) "oas=%d"
336
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d"
337
+smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
338
+smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
339
+smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
340
+smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
341
+smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
342
+smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
152
--
343
--
153
2.16.1
344
2.17.1
154
345
155
346
diff view generated by jsdifflib
New patch
1
1
From: Eric Auger <eric.auger@redhat.com>
2
3
We emulate a TLB cache of size SMMU_IOTLB_MAX_SIZE=256.
4
It is implemented as a hash table whose key is a combination
5
of the 16b asid and 48b IOVA (Jenkins hash).
6
7
Entries are invalidated on TLB invalidation commands, either
8
globally, or per asid, or per asid/iova.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Message-id: 1529653501-15358-4-git-send-email-eric.auger@redhat.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/hw/arm/smmu-common.h | 13 +++++
16
hw/arm/smmu-common.c | 60 ++++++++++++++++++++++
17
hw/arm/smmuv3.c | 98 ++++++++++++++++++++++++++++++++++--
18
hw/arm/trace-events | 9 ++++
19
4 files changed, 176 insertions(+), 4 deletions(-)
20
21
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/smmu-common.h
24
+++ b/include/hw/arm/smmu-common.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
26
uint8_t tbi; /* Top Byte Ignore */
27
uint16_t asid;
28
SMMUTransTableInfo tt[2];
29
+ uint32_t iotlb_hits; /* counts IOTLB hits for this asid */
30
+ uint32_t iotlb_misses; /* counts IOTLB misses for this asid */
31
} SMMUTransCfg;
32
33
typedef struct SMMUDevice {
34
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUPciBus {
35
SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
36
} SMMUPciBus;
37
38
+typedef struct SMMUIOTLBKey {
39
+ uint64_t iova;
40
+ uint16_t asid;
41
+} SMMUIOTLBKey;
42
+
43
typedef struct SMMUState {
44
/* <private> */
45
SysBusDevice dev;
46
@@ -XXX,XX +XXX,XX @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
47
/* Return the iommu mr associated to @sid, or NULL if none */
48
IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
49
50
+#define SMMU_IOTLB_MAX_SIZE 256
51
+
52
+void smmu_iotlb_inv_all(SMMUState *s);
53
+void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
54
+void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
55
+
56
#endif /* HW_ARM_SMMU_COMMON */
57
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/smmu-common.c
60
+++ b/hw/arm/smmu-common.c
61
@@ -XXX,XX +XXX,XX @@
62
#include "qom/cpu.h"
63
#include "hw/qdev-properties.h"
64
#include "qapi/error.h"
65
+#include "qemu/jhash.h"
66
67
#include "qemu/error-report.h"
68
#include "hw/arm/smmu-common.h"
69
#include "smmu-internal.h"
70
71
+/* IOTLB Management */
72
+
73
+inline void smmu_iotlb_inv_all(SMMUState *s)
74
+{
75
+ trace_smmu_iotlb_inv_all();
76
+ g_hash_table_remove_all(s->iotlb);
77
+}
78
+
79
+static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value,
80
+ gpointer user_data)
81
+{
82
+ uint16_t asid = *(uint16_t *)user_data;
83
+ SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key;
84
+
85
+ return iotlb_key->asid == asid;
86
+}
87
+
88
+inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova)
89
+{
90
+ SMMUIOTLBKey key = {.asid = asid, .iova = iova};
91
+
92
+ trace_smmu_iotlb_inv_iova(asid, iova);
93
+ g_hash_table_remove(s->iotlb, &key);
94
+}
95
+
96
+inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
97
+{
98
+ trace_smmu_iotlb_inv_asid(asid);
99
+ g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid, &asid);
100
+}
101
+
102
/* VMSAv8-64 Translation */
103
104
/**
105
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
106
return NULL;
107
}
108
109
+static guint smmu_iotlb_key_hash(gconstpointer v)
110
+{
111
+ SMMUIOTLBKey *key = (SMMUIOTLBKey *)v;
112
+ uint32_t a, b, c;
113
+
114
+ /* Jenkins hash */
115
+ a = b = c = JHASH_INITVAL + sizeof(*key);
116
+ a += key->asid;
117
+ b += extract64(key->iova, 0, 32);
118
+ c += extract64(key->iova, 32, 32);
119
+
120
+ __jhash_mix(a, b, c);
121
+ __jhash_final(a, b, c);
122
+
123
+ return c;
124
+}
125
+
126
+static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
127
+{
128
+ const SMMUIOTLBKey *k1 = v1;
129
+ const SMMUIOTLBKey *k2 = v2;
130
+
131
+ return (k1->asid == k2->asid) && (k1->iova == k2->iova);
132
+}
133
+
134
static void smmu_base_realize(DeviceState *dev, Error **errp)
135
{
136
SMMUState *s = ARM_SMMU(dev);
137
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
138
return;
139
}
140
s->configs = g_hash_table_new_full(NULL, NULL, NULL, g_free);
141
+ s->iotlb = g_hash_table_new_full(smmu_iotlb_key_hash, smmu_iotlb_key_equal,
142
+ g_free, g_free);
143
s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
144
145
if (s->primary_bus) {
146
@@ -XXX,XX +XXX,XX @@ static void smmu_base_reset(DeviceState *dev)
147
SMMUState *s = ARM_SMMU(dev);
148
149
g_hash_table_remove_all(s->configs);
150
+ g_hash_table_remove_all(s->iotlb);
151
}
152
153
static Property smmu_dev_properties[] = {
154
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/hw/arm/smmuv3.c
157
+++ b/hw/arm/smmuv3.c
158
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
159
SMMUEventInfo event = {.type = SMMU_EVT_NONE, .sid = sid};
160
SMMUPTWEventInfo ptw_info = {};
161
SMMUTranslationStatus status;
162
+ SMMUState *bs = ARM_SMMU(s);
163
+ uint64_t page_mask, aligned_addr;
164
+ IOMMUTLBEntry *cached_entry = NULL;
165
+ SMMUTransTableInfo *tt;
166
SMMUTransCfg *cfg = NULL;
167
IOMMUTLBEntry entry = {
168
.target_as = &address_space_memory,
169
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
170
.addr_mask = ~(hwaddr)0,
171
.perm = IOMMU_NONE,
172
};
173
+ SMMUIOTLBKey key, *new_key;
174
175
qemu_mutex_lock(&s->mutex);
176
177
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
178
goto epilogue;
179
}
180
181
- if (smmu_ptw(cfg, addr, flag, &entry, &ptw_info)) {
182
+ tt = select_tt(cfg, addr);
183
+ if (!tt) {
184
+ if (event.record_trans_faults) {
185
+ event.type = SMMU_EVT_F_TRANSLATION;
186
+ event.u.f_translation.addr = addr;
187
+ event.u.f_translation.rnw = flag & 0x1;
188
+ }
189
+ status = SMMU_TRANS_ERROR;
190
+ goto epilogue;
191
+ }
192
+
193
+ page_mask = (1ULL << (tt->granule_sz)) - 1;
194
+ aligned_addr = addr & ~page_mask;
195
+
196
+ key.asid = cfg->asid;
197
+ key.iova = aligned_addr;
198
+
199
+ cached_entry = g_hash_table_lookup(bs->iotlb, &key);
200
+ if (cached_entry) {
201
+ cfg->iotlb_hits++;
202
+ trace_smmu_iotlb_cache_hit(cfg->asid, aligned_addr,
203
+ cfg->iotlb_hits, cfg->iotlb_misses,
204
+ 100 * cfg->iotlb_hits /
205
+ (cfg->iotlb_hits + cfg->iotlb_misses));
206
+ if ((flag & IOMMU_WO) && !(cached_entry->perm & IOMMU_WO)) {
207
+ status = SMMU_TRANS_ERROR;
208
+ if (event.record_trans_faults) {
209
+ event.type = SMMU_EVT_F_PERMISSION;
210
+ event.u.f_permission.addr = addr;
211
+ event.u.f_permission.rnw = flag & 0x1;
212
+ }
213
+ } else {
214
+ status = SMMU_TRANS_SUCCESS;
215
+ }
216
+ goto epilogue;
217
+ }
218
+
219
+ cfg->iotlb_misses++;
220
+ trace_smmu_iotlb_cache_miss(cfg->asid, addr & ~page_mask,
221
+ cfg->iotlb_hits, cfg->iotlb_misses,
222
+ 100 * cfg->iotlb_hits /
223
+ (cfg->iotlb_hits + cfg->iotlb_misses));
224
+
225
+ if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) {
226
+ smmu_iotlb_inv_all(bs);
227
+ }
228
+
229
+ cached_entry = g_new0(IOMMUTLBEntry, 1);
230
+
231
+ if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) {
232
+ g_free(cached_entry);
233
switch (ptw_info.type) {
234
case SMMU_PTW_ERR_WALK_EABT:
235
event.type = SMMU_EVT_F_WALK_EABT;
236
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
237
}
238
status = SMMU_TRANS_ERROR;
239
} else {
240
+ new_key = g_new0(SMMUIOTLBKey, 1);
241
+ new_key->asid = cfg->asid;
242
+ new_key->iova = aligned_addr;
243
+ g_hash_table_insert(bs->iotlb, new_key, cached_entry);
244
status = SMMU_TRANS_SUCCESS;
245
}
246
247
@@ -XXX,XX +XXX,XX @@ epilogue:
248
switch (status) {
249
case SMMU_TRANS_SUCCESS:
250
entry.perm = flag;
251
+ entry.translated_addr = cached_entry->translated_addr +
252
+ (addr & page_mask);
253
+ entry.addr_mask = cached_entry->addr_mask;
254
trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr,
255
entry.translated_addr, entry.perm);
256
break;
257
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
258
smmuv3_flush_config(sdev);
259
break;
260
}
261
- case SMMU_CMD_TLBI_NH_ALL:
262
case SMMU_CMD_TLBI_NH_ASID:
263
- case SMMU_CMD_TLBI_NH_VA:
264
+ {
265
+ uint16_t asid = CMD_ASID(&cmd);
266
+
267
+ trace_smmuv3_cmdq_tlbi_nh_asid(asid);
268
+ smmu_iotlb_inv_asid(bs, asid);
269
+ break;
270
+ }
271
+ case SMMU_CMD_TLBI_NH_ALL:
272
+ case SMMU_CMD_TLBI_NSNH_ALL:
273
+ trace_smmuv3_cmdq_tlbi_nh();
274
+ smmu_iotlb_inv_all(bs);
275
+ break;
276
case SMMU_CMD_TLBI_NH_VAA:
277
+ {
278
+ dma_addr_t addr = CMD_ADDR(&cmd);
279
+ uint16_t vmid = CMD_VMID(&cmd);
280
+
281
+ trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr);
282
+ smmu_iotlb_inv_all(bs);
283
+ break;
284
+ }
285
+ case SMMU_CMD_TLBI_NH_VA:
286
+ {
287
+ uint16_t asid = CMD_ASID(&cmd);
288
+ uint16_t vmid = CMD_VMID(&cmd);
289
+ dma_addr_t addr = CMD_ADDR(&cmd);
290
+ bool leaf = CMD_LEAF(&cmd);
291
+
292
+ trace_smmuv3_cmdq_tlbi_nh_va(vmid, asid, addr, leaf);
293
+ smmu_iotlb_inv_iova(bs, asid, addr);
294
+ break;
295
+ }
296
case SMMU_CMD_TLBI_EL3_ALL:
297
case SMMU_CMD_TLBI_EL3_VA:
298
case SMMU_CMD_TLBI_EL2_ALL:
299
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
300
case SMMU_CMD_TLBI_EL2_VAA:
301
case SMMU_CMD_TLBI_S12_VMALL:
302
case SMMU_CMD_TLBI_S2_IPA:
303
- case SMMU_CMD_TLBI_NSNH_ALL:
304
case SMMU_CMD_ATC_INV:
305
case SMMU_CMD_PRI_RESP:
306
case SMMU_CMD_RESUME:
307
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
308
index XXXXXXX..XXXXXXX 100644
309
--- a/hw/arm/trace-events
310
+++ b/hw/arm/trace-events
311
@@ -XXX,XX +XXX,XX @@ smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr,
312
smmu_ptw_page_pte(int stage, int level, uint64_t iova, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d level=%d iova=0x%"PRIx64" base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" page address = 0x%"PRIx64
313
smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=%d level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" iova=0x%"PRIx64" block address = 0x%"PRIx64" block size = %d MiB"
314
smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64
315
+smmu_iotlb_cache_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
316
+smmu_iotlb_cache_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
317
+smmu_iotlb_inv_all(void) "IOTLB invalidate all"
318
+smmu_iotlb_inv_asid(uint16_t asid) "IOTLB invalidate asid=%d"
319
+smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
320
321
#hw/arm/smmuv3.c
322
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
323
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
324
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
325
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
326
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
327
+smmuv3_cmdq_tlbi_nh_va(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d"
328
+smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64
329
+smmuv3_cmdq_tlbi_nh(void) ""
330
+smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
331
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
332
--
333
2.17.1
334
335
diff view generated by jsdifflib
New patch
1
1
From: Eric Auger <eric.auger@redhat.com>
2
3
On TLB invalidation commands, let's call registered
4
IOMMU notifiers. Those can only be UNMAP notifiers.
5
SMMUv3 does not support notification on MAP (VFIO).
6
7
This patch allows vhost use case where IOTLB API is notified
8
on each guest IOTLB invalidation.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1529653501-15358-5-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/hw/arm/smmu-common.h | 6 +++
16
hw/arm/smmu-common.c | 34 +++++++++++++
17
hw/arm/smmuv3.c | 99 +++++++++++++++++++++++++++++++++++-
18
hw/arm/trace-events | 5 ++
19
4 files changed, 142 insertions(+), 2 deletions(-)
20
21
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/smmu-common.h
24
+++ b/include/hw/arm/smmu-common.h
25
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_inv_all(SMMUState *s);
26
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
27
void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
28
29
+/* Unmap the range of all the notifiers registered to any IOMMU mr */
30
+void smmu_inv_notifiers_all(SMMUState *s);
31
+
32
+/* Unmap the range of all the notifiers registered to @mr */
33
+void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr);
34
+
35
#endif /* HW_ARM_SMMU_COMMON */
36
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/smmu-common.c
39
+++ b/hw/arm/smmu-common.c
40
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
41
return (k1->asid == k2->asid) && (k1->iova == k2->iova);
42
}
43
44
+/* Unmap the whole notifier's range */
45
+static void smmu_unmap_notifier_range(IOMMUNotifier *n)
46
+{
47
+ IOMMUTLBEntry entry;
48
+
49
+ entry.target_as = &address_space_memory;
50
+ entry.iova = n->start;
51
+ entry.perm = IOMMU_NONE;
52
+ entry.addr_mask = n->end - n->start;
53
+
54
+ memory_region_notify_one(n, &entry);
55
+}
56
+
57
+/* Unmap all notifiers attached to @mr */
58
+inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
59
+{
60
+ IOMMUNotifier *n;
61
+
62
+ trace_smmu_inv_notifiers_mr(mr->parent_obj.name);
63
+ IOMMU_NOTIFIER_FOREACH(n, mr) {
64
+ smmu_unmap_notifier_range(n);
65
+ }
66
+}
67
+
68
+/* Unmap all notifiers of all mr's */
69
+void smmu_inv_notifiers_all(SMMUState *s)
70
+{
71
+ SMMUNotifierNode *node;
72
+
73
+ QLIST_FOREACH(node, &s->notifiers_list, next) {
74
+ smmu_inv_notifiers_mr(&node->sdev->iommu);
75
+ }
76
+}
77
+
78
static void smmu_base_realize(DeviceState *dev, Error **errp)
79
{
80
SMMUState *s = ARM_SMMU(dev);
81
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/arm/smmuv3.c
84
+++ b/hw/arm/smmuv3.c
85
@@ -XXX,XX +XXX,XX @@ epilogue:
86
return entry;
87
}
88
89
+/**
90
+ * smmuv3_notify_iova - call the notifier @n for a given
91
+ * @asid and @iova tuple.
92
+ *
93
+ * @mr: IOMMU mr region handle
94
+ * @n: notifier to be called
95
+ * @asid: address space ID or negative value if we don't care
96
+ * @iova: iova
97
+ */
98
+static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
99
+ IOMMUNotifier *n,
100
+ int asid,
101
+ dma_addr_t iova)
102
+{
103
+ SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
104
+ SMMUEventInfo event = {};
105
+ SMMUTransTableInfo *tt;
106
+ SMMUTransCfg *cfg;
107
+ IOMMUTLBEntry entry;
108
+
109
+ cfg = smmuv3_get_config(sdev, &event);
110
+ if (!cfg) {
111
+ qemu_log_mask(LOG_GUEST_ERROR,
112
+ "%s error decoding the configuration for iommu mr=%s\n",
113
+ __func__, mr->parent_obj.name);
114
+ return;
115
+ }
116
+
117
+ if (asid >= 0 && cfg->asid != asid) {
118
+ return;
119
+ }
120
+
121
+ tt = select_tt(cfg, iova);
122
+ if (!tt) {
123
+ return;
124
+ }
125
+
126
+ entry.target_as = &address_space_memory;
127
+ entry.iova = iova;
128
+ entry.addr_mask = (1 << tt->granule_sz) - 1;
129
+ entry.perm = IOMMU_NONE;
130
+
131
+ memory_region_notify_one(n, &entry);
132
+}
133
+
134
+/* invalidate an asid/iova tuple in all mr's */
135
+static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
136
+{
137
+ SMMUNotifierNode *node;
138
+
139
+ QLIST_FOREACH(node, &s->notifiers_list, next) {
140
+ IOMMUMemoryRegion *mr = &node->sdev->iommu;
141
+ IOMMUNotifier *n;
142
+
143
+ trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
144
+
145
+ IOMMU_NOTIFIER_FOREACH(n, mr) {
146
+ smmuv3_notify_iova(mr, n, asid, iova);
147
+ }
148
+ }
149
+}
150
+
151
static int smmuv3_cmdq_consume(SMMUv3State *s)
152
{
153
SMMUState *bs = ARM_SMMU(s);
154
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
155
uint16_t asid = CMD_ASID(&cmd);
156
157
trace_smmuv3_cmdq_tlbi_nh_asid(asid);
158
+ smmu_inv_notifiers_all(&s->smmu_state);
159
smmu_iotlb_inv_asid(bs, asid);
160
break;
161
}
162
case SMMU_CMD_TLBI_NH_ALL:
163
case SMMU_CMD_TLBI_NSNH_ALL:
164
trace_smmuv3_cmdq_tlbi_nh();
165
+ smmu_inv_notifiers_all(&s->smmu_state);
166
smmu_iotlb_inv_all(bs);
167
break;
168
case SMMU_CMD_TLBI_NH_VAA:
169
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
170
uint16_t vmid = CMD_VMID(&cmd);
171
172
trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr);
173
+ smmuv3_inv_notifiers_iova(bs, -1, addr);
174
smmu_iotlb_inv_all(bs);
175
break;
176
}
177
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
178
bool leaf = CMD_LEAF(&cmd);
179
180
trace_smmuv3_cmdq_tlbi_nh_va(vmid, asid, addr, leaf);
181
+ smmuv3_inv_notifiers_iova(bs, asid, addr);
182
smmu_iotlb_inv_iova(bs, asid, addr);
183
break;
184
}
185
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
186
IOMMUNotifierFlag old,
187
IOMMUNotifierFlag new)
188
{
189
+ SMMUDevice *sdev = container_of(iommu, SMMUDevice, iommu);
190
+ SMMUv3State *s3 = sdev->smmu;
191
+ SMMUState *s = &(s3->smmu_state);
192
+ SMMUNotifierNode *node = NULL;
193
+ SMMUNotifierNode *next_node = NULL;
194
+
195
+ if (new & IOMMU_NOTIFIER_MAP) {
196
+ int bus_num = pci_bus_num(sdev->bus);
197
+ PCIDevice *pcidev = pci_find_device(sdev->bus, bus_num, sdev->devfn);
198
+
199
+ warn_report("SMMUv3 does not support notification on MAP: "
200
+ "device %s will not function properly", pcidev->name);
201
+ }
202
+
203
if (old == IOMMU_NOTIFIER_NONE) {
204
- warn_report("SMMUV3 does not support vhost/vfio integration yet: "
205
- "devices of those types will not function properly");
206
+ trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
207
+ node = g_malloc0(sizeof(*node));
208
+ node->sdev = sdev;
209
+ QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
210
+ return;
211
+ }
212
+
213
+ /* update notifier node with new flags */
214
+ QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
215
+ if (node->sdev == sdev) {
216
+ if (new == IOMMU_NOTIFIER_NONE) {
217
+ trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
218
+ QLIST_REMOVE(node, next);
219
+ g_free(node);
220
+ }
221
+ return;
222
+ }
223
}
224
}
225
226
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
227
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/arm/trace-events
229
+++ b/hw/arm/trace-events
230
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_cache_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss,
231
smmu_iotlb_inv_all(void) "IOTLB invalidate all"
232
smmu_iotlb_inv_asid(uint16_t asid) "IOTLB invalidate asid=%d"
233
smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
234
+smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
235
236
#hw/arm/smmuv3.c
237
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
238
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64
239
smmuv3_cmdq_tlbi_nh(void) ""
240
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
241
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
242
+smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
243
+smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
244
+smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64
245
+
246
--
247
2.17.1
248
249
diff view generated by jsdifflib
New patch
1
1
From: Cédric Le Goater <clg@kaod.org>
2
3
All Aspeed SoC clocks are driven by an input source clock which can
4
have different frequencies : 24MHz or 25MHz, and also, on the Aspeed
5
AST2400 SoC, 48MHz. The H-PLL (CPU) clock is defined from a
6
calculation using parameters in the H-PLL Parameter register or from a
7
predefined set of frequencies if the setting is strapped by hardware
8
(Aspeed AST2400 SoC). The other clocks of the SoC are then defined
9
from the H-PLL using dividers.
10
11
We introduce first the APB clock because it should be used to drive
12
the Aspeed timer model.
13
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
16
Message-id: 20180622075700.5923-2-clg@kaod.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/misc/aspeed_scu.h | 70 +++++++++++++++++++++--
20
hw/misc/aspeed_scu.c | 106 +++++++++++++++++++++++++++++++++++
21
2 files changed, 172 insertions(+), 4 deletions(-)
22
23
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/aspeed_scu.h
26
+++ b/include/hw/misc/aspeed_scu.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState {
28
uint32_t hw_strap1;
29
uint32_t hw_strap2;
30
uint32_t hw_prot_key;
31
+
32
+ uint32_t clkin;
33
+ uint32_t hpll;
34
+ uint32_t apb_freq;
35
} AspeedSCUState;
36
37
#define AST2400_A0_SILICON_REV 0x02000303U
38
@@ -XXX,XX +XXX,XX @@ extern bool is_supported_silicon_rev(uint32_t silicon_rev);
39
* 1. 2012/12/29 Ryan Chen Create
40
*/
41
42
-/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
43
+/* SCU08 Clock Selection Register
44
+ *
45
+ * 31 Enable Video Engine clock dynamic slow down
46
+ * 30:28 Video Engine clock slow down setting
47
+ * 27 2D Engine GCLK clock source selection
48
+ * 26 2D Engine GCLK clock throttling enable
49
+ * 25:23 APB PCLK divider selection
50
+ * 22:20 LPC Host LHCLK divider selection
51
+ * 19 LPC Host LHCLK clock generation/output enable control
52
+ * 18:16 MAC AHB bus clock divider selection
53
+ * 15 SD/SDIO clock running enable
54
+ * 14:12 SD/SDIO divider selection
55
+ * 11 Reserved
56
+ * 10:8 Video port output clock delay control bit
57
+ * 7 ARM CPU/AHB clock slow down enable
58
+ * 6:4 ARM CPU/AHB clock slow down setting
59
+ * 3:2 ECLK clock source selection
60
+ * 1 CPU/AHB clock slow down idle timer
61
+ * 0 CPU/AHB clock dynamic slow down enable (defined in bit[6:4])
62
+ */
63
+#define SCU_CLK_GET_PCLK_DIV(x) (((x) >> 23) & 0x7)
64
+
65
+/* SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
66
+ *
67
+ * 18 H-PLL parameter selection
68
+ * 0: Select H-PLL by strapping resistors
69
+ * 1: Select H-PLL by the programmed registers (SCU24[17:0])
70
+ * 17 Enable H-PLL bypass mode
71
+ * 16 Turn off H-PLL
72
+ * 10:5 H-PLL Numerator
73
+ * 4 H-PLL Output Divider
74
+ * 3:0 H-PLL Denumerator
75
+ *
76
+ * (Output frequency) = 24MHz * (2-OD) * [(Numerator+2) / (Denumerator+1)]
77
+ */
78
+
79
+#define SCU_AST2400_H_PLL_PROGRAMMED (0x1 << 18)
80
+#define SCU_AST2400_H_PLL_BYPASS_EN (0x1 << 17)
81
+#define SCU_AST2400_H_PLL_OFF (0x1 << 16)
82
+
83
+/* SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
84
+ *
85
+ * 21 Enable H-PLL reset
86
+ * 20 Enable H-PLL bypass mode
87
+ * 19 Turn off H-PLL
88
+ * 18:13 H-PLL Post Divider
89
+ * 12:5 H-PLL Numerator (M)
90
+ * 4:0 H-PLL Denumerator (N)
91
+ *
92
+ * (Output frequency) = CLKIN(24MHz) * [(M+1) / (N+1)] / (P+1)
93
+ *
94
+ * The default frequency is 792Mhz when CLKIN = 24MHz
95
+ */
96
+
97
+#define SCU_H_PLL_BYPASS_EN (0x1 << 20)
98
+#define SCU_H_PLL_OFF (0x1 << 19)
99
+
100
+/* SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
101
*
102
* 31:29 Software defined strapping registers
103
* 28:27 DRAM size setting (for VGA driver use)
104
@@ -XXX,XX +XXX,XX @@ extern bool is_supported_silicon_rev(uint32_t silicon_rev);
105
#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (((((x) >> 23) & 0x1) << 1) \
106
| (((x) >> 18) & 0x1))
107
#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1 << 18))
108
-#define AST2400_CLK_25M_IN (0x1 << 23)
109
+#define SCU_HW_STRAP_CLK_25M_IN (0x1 << 23)
110
#define AST2400_CLK_24M_IN 0
111
#define AST2400_CLK_48M_IN 1
112
#define AST2400_CLK_25M_IN_24M_USB_CKI 2
113
#define AST2400_CLK_25M_IN_48M_USB_CKI 3
114
115
+#define SCU_HW_STRAP_CLK_48M_IN (0x1 << 18)
116
#define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
117
#define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
118
#define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
119
@@ -XXX,XX +XXX,XX @@ extern bool is_supported_silicon_rev(uint32_t silicon_rev);
120
#define AST2400_DIS_BOOT 3
121
122
/*
123
- * Hardware strapping register definition (for Aspeed AST2500 SoC and
124
- * higher)
125
+ * SCU70 Hardware strapping register definition (for Aspeed AST2500
126
+ * SoC and higher)
127
*
128
* 31 Enable SPI Flash Strap Auto Fetch Mode
129
* 30 Enable GPIO Strap Mode
130
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/misc/aspeed_scu.c
133
+++ b/hw/misc/aspeed_scu.c
134
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void)
135
return num;
136
}
137
138
+static void aspeed_scu_set_apb_freq(AspeedSCUState *s)
139
+{
140
+ uint32_t apb_divider;
141
+
142
+ switch (s->silicon_rev) {
143
+ case AST2400_A0_SILICON_REV:
144
+ case AST2400_A1_SILICON_REV:
145
+ apb_divider = 2;
146
+ break;
147
+ case AST2500_A0_SILICON_REV:
148
+ case AST2500_A1_SILICON_REV:
149
+ apb_divider = 4;
150
+ break;
151
+ default:
152
+ g_assert_not_reached();
153
+ }
154
+
155
+ s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
156
+ / apb_divider;
157
+}
158
+
159
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
160
{
161
AspeedSCUState *s = ASPEED_SCU(opaque);
162
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
163
case PROT_KEY:
164
s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
165
return;
166
+ case CLK_SEL:
167
+ s->regs[reg] = data;
168
+ aspeed_scu_set_apb_freq(s);
169
+ break;
170
171
case FREQ_CNTR_EVAL:
172
case VGA_SCRATCH1 ... VGA_SCRATCH8:
173
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_scu_ops = {
174
.valid.unaligned = false,
175
};
176
177
+static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
178
+{
179
+ if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN) {
180
+ return 25000000;
181
+ } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
182
+ return 48000000;
183
+ } else {
184
+ return 24000000;
185
+ }
186
+}
187
+
188
+/*
189
+ * Strapped frequencies for the AST2400 in MHz. They depend on the
190
+ * clkin frequency.
191
+ */
192
+static const uint32_t hpll_ast2400_freqs[][4] = {
193
+ { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
194
+ { 400, 375, 350, 425 }, /* 25MHz */
195
+};
196
+
197
+static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
198
+{
199
+ uint32_t hpll_reg = s->regs[HPLL_PARAM];
200
+ uint8_t freq_select;
201
+ bool clk_25m_in;
202
+
203
+ if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
204
+ return 0;
205
+ }
206
+
207
+ if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
208
+ uint32_t multiplier = 1;
209
+
210
+ if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
211
+ uint32_t n = (hpll_reg >> 5) & 0x3f;
212
+ uint32_t od = (hpll_reg >> 4) & 0x1;
213
+ uint32_t d = hpll_reg & 0xf;
214
+
215
+ multiplier = (2 - od) * ((n + 2) / (d + 1));
216
+ }
217
+
218
+ return s->clkin * multiplier;
219
+ }
220
+
221
+ /* HW strapping */
222
+ clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
223
+ freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
224
+
225
+ return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
226
+}
227
+
228
+static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
229
+{
230
+ uint32_t hpll_reg = s->regs[HPLL_PARAM];
231
+ uint32_t multiplier = 1;
232
+
233
+ if (hpll_reg & SCU_H_PLL_OFF) {
234
+ return 0;
235
+ }
236
+
237
+ if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
238
+ uint32_t p = (hpll_reg >> 13) & 0x3f;
239
+ uint32_t m = (hpll_reg >> 5) & 0xff;
240
+ uint32_t n = hpll_reg & 0x1f;
241
+
242
+ multiplier = ((m + 1) / (n + 1)) / (p + 1);
243
+ }
244
+
245
+ return s->clkin * multiplier;
246
+}
247
+
248
static void aspeed_scu_reset(DeviceState *dev)
249
{
250
AspeedSCUState *s = ASPEED_SCU(dev);
251
const uint32_t *reset;
252
+ uint32_t (*calc_hpll)(AspeedSCUState *s);
253
254
switch (s->silicon_rev) {
255
case AST2400_A0_SILICON_REV:
256
case AST2400_A1_SILICON_REV:
257
reset = ast2400_a0_resets;
258
+ calc_hpll = aspeed_scu_calc_hpll_ast2400;
259
break;
260
case AST2500_A0_SILICON_REV:
261
case AST2500_A1_SILICON_REV:
262
reset = ast2500_a1_resets;
263
+ calc_hpll = aspeed_scu_calc_hpll_ast2500;
264
break;
265
default:
266
g_assert_not_reached();
267
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev)
268
s->regs[HW_STRAP1] = s->hw_strap1;
269
s->regs[HW_STRAP2] = s->hw_strap2;
270
s->regs[PROT_KEY] = s->hw_prot_key;
271
+
272
+ /*
273
+ * All registers are set. Now compute the frequencies of the main clocks
274
+ */
275
+ s->clkin = aspeed_scu_get_clkin(s);
276
+ s->hpll = calc_hpll(s);
277
+ aspeed_scu_set_apb_freq(s);
278
}
279
280
static uint32_t aspeed_silicon_revs[] = {
281
--
282
2.17.1
283
284
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
(qemu) info mtree
3
The System Control Unit should be initialized first as it drives all
4
address-space: cpu-memory-0
4
the configuration of the SoC and other device models.
5
0000000000000000-ffffffffffffffff (prio 0, i/o): system
6
0000000000000000-0000000007ffffff (prio 0, rom): aspeed.boot_rom
7
000000001e600000-000000001e7fffff (prio -1, i/o): aspeed_soc.io
8
- 000000001e784000-000000001e78401f (prio 0, i/o): serial
9
000000001e620000-000000001e6200ff (prio 0, i/o): aspeed.smc.ast2500-fmc
10
000000001e630000-000000001e6300ff (prio 0, i/o): aspeed.smc.ast2500-spi1
11
[...]
12
000000001e720000-000000001e728fff (prio 0, ram): aspeed.sram
13
000000001e782000-000000001e782fff (prio 0, i/o): aspeed.timer
14
+ 000000001e784000-000000001e78401f (prio 0, i/o): serial
15
000000001e785000-000000001e78501f (prio 0, i/o): aspeed.wdt
16
000000001e785020-000000001e78503f (prio 0, i/o): aspeed.wdt
17
5
18
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Cédric Le Goater <clg@kaod.org>
7
Reviewed-by: Joel Stanley <joel@jms.id.au>
20
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
8
Acked-by: Andrew Jeffery <andrew@aj.id.au>
21
Message-id: 20180209085755.30414-2-f4bug@amsat.org
9
Message-id: 20180622075700.5923-3-clg@kaod.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
11
---
24
hw/arm/aspeed_soc.c | 3 ++-
12
hw/arm/aspeed_soc.c | 40 ++++++++++++++++++++--------------------
25
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 20 insertions(+), 20 deletions(-)
26
14
27
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
15
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
28
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/aspeed_soc.c
17
--- a/hw/arm/aspeed_soc.c
30
+++ b/hw/arm/aspeed_soc.c
18
+++ b/hw/arm/aspeed_soc.c
19
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
20
object_initialize(&s->cpu, sizeof(s->cpu), sc->info->cpu_type);
21
object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
22
23
- object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
24
- object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
25
- qdev_set_parent_bus(DEVICE(&s->vic), sysbus_get_default());
26
-
27
- object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
28
- object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
29
- qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
30
-
31
- object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
32
- object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL);
33
- qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
34
-
35
object_initialize(&s->scu, sizeof(s->scu), TYPE_ASPEED_SCU);
36
object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
37
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
38
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
39
object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
40
"hw-prot-key", &error_abort);
41
42
+ object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
43
+ object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
44
+ qdev_set_parent_bus(DEVICE(&s->vic), sysbus_get_default());
45
+
46
+ object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
47
+ object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
48
+ qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
49
+
50
+ object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
51
+ object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL);
52
+ qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
53
+
54
object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
55
object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
56
qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
31
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
57
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
58
memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE,
59
&s->sram);
60
61
+ /* SCU */
62
+ object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
63
+ if (err) {
64
+ error_propagate(errp, err);
65
+ return;
66
+ }
67
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
68
+
69
/* VIC */
70
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
71
if (err) {
72
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
73
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
74
}
75
76
- /* SCU */
77
- object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
78
- if (err) {
79
- error_propagate(errp, err);
80
- return;
81
- }
82
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
83
-
32
/* UART - attach an 8250 to the IO space as our UART5 */
84
/* UART - attach an 8250 to the IO space as our UART5 */
33
if (serial_hds[0]) {
85
if (serial_hd(0)) {
34
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
86
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
35
- serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
36
+ serial_mm_init(get_system_memory(),
37
+ ASPEED_SOC_IOMEM_BASE + ASPEED_SOC_UART_5_BASE, 2,
38
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
39
}
40
41
--
87
--
42
2.16.1
88
2.17.1
43
89
44
90
diff view generated by jsdifflib
1
From: Pekka Enberg <penberg@iki.fi>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
This patch adds Raspberry Pi 3 support to hw/arm/raspi.c. The
3
The timer controller can be driven by either an external 1MHz clock or
4
differences to Pi 2 are:
4
by the APB clock. Today, the model makes the assumption that the APB
5
frequency is always set to 24MHz but this is incorrect.
5
6
6
- Firmware address
7
The AST2400 SoC on the palmetto machines uses a 48MHz input clock
7
- Board ID
8
source and the APB can be set to 48MHz. The consequence is a general
8
- Board revision
9
system slowdown. The QEMU machines using the AST2500 SoC do not seem
10
impacted today because the APB frequency is still set to 24MHz.
9
11
10
The CPU is different too, but that's going to be configured as part of
12
We fix the timer frequency for all SoCs by linking the Timer model to
11
the machine default CPU when we introduce a new machine type.
13
the SCU model. The APB frequency driving the timers is now the one
14
configured for the SoC.
12
15
13
The patch was written from scratch by me but the logic is similar to
16
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Zoltán Baldaszti's previous work, which I used as a reference (with
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
15
permission from the author):
18
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
16
19
Message-id: 20180622075700.5923-4-clg@kaod.org
17
https://github.com/bztsrc/qemu-raspi3
18
19
Signed-off-by: Pekka Enberg <penberg@iki.fi>
20
[PMM: fixed trailing whitespace on one line]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
21
---
24
hw/arm/raspi.c | 31 +++++++++++++++++++++----------
22
include/hw/timer/aspeed_timer.h | 4 ++++
25
1 file changed, 21 insertions(+), 10 deletions(-)
23
hw/arm/aspeed_soc.c | 2 ++
24
hw/timer/aspeed_timer.c | 19 +++++++++++++++----
25
3 files changed, 21 insertions(+), 4 deletions(-)
26
26
27
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
27
diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
28
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/raspi.c
29
--- a/include/hw/timer/aspeed_timer.h
30
+++ b/hw/arm/raspi.c
30
+++ b/include/hw/timer/aspeed_timer.h
31
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
32
* Rasperry Pi 2 emulation Copyright (c) 2015, Microsoft
32
33
* Written by Andrew Baumann
33
#include "qemu/timer.h"
34
*
34
35
+ * Raspberry Pi 3 emulation Copyright (c) 2018 Zoltán Baldaszti
35
+typedef struct AspeedSCUState AspeedSCUState;
36
+ * Upstream code cleanup (c) 2018 Pekka Enberg
36
+
37
+ *
37
#define ASPEED_TIMER(obj) \
38
* This code is licensed under the GNU GPLv2 and later.
38
OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
39
#define TYPE_ASPEED_TIMER "aspeed.timer"
40
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedTimerCtrlState {
41
uint32_t ctrl;
42
uint32_t ctrl2;
43
AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
44
+
45
+ AspeedSCUState *scu;
46
} AspeedTimerCtrlState;
47
48
#endif /* ASPEED_TIMER_H */
49
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/aspeed_soc.c
52
+++ b/hw/arm/aspeed_soc.c
53
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
54
55
object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
56
object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
57
+ object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
58
+ OBJECT(&s->scu), &error_abort);
59
qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
60
61
object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
62
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/timer/aspeed_timer.c
65
+++ b/hw/timer/aspeed_timer.c
66
@@ -XXX,XX +XXX,XX @@
39
*/
67
*/
40
68
69
#include "qemu/osdep.h"
70
+#include "qapi/error.h"
71
#include "hw/sysbus.h"
72
#include "hw/timer/aspeed_timer.h"
73
+#include "hw/misc/aspeed_scu.h"
74
#include "qemu-common.h"
75
#include "qemu/bitops.h"
76
#include "qemu/timer.h"
41
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@
42
#define SMPBOOT_ADDR 0x300 /* this should leave enough space for ATAGS */
78
#define TIMER_CLOCK_USE_EXT true
43
#define MVBAR_ADDR 0x400 /* secure vectors */
79
#define TIMER_CLOCK_EXT_HZ 1000000
44
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
80
#define TIMER_CLOCK_USE_APB false
45
-#define FIRMWARE_ADDR 0x8000 /* Pi loads kernel.img here by default */
81
-#define TIMER_CLOCK_APB_HZ 24000000
46
+#define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */
82
47
+#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
83
#define TIMER_REG_STATUS 0
48
84
#define TIMER_REG_RELOAD 1
49
/* Table of Linux board IDs for different Pi versions */
85
@@ -XXX,XX +XXX,XX @@ static inline bool timer_external_clock(AspeedTimer *t)
50
-static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43};
86
return timer_ctrl_status(t, op_external_clock);
51
+static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
52
53
typedef struct RasPiState {
54
BCM2836State soc;
55
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
56
binfo.secure_board_setup = true;
57
binfo.secure_boot = true;
58
59
- /* Pi2 requires SMP setup */
60
- if (version == 2) {
61
+ /* Pi2 and Pi3 requires SMP setup */
62
+ if (version >= 2) {
63
binfo.smp_loader_start = SMPBOOT_ADDR;
64
binfo.write_secondary_boot = write_smpboot;
65
binfo.secondary_cpu_reset_hook = reset_secondary;
66
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
67
* the normal Linux boot process
68
*/
69
if (machine->firmware) {
70
+ hwaddr firmware_addr = version == 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2;
71
/* load the firmware image (typically kernel.img) */
72
- r = load_image_targphys(machine->firmware, FIRMWARE_ADDR,
73
- ram_size - FIRMWARE_ADDR);
74
+ r = load_image_targphys(machine->firmware, firmware_addr,
75
+ ram_size - firmware_addr);
76
if (r < 0) {
77
error_report("Failed to load firmware from %s", machine->firmware);
78
exit(1);
79
}
80
81
- binfo.entry = FIRMWARE_ADDR;
82
+ binfo.entry = firmware_addr;
83
binfo.firmware_loaded = true;
84
} else {
85
binfo.kernel_filename = machine->kernel_filename;
86
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
87
arm_load_kernel(ARM_CPU(first_cpu), &binfo);
88
}
87
}
89
88
90
-static void raspi2_init(MachineState *machine)
89
-static uint32_t clock_rates[] = { TIMER_CLOCK_APB_HZ, TIMER_CLOCK_EXT_HZ };
91
+static void raspi_init(MachineState *machine, int version)
90
-
91
static inline uint32_t calculate_rate(struct AspeedTimer *t)
92
{
92
{
93
RasPiState *s = g_new0(RasPiState, 1);
93
- return clock_rates[timer_external_clock(t)];
94
uint32_t vcram_size;
94
+ AspeedTimerCtrlState *s = timer_to_ctrl(t);
95
@@ -XXX,XX +XXX,XX @@ static void raspi2_init(MachineState *machine)
96
&error_abort);
97
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
98
&error_abort);
99
- object_property_set_int(OBJECT(&s->soc), 0xa21041, "board-rev",
100
+ int board_rev = version == 3 ? 0xa02082 : 0xa21041;
101
+ object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
102
&error_abort);
103
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);
104
105
@@ -XXX,XX +XXX,XX @@ static void raspi2_init(MachineState *machine)
106
107
vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
108
&error_abort);
109
- setup_boot(machine, 2, machine->ram_size - vcram_size);
110
+ setup_boot(machine, version, machine->ram_size - vcram_size);
111
+}
112
+
95
+
113
+static void raspi2_init(MachineState *machine)
96
+ return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
114
+{
115
+ raspi_init(machine, 2);
116
}
97
}
117
98
118
static void raspi2_machine_init(MachineClass *mc)
99
static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
100
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_realize(DeviceState *dev, Error **errp)
101
int i;
102
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
103
AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
104
+ Object *obj;
105
+ Error *err = NULL;
106
+
107
+ obj = object_property_get_link(OBJECT(dev), "scu", &err);
108
+ if (!obj) {
109
+ error_propagate(errp, err);
110
+ error_prepend(errp, "required link 'scu' not found: ");
111
+ return;
112
+ }
113
+ s->scu = ASPEED_SCU(obj);
114
115
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
116
aspeed_init_one_timer(s, i);
119
--
117
--
120
2.16.1
118
2.17.1
121
119
122
120
diff view generated by jsdifflib