1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
target-arm queue: I have a lot more still in my to-review
2
queue, but my rule of thumb is when I get to 50 patches or
3
so to send out what I have.
2
4
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
5
thanks
6
-- PMM
7
8
The following changes since commit 9a7beaad3dbba982f7a461d676b55a5c3851d312:
9
10
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210304' into staging (2021-03-05 10:47:46 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210305
8
15
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
16
for you to fetch changes up to 2c669ff88ec6733420a000103a2b8b9e93df4945:
10
17
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
18
hw/arm/mps2: Update old infocenter.arm.com URLs (2021-03-05 15:17:38 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
* sbsa-ref: remove cortex-a53 from list of supported cpus
15
* Fix AArch32 SMLAD incorrect setting of Q bit
22
* sbsa-ref: add 'max' to list of allowed cpus
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
23
* target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
17
* strongarm: Fix 'time to transmit a char' unit comment
24
* npcm7xx: add EMC model
18
* Restrict APEI tables generation to the 'virt' machine
25
* xlnx-zynqmp: Remove obsolete 'has_rpu' property
19
* bcm2835: minor code cleanups
26
* target/arm: Speed up aarch64 TBL/TBX
20
* correctly flush TLBs when TBI is enabled
27
* virtio-mmio: improve virtio-mmio get_dev_path alog
21
* tests/qtest: Add npcm7xx timer test
28
* target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
22
* loads-stores.rst: add footnote that clarifies GETPC usage
29
* target/arm: Restrict v8M IDAU to TCG
23
* Fix reported EL for mte_check_fail
30
* target/arm/cpu: Update coding style to make checkpatch.pl happy
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
31
* musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces
25
* microbit_i2c: Fix coredump when dump-vmstate
32
* Add new board: mps3-an524
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
29
33
30
----------------------------------------------------------------
34
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
35
Doug Evans (3):
32
loads-stores.rst: add footnote that clarifies GETPC usage
36
hw/net: Add npcm7xx emc model
37
hw/arm: Add npcm7xx emc model
38
tests/qtests: Add npcm7xx emc model test
33
39
34
Havard Skinnemoen (1):
40
Marcin Juszkiewicz (2):
35
tests/qtest: Add npcm7xx timer test
41
sbsa-ref: remove cortex-a53 from list of supported cpus
42
sbsa-ref: add 'max' to list of allowed cpus
36
43
37
Peng Liang (1):
44
Peter Collingbourne (1):
38
microbit_i2c: Fix coredump when dump-vmstate
45
target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
39
46
40
Peter Maydell (12):
47
Peter Maydell (34):
41
target/arm: Fix SMLAD incorrect setting of Q bit
48
hw/arm/musicpal: Remove dead code for non-32-bit-RGB surfaces
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
49
hw/display/tc6393xb: Remove dead code for handling non-32bpp surfaces
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
50
hw/display/tc6393xb: Expand out macros in template header
44
target/arm: Implement v8.1M NOCP handling
51
hw/display/tc6393xb: Inline tc6393xb_draw_graphic32() at its callsite
45
target/arm: Implement v8.1M conditional-select insns
52
hw/display/omap_lcdc: Expand out macros in template header
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
53
hw/display/omap_lcdc: Drop broken bigendian ifdef
47
target/arm: Don't allow BLX imm for M-profile
54
hw/display/omap_lcdc: Fix coding style issues in template header
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
55
hw/display/omap_lcdc: Inline template header into C file
49
target/arm: Implement v8.1M low-overhead-loop instructions
56
hw/display/omap_lcdc: Delete unnecessary macro
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
57
hw/display/tcx: Drop unnecessary code for handling BGR format outputs
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
58
hw/arm/mps2-tz: Make SYSCLK frequency board-specific
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
59
hw/misc/mps2-scc: Support configurable number of OSCCLK values
60
hw/arm/mps2-tz: Correct the OSCCLK settings for mps2-an505 and mps2-an511
61
hw/arm/mps2-tz: Make the OSCCLK settings be configurable per-board
62
hw/misc/mps2-fpgaio: Make number of LEDs configurable by board
63
hw/misc/mps2-fpgaio: Support SWITCH register
64
hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board
65
hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type
66
hw/arm/mps2-tz: Make number of IRQs board-specific
67
hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524
68
hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI
69
hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts
70
hw/arm/mps2-tz: Move device IRQ info to data structures
71
hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs
72
hw/arm/mps2-tz: Allow boards to have different PPCInfo data
73
hw/arm/mps2-tz: Make RAM arrangement board-specific
74
hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data
75
hw/arm/mps2-tz: Support ROMs as well as RAMs
76
hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo
77
hw/arm/mps2-tz: Add new mps3-an524 board
78
hw/arm/mps2-tz: Stub out USB controller for mps3-an524
79
hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524
80
docs/system/arm/mps2.rst: Document the new mps3-an524 board
81
hw/arm/mps2: Update old infocenter.arm.com URLs
53
82
54
Philippe Mathieu-Daudé (10):
83
Philippe Mathieu-Daudé (4):
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
84
hw/arm/xlnx-zynqmp: Remove obsolete 'has_rpu' property
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
85
hw/i2c/npcm7xx_smbus: Simplify npcm7xx_smbus_init()
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
86
target/arm: Restrict v8M IDAU to TCG
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
87
target/arm/cpu: Update coding style to make checkpatch.pl happy
59
hw/timer/bcm2835: Support the timer COMPARE registers
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
65
88
66
Richard Henderson (16):
89
Rebecca Cran (3):
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
90
target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
91
target/arm: Enable FEAT_SSBS for "max" AARCH64 CPU
69
target/arm: Remove redundant mmu_idx lookup
92
target/arm: Set ID_PFR2.SSBS to 1 for "max" 32-bit CPU
70
target/arm: Fix reported EL for mte_check_fail
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
72
linux-user/aarch64: Reset btype for signals
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
74
include/elf: Add defines related to GNU property notes for AArch64
75
linux-user/elfload: Fix coding style in load_elf_image
76
linux-user/elfload: Adjust iteration over phdr
77
linux-user/elfload: Move PT_INTERP detection to first loop
78
linux-user/elfload: Use Error for load_elf_image
79
linux-user/elfload: Use Error for load_elf_interp
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
82
tests/tcg/aarch64: Add bti smoke tests
83
93
84
docs/devel/loads-stores.rst | 8 +-
94
Richard Henderson (1):
85
default-configs/devices/arm-softmmu.mak | 1 -
95
target/arm: Speed up aarch64 TBL/TBX
86
include/elf.h | 22 ++
87
include/exec/cpu-all.h | 2 +
88
include/exec/exec-all.h | 36 ++
89
include/hw/timer/bcm2835_systmr.h | 17 +-
90
linux-user/qemu.h | 4 +
91
linux-user/syscall_defs.h | 4 +
92
target/arm/cpu.h | 13 +
93
target/arm/helper.h | 13 +
94
target/arm/internals.h | 9 +-
95
target/arm/m-nocp.decode | 10 +-
96
target/arm/t32.decode | 50 ++-
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
98
hw/arm/bcm2835_peripherals.c | 13 +-
99
hw/arm/nseries.c | 1 +
100
hw/arm/strongarm.c | 2 +-
101
hw/i2c/microbit_i2c.c | 1 +
102
hw/intc/bcm2835_ic.c | 4 +-
103
hw/intc/bcm2836_control.c | 8 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
105
linux-user/aarch64/signal.c | 10 +-
106
linux-user/elfload.c | 326 ++++++++++++++----
107
linux-user/mmap.c | 16 +
108
target/arm/cpu.c | 38 ++-
109
target/arm/helper.c | 55 +++-
110
target/arm/mte_helper.c | 13 +-
111
target/arm/translate-a64.c | 6 +-
112
target/arm/translate.c | 239 +++++++++++++-
113
target/arm/vfp_helper.c | 76 +++--
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
115
tests/tcg/aarch64/bti-1.c | 62 ++++
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
96
97
schspa (1):
98
virtio-mmio: improve virtio-mmio get_dev_path alog
99
100
docs/system/arm/mps2.rst | 24 +-
101
docs/system/arm/nuvoton.rst | 3 +-
102
hw/display/omap_lcd_template.h | 169 --------
103
hw/display/tc6393xb_template.h | 72 ----
104
include/hw/arm/armsse.h | 4 +-
105
include/hw/arm/npcm7xx.h | 2 +
106
include/hw/arm/xlnx-zynqmp.h | 2 -
107
include/hw/misc/armsse-cpuid.h | 2 +-
108
include/hw/misc/armsse-mhu.h | 2 +-
109
include/hw/misc/iotkit-secctl.h | 2 +-
110
include/hw/misc/iotkit-sysctl.h | 2 +-
111
include/hw/misc/iotkit-sysinfo.h | 2 +-
112
include/hw/misc/mps2-fpgaio.h | 8 +-
113
include/hw/misc/mps2-scc.h | 10 +-
114
include/hw/net/npcm7xx_emc.h | 286 +++++++++++++
115
include/ui/console.h | 10 -
116
target/arm/cpu.h | 15 +-
117
target/arm/helper-a64.h | 2 +-
118
target/arm/internals.h | 6 +
119
hw/arm/mps2-tz.c | 632 +++++++++++++++++++++++-----
120
hw/arm/mps2.c | 5 +
121
hw/arm/musicpal.c | 64 ++-
122
hw/arm/npcm7xx.c | 50 ++-
123
hw/arm/sbsa-ref.c | 2 +-
124
hw/arm/xlnx-zynqmp.c | 6 -
125
hw/display/omap_lcdc.c | 129 +++++-
126
hw/display/tc6393xb.c | 48 +--
127
hw/display/tcx.c | 31 +-
128
hw/i2c/npcm7xx_smbus.c | 1 -
129
hw/misc/armsse-cpuid.c | 2 +-
130
hw/misc/armsse-mhu.c | 2 +-
131
hw/misc/iotkit-sysctl.c | 2 +-
132
hw/misc/iotkit-sysinfo.c | 2 +-
133
hw/misc/mps2-fpgaio.c | 43 +-
134
hw/misc/mps2-scc.c | 93 ++++-
135
hw/net/npcm7xx_emc.c | 857 ++++++++++++++++++++++++++++++++++++++
136
hw/virtio/virtio-mmio.c | 13 +-
137
target/arm/cpu.c | 23 +-
138
target/arm/cpu64.c | 5 +
139
target/arm/cpu_tcg.c | 8 +
140
target/arm/helper-a64.c | 32 --
141
target/arm/helper.c | 39 +-
142
target/arm/mte_helper.c | 13 +-
143
target/arm/translate-a64.c | 70 +---
144
target/arm/vec_helper.c | 48 +++
145
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++++++++
146
hw/net/meson.build | 1 +
147
hw/net/trace-events | 17 +
148
tests/qtest/meson.build | 3 +-
149
49 files changed, 3098 insertions(+), 628 deletions(-)
150
delete mode 100644 hw/display/omap_lcd_template.h
151
delete mode 100644 hw/display/tc6393xb_template.h
152
create mode 100644 include/hw/net/npcm7xx_emc.h
153
create mode 100644 hw/net/npcm7xx_emc.c
154
create mode 100644 tests/qtest/npcm7xx_emc-test.c
155
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
The SYS_timer is not directly wired to the ARM core, but to the
3
Cortex-A53 supports 40bits of address space. sbsa-ref's memory starts
4
SoC (peripheral) interrupt controller.
4
above this limit.
5
5
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Acked-by: Leif Lindholm <leif@nuviainc.com>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210216150122.3830863-2-marcin.juszkiewicz@linaro.org
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
12
hw/arm/sbsa-ref.c | 1 -
14
1 file changed, 11 insertions(+), 2 deletions(-)
13
1 file changed, 1 deletion(-)
15
14
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
17
--- a/hw/arm/sbsa-ref.c
19
+++ b/hw/arm/bcm2835_peripherals.c
18
+++ b/hw/arm/sbsa-ref.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
20
};
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
21
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
22
static const char * const valid_cpus[] = {
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
23
- ARM_CPU_TYPE_NAME("cortex-a53"),
25
- INTERRUPT_ARM_TIMER));
24
ARM_CPU_TYPE_NAME("cortex-a57"),
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
25
ARM_CPU_TYPE_NAME("cortex-a72"),
27
+ INTERRUPT_TIMER0));
26
};
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
27
--
41
2.20.1
28
2.20.1
42
29
43
30
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Commit 7998beb9c2e removed the ram_size initialization in the
3
Let add 'max' cpu while work goes on adding newer CPU types than
4
arm_boot_info structure, however it is used by arm_load_kernel().
4
Cortex-A72. This allows us to check SVE etc support.
5
5
6
Initialize the field to fix:
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
7
Acked-by: Leif Lindholm <leif@nuviainc.com>
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
9
Message-id: 20210216150122.3830863-3-marcin.juszkiewicz@linaro.org
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
11
---
22
hw/arm/nseries.c | 1 +
12
hw/arm/sbsa-ref.c | 1 +
23
1 file changed, 1 insertion(+)
13
1 file changed, 1 insertion(+)
24
14
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
17
--- a/hw/arm/sbsa-ref.c
28
+++ b/hw/arm/nseries.c
18
+++ b/hw/arm/sbsa-ref.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
30
g_free(sz);
20
static const char * const valid_cpus[] = {
31
exit(EXIT_FAILURE);
21
ARM_CPU_TYPE_NAME("cortex-a57"),
32
}
22
ARM_CPU_TYPE_NAME("cortex-a72"),
33
+ binfo->ram_size = machine->ram_size;
23
+ ARM_CPU_TYPE_NAME("max"),
34
24
};
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
25
36
machine->ram);
26
static bool cpu_type_valid(const char *cpu)
37
--
27
--
38
2.20.1
28
2.20.1
39
29
40
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
Transform the prot bit to a qemu internal page bit, and save
3
Add support for FEAT_SSBS. SSBS (Speculative Store Bypass Safe) is an
4
it in the page tables.
4
optional feature in ARMv8.0, and mandatory in ARMv8.5.
5
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
8
Message-id: 20210216224543.16142-2-rebecca@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
include/exec/cpu-all.h | 2 ++
11
target/arm/cpu.h | 15 ++++++++++++++-
12
linux-user/syscall_defs.h | 4 ++++
12
target/arm/internals.h | 6 ++++++
13
target/arm/cpu.h | 5 +++++
13
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++++++++
14
linux-user/mmap.c | 16 ++++++++++++++++
14
target/arm/translate-a64.c | 12 ++++++++++++
15
target/arm/translate-a64.c | 6 +++---
15
4 files changed, 69 insertions(+), 1 deletion(-)
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
16
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
21
+++ b/include/exec/cpu-all.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
24
#define PAGE_RESERVED 0x0020
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
22
#define SCTLR_TE (1U << 30) /* AArch32 only */
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
23
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
53
24
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
54
+/*
25
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
26
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
56
+ */
27
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
57
+#define PAGE_BTI PAGE_TARGET_1
28
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
30
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
31
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
32
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
33
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
34
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
35
36
#define CPTR_TCPAC (1U << 31)
37
#define CPTR_TTA (1U << 20)
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
39
#define CPSR_IL (1U << 20)
40
#define CPSR_DIT (1U << 21)
41
#define CPSR_PAN (1U << 22)
42
+#define CPSR_SSBS (1U << 23)
43
#define CPSR_J (1U << 24)
44
#define CPSR_IT_0_1 (3U << 25)
45
#define CPSR_Q (1U << 27)
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
47
#define PSTATE_A (1U << 8)
48
#define PSTATE_D (1U << 9)
49
#define PSTATE_BTYPE (3U << 10)
50
+#define PSTATE_SSBS (1U << 12)
51
#define PSTATE_IL (1U << 20)
52
#define PSTATE_SS (1U << 21)
53
#define PSTATE_PAN (1U << 22)
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
55
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
56
}
57
58
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
59
+{
60
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
61
+}
58
+
62
+
59
/*
63
/*
60
* Naming convention for isar_feature functions:
64
* 64-bit feature tests via id registers.
61
* Functions which test 32-bit ID registers should have _aa32_ in
65
*/
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
67
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
68
}
69
70
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
71
+{
72
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
73
+}
74
+
75
/*
76
* Feature tests for "does this exist in either 32-bit or 64-bit?"
77
*/
78
diff --git a/target/arm/internals.h b/target/arm/internals.h
63
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
80
--- a/target/arm/internals.h
65
+++ b/linux-user/mmap.c
81
+++ b/target/arm/internals.h
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
82
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
83
if (isar_feature_aa32_dit(id)) {
68
| (prot & PROT_EXEC ? PROT_READ : 0);
84
valid |= CPSR_DIT;
69
85
}
70
+#ifdef TARGET_AARCH64
86
+ if (isar_feature_aa32_ssbs(id)) {
71
+ /*
87
+ valid |= CPSR_SSBS;
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
88
+ }
73
+ * Since this is the unusual case, don't bother checking unless
89
74
+ * the bit has been requested. If set and valid, record the bit
90
return valid;
75
+ * within QEMU's page_flags.
91
}
76
+ */
92
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
77
+ if (prot & TARGET_PROT_BTI) {
93
if (isar_feature_aa64_dit(id)) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
94
valid |= PSTATE_DIT;
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
95
}
80
+ valid |= TARGET_PROT_BTI;
96
+ if (isar_feature_aa64_ssbs(id)) {
81
+ page_flags |= PAGE_BTI;
97
+ valid |= PSTATE_SSBS;
98
+ }
99
if (isar_feature_aa64_mte(id)) {
100
valid |= PSTATE_TCO;
101
}
102
diff --git a/target/arm/helper.c b/target/arm/helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/helper.c
105
+++ b/target/arm/helper.c
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dit_reginfo = {
107
.readfn = aa64_dit_read, .writefn = aa64_dit_write
108
};
109
110
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
111
+{
112
+ return env->pstate & PSTATE_SSBS;
113
+}
114
+
115
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
+ uint64_t value)
117
+{
118
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
119
+}
120
+
121
+static const ARMCPRegInfo ssbs_reginfo = {
122
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
124
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
125
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
126
+};
127
+
128
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
129
const ARMCPRegInfo *ri,
130
bool isread)
131
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
132
if (cpu_isar_feature(aa64_dit, cpu)) {
133
define_one_arm_cp_reg(cpu, &dit_reginfo);
134
}
135
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
136
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
137
+ }
138
139
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
140
define_arm_cp_regs(cpu, vhe_reginfo);
141
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
142
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
143
env->daif |= mask;
144
145
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
146
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
147
+ env->uncached_cpsr |= CPSR_SSBS;
148
+ } else {
149
+ env->uncached_cpsr &= ~CPSR_SSBS;
82
+ }
150
+ }
83
+ }
151
+ }
84
+#endif
85
+
152
+
86
return prot & ~valid ? 0 : page_flags;
153
if (new_mode == ARM_CPU_MODE_HYP) {
87
}
154
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
88
155
env->elr_el[2] = env->regs[15];
156
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
157
new_mode |= PSTATE_TCO;
158
}
159
160
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
161
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
162
+ new_mode |= PSTATE_SSBS;
163
+ } else {
164
+ new_mode &= ~PSTATE_SSBS;
165
+ }
166
+ }
167
+
168
pstate_write(env, PSTATE_DAIF | new_mode);
169
env->aarch64 = 1;
170
aarch64_restore_sp(env, new_el);
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
171
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
172
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
173
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
174
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
175
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
94
*/
176
tcg_temp_free_i32(t1);
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
177
break;
96
{
178
97
-#ifdef CONFIG_USER_ONLY
179
+ case 0x19: /* SSBS */
98
- return false; /* FIXME */
180
+ if (!dc_isar_feature(aa64_ssbs, s)) {
99
-#else
181
+ goto do_unallocated;
100
uint64_t addr = s->base.pc_first;
182
+ }
101
+#ifdef CONFIG_USER_ONLY
183
+ if (crm & 1) {
102
+ return page_get_flags(addr) & PAGE_BTI;
184
+ set_pstate_bits(PSTATE_SSBS);
103
+#else
185
+ } else {
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
186
+ clear_pstate_bits(PSTATE_SSBS);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
187
+ }
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
188
+ /* Don't need to rebuild hflags since SSBS is a nop */
189
+ break;
190
+
191
case 0x1a: /* DIT */
192
if (!dc_isar_feature(aa64_dit, s)) {
193
goto do_unallocated;
107
--
194
--
108
2.20.1
195
2.20.1
109
196
110
197
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
For BTI, we need to know if the executable is static or dynamic,
3
Set ID_AA64PFR1_EL1.SSBS to 2 and ID_PFR2.SSBS to 1.
4
which means looking for PT_INTERP earlier.
5
4
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20210216224543.16142-3-rebecca@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
10
target/arm/cpu64.c | 5 +++++
12
1 file changed, 31 insertions(+), 29 deletions(-)
11
1 file changed, 5 insertions(+)
13
12
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
15
--- a/target/arm/cpu64.c
17
+++ b/linux-user/elfload.c
16
+++ b/target/arm/cpu64.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
19
18
20
mmap_lock();
19
t = cpu->isar.id_aa64pfr1;
21
20
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
22
- /* Find the maximum size of the image and allocate an appropriate
21
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
23
- amount of memory to handle that. */
22
/*
24
+ /*
23
* Begin with full support for MTE. This will be downgraded to MTE=0
25
+ * Find the maximum size of the image and allocate an appropriate
24
* during realize if the board provides no tag memory, much like
26
+ * amount of memory to handle that. Locate the interpreter, if any.
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
27
+ */
26
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
28
loaddr = -1, hiaddr = 0;
27
cpu->isar.id_pfr0 = u;
29
info->alignment = 0;
28
30
for (i = 0; i < ehdr->e_phnum; ++i) {
29
+ u = cpu->isar.id_pfr2;
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
30
+ u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
32
}
31
+ cpu->isar.id_pfr2 = u;
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
32
+
38
+ if (*pinterp_name) {
33
u = cpu->isar.id_mmfr3;
39
+ errmsg = "Multiple PT_INTERP entries";
34
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
40
+ goto exit_errmsg;
35
cpu->isar.id_mmfr3 = u;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
36
--
100
2.20.1
37
2.20.1
101
38
102
39
diff view generated by jsdifflib
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
squash the ID register fields so that we don't advertise it to the
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
5
2
6
* A-profile only fields should not be zeroed on M-profile:
3
Enable FEAT_SSBS for the "max" 32-bit CPU.
7
- MVFR0.FPSHVEC,FPTRAP
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
4
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
15
support on an M-profile CPU (where has_neon is always false). This
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210216224543.16142-4-rebecca@nuviainc.com
8
[PMM: fix typo causing compilation failure]
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
10
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
11
target/arm/cpu.c | 4 ++++
24
1 file changed, 18 insertions(+), 11 deletions(-)
12
1 file changed, 4 insertions(+)
25
13
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
16
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
31
u = cpu->isar.mvfr0;
19
t = cpu->isar.id_pfr0;
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
20
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
21
cpu->isar.id_pfr0 = t;
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
22
+
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
23
+ t = cpu->isar.id_pfr2;
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
24
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
25
+ cpu->isar.id_pfr2 = t;
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
42
+ }
43
cpu->isar.mvfr0 = u;
44
45
u = cpu->isar.mvfr1;
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
51
+ }
52
cpu->isar.mvfr1 = u;
53
54
u = cpu->isar.mvfr2;
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
57
cpu->isar.id_isar6 = u;
58
59
- u = cpu->isar.mvfr1;
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
64
- cpu->isar.mvfr1 = u;
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
66
+ u = cpu->isar.mvfr1;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
71
+ cpu->isar.mvfr1 = u;
72
73
- u = cpu->isar.mvfr2;
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
75
- cpu->isar.mvfr2 = u;
76
+ u = cpu->isar.mvfr2;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
78
+ cpu->isar.mvfr2 = u;
79
+ }
80
}
26
}
81
27
#endif
82
if (!cpu->has_neon && !cpu->has_vfp) {
28
}
83
--
29
--
84
2.20.1
30
2.20.1
85
31
86
32
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Doug Evans <dje@google.com>
2
2
3
The note test requires gcc 10 for -mbranch-protection=standard.
3
This is a 10/100 ethernet device that has several features.
4
The mmap test uses PROT_BTI and does not require special compiler support.
4
Only the ones needed by the Linux driver have been implemented.
5
See npcm7xx_emc.c for a list of unimplemented features.
5
6
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Doug Evans <dje@google.com>
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
10
Message-id: 20210218212453.831406-2-dje@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
13
include/hw/net/npcm7xx_emc.h | 286 ++++++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
14
hw/net/npcm7xx_emc.c | 857 +++++++++++++++++++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
15
hw/net/meson.build | 1 +
15
tests/tcg/aarch64/Makefile.target | 10 +++
16
hw/net/trace-events | 17 +
16
tests/tcg/configure.sh | 4 ++
17
4 files changed, 1161 insertions(+)
17
5 files changed, 235 insertions(+)
18
create mode 100644 include/hw/net/npcm7xx_emc.h
18
create mode 100644 tests/tcg/aarch64/bti-1.c
19
create mode 100644 hw/net/npcm7xx_emc.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
21
20
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
21
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
23
new file mode 100644
22
new file mode 100644
24
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
25
--- /dev/null
24
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
25
+++ b/include/hw/net/npcm7xx_emc.h
27
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
28
+/*
27
+/*
29
+ * Branch target identification, basic notskip cases.
28
+ * Nuvoton NPCM7xx EMC Module
29
+ *
30
+ * Copyright 2020 Google LLC
31
+ *
32
+ * This program is free software; you can redistribute it and/or modify it
33
+ * under the terms of the GNU General Public License as published by the
34
+ * Free Software Foundation; either version 2 of the License, or
35
+ * (at your option) any later version.
36
+ *
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * for more details.
30
+ */
41
+ */
31
+
42
+
32
+#include "bti-crt.inc.c"
43
+#ifndef NPCM7XX_EMC_H
33
+
44
+#define NPCM7XX_EMC_H
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
45
+
35
+{
46
+#include "hw/irq.h"
36
+ uc->uc_mcontext.pc += 8;
47
+#include "hw/sysbus.h"
37
+ uc->uc_mcontext.pstate = 1;
48
+#include "net/net.h"
38
+}
49
+
39
+
50
+/* 32-bit register indices. */
40
+#define NOP "nop"
51
+enum NPCM7xxPWMRegister {
41
+#define BTI_N "hint #32"
52
+ /* Control registers. */
42
+#define BTI_C "hint #34"
53
+ REG_CAMCMR,
43
+#define BTI_J "hint #36"
54
+ REG_CAMEN,
44
+#define BTI_JC "hint #38"
55
+
45
+
56
+ /* There are 16 CAMn[ML] registers. */
46
+#define BTYPE_1(DEST) \
57
+ REG_CAMM_BASE,
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
58
+ REG_CAML_BASE,
48
+ : "=r"(skipped) : : "x16")
59
+ REG_CAMML_LAST = 0x21,
49
+
60
+
50
+#define BTYPE_2(DEST) \
61
+ REG_TXDLSA = 0x22,
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
62
+ REG_RXDLSA,
52
+ : "=r"(skipped) : : "x16", "x30")
63
+ REG_MCMDR,
53
+
64
+ REG_MIID,
54
+#define BTYPE_3(DEST) \
65
+ REG_MIIDA,
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
66
+ REG_FFTCR,
56
+ : "=r"(skipped) : : "x15")
67
+ REG_TSDR,
57
+
68
+ REG_RSDR,
58
+#define TEST(WHICH, DEST, EXPECT) \
69
+ REG_DMARFC,
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
70
+ REG_MIEN,
60
+
71
+
61
+
72
+ /* Status registers. */
62
+int main()
73
+ REG_MISTA,
63
+{
74
+ REG_MGSTA,
64
+ int fail = 0;
75
+ REG_MPCNT,
65
+ int skipped;
76
+ REG_MRPC,
66
+
77
+ REG_MRPCC,
67
+ /* Signal-like with SA_SIGINFO. */
78
+ REG_MREPC,
68
+ signal_info(SIGILL, skip2_sigill);
79
+ REG_DMARFS,
69
+
80
+ REG_CTXDSA,
70
+ TEST(BTYPE_1, NOP, 1);
81
+ REG_CTXBSA,
71
+ TEST(BTYPE_1, BTI_N, 1);
82
+ REG_CRXDSA,
72
+ TEST(BTYPE_1, BTI_C, 0);
83
+ REG_CRXBSA,
73
+ TEST(BTYPE_1, BTI_J, 0);
84
+
74
+ TEST(BTYPE_1, BTI_JC, 0);
85
+ NPCM7XX_NUM_EMC_REGS,
75
+
86
+};
76
+ TEST(BTYPE_2, NOP, 1);
87
+
77
+ TEST(BTYPE_2, BTI_N, 1);
88
+/* REG_CAMCMR fields */
78
+ TEST(BTYPE_2, BTI_C, 0);
89
+/* Enable CAM Compare */
79
+ TEST(BTYPE_2, BTI_J, 1);
90
+#define REG_CAMCMR_ECMP (1 << 4)
80
+ TEST(BTYPE_2, BTI_JC, 0);
91
+/* Complement CAM Compare */
81
+
92
+#define REG_CAMCMR_CCAM (1 << 3)
82
+ TEST(BTYPE_3, NOP, 1);
93
+/* Accept Broadcast Packet */
83
+ TEST(BTYPE_3, BTI_N, 1);
94
+#define REG_CAMCMR_ABP (1 << 2)
84
+ TEST(BTYPE_3, BTI_C, 1);
95
+/* Accept Multicast Packet */
85
+ TEST(BTYPE_3, BTI_J, 0);
96
+#define REG_CAMCMR_AMP (1 << 1)
86
+ TEST(BTYPE_3, BTI_JC, 0);
97
+/* Accept Unicast Packet */
87
+
98
+#define REG_CAMCMR_AUP (1 << 0)
88
+ return fail;
99
+
89
+}
100
+/* REG_MCMDR fields */
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
101
+/* Software Reset */
102
+#define REG_MCMDR_SWR (1 << 24)
103
+/* Internal Loopback Select */
104
+#define REG_MCMDR_LBK (1 << 21)
105
+/* Operation Mode Select */
106
+#define REG_MCMDR_OPMOD (1 << 20)
107
+/* Enable MDC Clock Generation */
108
+#define REG_MCMDR_ENMDC (1 << 19)
109
+/* Full-Duplex Mode Select */
110
+#define REG_MCMDR_FDUP (1 << 18)
111
+/* Enable SQE Checking */
112
+#define REG_MCMDR_ENSEQ (1 << 17)
113
+/* Send PAUSE Frame */
114
+#define REG_MCMDR_SDPZ (1 << 16)
115
+/* No Defer */
116
+#define REG_MCMDR_NDEF (1 << 9)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Strip CRC Checksum */
120
+#define REG_MCMDR_SPCRC (1 << 5)
121
+/* Accept CRC Error Packet */
122
+#define REG_MCMDR_AEP (1 << 4)
123
+/* Accept Control Packet */
124
+#define REG_MCMDR_ACP (1 << 3)
125
+/* Accept Runt Packet */
126
+#define REG_MCMDR_ARP (1 << 2)
127
+/* Accept Long Packet */
128
+#define REG_MCMDR_ALP (1 << 1)
129
+/* Frame Reception On */
130
+#define REG_MCMDR_RXON (1 << 0)
131
+
132
+/* REG_MIEN fields */
133
+/* Enable Transmit Descriptor Unavailable Interrupt */
134
+#define REG_MIEN_ENTDU (1 << 23)
135
+/* Enable Transmit Completion Interrupt */
136
+#define REG_MIEN_ENTXCP (1 << 18)
137
+/* Enable Transmit Interrupt */
138
+#define REG_MIEN_ENTXINTR (1 << 16)
139
+/* Enable Receive Descriptor Unavailable Interrupt */
140
+#define REG_MIEN_ENRDU (1 << 10)
141
+/* Enable Receive Good Interrupt */
142
+#define REG_MIEN_ENRXGD (1 << 4)
143
+/* Enable Receive Interrupt */
144
+#define REG_MIEN_ENRXINTR (1 << 0)
145
+
146
+/* REG_MISTA fields */
147
+/* TODO: Add error fields and support simulated errors? */
148
+/* Transmit Bus Error Interrupt */
149
+#define REG_MISTA_TXBERR (1 << 24)
150
+/* Transmit Descriptor Unavailable Interrupt */
151
+#define REG_MISTA_TDU (1 << 23)
152
+/* Transmit Completion Interrupt */
153
+#define REG_MISTA_TXCP (1 << 18)
154
+/* Transmit Interrupt */
155
+#define REG_MISTA_TXINTR (1 << 16)
156
+/* Receive Bus Error Interrupt */
157
+#define REG_MISTA_RXBERR (1 << 11)
158
+/* Receive Descriptor Unavailable Interrupt */
159
+#define REG_MISTA_RDU (1 << 10)
160
+/* DMA Early Notification Interrupt */
161
+#define REG_MISTA_DENI (1 << 9)
162
+/* Maximum Frame Length Interrupt */
163
+#define REG_MISTA_DFOI (1 << 8)
164
+/* Receive Good Interrupt */
165
+#define REG_MISTA_RXGD (1 << 4)
166
+/* Packet Too Long Interrupt */
167
+#define REG_MISTA_PTLE (1 << 3)
168
+/* Receive Interrupt */
169
+#define REG_MISTA_RXINTR (1 << 0)
170
+
171
+/* REG_MGSTA fields */
172
+/* Transmission Halted */
173
+#define REG_MGSTA_TXHA (1 << 11)
174
+/* Receive Halted */
175
+#define REG_MGSTA_RXHA (1 << 11)
176
+
177
+/* REG_DMARFC fields */
178
+/* Maximum Receive Frame Length */
179
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
180
+
181
+/* REG MIIDA fields */
182
+/* Busy Bit */
183
+#define REG_MIIDA_BUSY (1 << 17)
184
+
185
+/* Transmit and receive descriptors */
186
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
187
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
188
+
189
+struct NPCM7xxEMCTxDesc {
190
+ uint32_t flags;
191
+ uint32_t txbsa;
192
+ uint32_t status_and_length;
193
+ uint32_t ntxdsa;
194
+};
195
+
196
+struct NPCM7xxEMCRxDesc {
197
+ uint32_t status_and_length;
198
+ uint32_t rxbsa;
199
+ uint32_t reserved;
200
+ uint32_t nrxdsa;
201
+};
202
+
203
+/* NPCM7xxEMCTxDesc.flags values */
204
+/* Owner: 0 = cpu, 1 = emc */
205
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
206
+/* Transmit interrupt enable */
207
+#define TX_DESC_FLAG_INTEN (1 << 2)
208
+/* CRC append */
209
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
210
+/* Padding enable */
211
+#define TX_DESC_FLAG_PADEN (1 << 0)
212
+
213
+/* NPCM7xxEMCTxDesc.status_and_length values */
214
+/* Collision count */
215
+#define TX_DESC_STATUS_CCNT_SHIFT 28
216
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
217
+/* SQE error */
218
+#define TX_DESC_STATUS_SQE (1 << 26)
219
+/* Transmission paused */
220
+#define TX_DESC_STATUS_PAU (1 << 25)
221
+/* P transmission halted */
222
+#define TX_DESC_STATUS_TXHA (1 << 24)
223
+/* Late collision */
224
+#define TX_DESC_STATUS_LC (1 << 23)
225
+/* Transmission abort */
226
+#define TX_DESC_STATUS_TXABT (1 << 22)
227
+/* No carrier sense */
228
+#define TX_DESC_STATUS_NCS (1 << 21)
229
+/* Defer exceed */
230
+#define TX_DESC_STATUS_EXDEF (1 << 20)
231
+/* Transmission complete */
232
+#define TX_DESC_STATUS_TXCP (1 << 19)
233
+/* Transmission deferred */
234
+#define TX_DESC_STATUS_DEF (1 << 17)
235
+/* Transmit interrupt */
236
+#define TX_DESC_STATUS_TXINTR (1 << 16)
237
+
238
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
239
+
240
+/* Transmit buffer start address */
241
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
242
+
243
+/* Next transmit descriptor start address */
244
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
245
+
246
+/* NPCM7xxEMCRxDesc.status_and_length values */
247
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
248
+#define RX_DESC_STATUS_OWNER_SHIFT 30
249
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
250
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
251
+/* Runt packet */
252
+#define RX_DESC_STATUS_RP (1 << 22)
253
+/* Alignment error */
254
+#define RX_DESC_STATUS_ALIE (1 << 21)
255
+/* Frame reception complete */
256
+#define RX_DESC_STATUS_RXGD (1 << 20)
257
+/* Packet too long */
258
+#define RX_DESC_STATUS_PTLE (1 << 19)
259
+/* CRC error */
260
+#define RX_DESC_STATUS_CRCE (1 << 17)
261
+/* Receive interrupt */
262
+#define RX_DESC_STATUS_RXINTR (1 << 16)
263
+
264
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
265
+
266
+/* Receive buffer start address */
267
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
268
+
269
+/* Next receive descriptor start address */
270
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
271
+
272
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
273
+#define MIN_PACKET_LENGTH 64
274
+
275
+struct NPCM7xxEMCState {
276
+ /*< private >*/
277
+ SysBusDevice parent;
278
+ /*< public >*/
279
+
280
+ MemoryRegion iomem;
281
+
282
+ qemu_irq tx_irq;
283
+ qemu_irq rx_irq;
284
+
285
+ NICState *nic;
286
+ NICConf conf;
287
+
288
+ /* 0 or 1, for log messages */
289
+ uint8_t emc_num;
290
+
291
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
292
+
293
+ /*
294
+ * tx is active. Set to true by TSDR and then switches off when out of
295
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
296
+ */
297
+ bool tx_active;
298
+
299
+ /*
300
+ * rx is active. Set to true by RSDR and then switches off when out of
301
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
302
+ */
303
+ bool rx_active;
304
+};
305
+
306
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
307
+
308
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
309
+#define NPCM7XX_EMC(obj) \
310
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
311
+
312
+#endif /* NPCM7XX_EMC_H */
313
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
91
new file mode 100644
314
new file mode 100644
92
index XXXXXXX..XXXXXXX
315
index XXXXXXX..XXXXXXX
93
--- /dev/null
316
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
317
+++ b/hw/net/npcm7xx_emc.c
95
@@ -XXX,XX +XXX,XX @@
318
@@ -XXX,XX +XXX,XX @@
96
+/*
319
+/*
97
+ * Branch target identification, basic notskip cases.
320
+ * Nuvoton NPCM7xx EMC Module
321
+ *
322
+ * Copyright 2020 Google LLC
323
+ *
324
+ * This program is free software; you can redistribute it and/or modify it
325
+ * under the terms of the GNU General Public License as published by the
326
+ * Free Software Foundation; either version 2 of the License, or
327
+ * (at your option) any later version.
328
+ *
329
+ * This program is distributed in the hope that it will be useful, but WITHOUT
330
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
331
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
332
+ * for more details.
333
+ *
334
+ * Unsupported/unimplemented features:
335
+ * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported
336
+ * - Only CAM0 is supported, CAM[1-15] are not
337
+ * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes
338
+ * - MII is not implemented, MIIDA.BUSY and MIID always return zero
339
+ * - MCMDR.LBK is not implemented
340
+ * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported
341
+ * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored
342
+ * - MGSTA.SQE is not supported
343
+ * - pause and control frames are not implemented
344
+ * - MGSTA.CCNT is not supported
345
+ * - MPCNT, DMARFS are not implemented
98
+ */
346
+ */
99
+
347
+
100
+#include <stdio.h>
348
+#include "qemu/osdep.h"
101
+#include <signal.h>
349
+
102
+#include <string.h>
350
+/* For crc32 */
103
+#include <unistd.h>
351
+#include <zlib.h>
104
+#include <sys/mman.h>
352
+
105
+
353
+#include "qemu-common.h"
106
+#ifndef PROT_BTI
354
+#include "hw/irq.h"
107
+#define PROT_BTI 0x10
355
+#include "hw/qdev-clock.h"
108
+#endif
356
+#include "hw/qdev-properties.h"
109
+
357
+#include "hw/net/npcm7xx_emc.h"
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
358
+#include "net/eth.h"
111
+{
359
+#include "migration/vmstate.h"
112
+ ucontext_t *uc = vuc;
360
+#include "qemu/bitops.h"
113
+ uc->uc_mcontext.pc += 8;
361
+#include "qemu/error-report.h"
114
+ uc->uc_mcontext.pstate = 1;
362
+#include "qemu/log.h"
115
+}
363
+#include "qemu/module.h"
116
+
364
+#include "qemu/units.h"
117
+#define NOP "nop"
365
+#include "sysemu/dma.h"
118
+#define BTI_N "hint #32"
366
+#include "trace.h"
119
+#define BTI_C "hint #34"
367
+
120
+#define BTI_J "hint #36"
368
+#define CRC_LENGTH 4
121
+#define BTI_JC "hint #38"
369
+
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
181
+int main()
182
+{
183
+ struct sigaction sa;
184
+
185
+ void *p = mmap(0, getpagesize(),
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188
+ if (p == MAP_FAILED) {
189
+ perror("mmap");
190
+ return 1;
191
+ }
192
+
193
+ memset(&sa, 0, sizeof(sa));
194
+ sa.sa_sigaction = skip2_sigill;
195
+ sa.sa_flags = SA_SIGINFO;
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
197
+ perror("sigaction");
198
+ return 1;
199
+ }
200
+
201
+ memcpy(p, test_begin, test_end - test_begin);
202
+ return ((int (*)(void))p)();
203
+}
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
205
new file mode 100644
206
index XXXXXXX..XXXXXXX
207
--- /dev/null
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
209
@@ -XXX,XX +XXX,XX @@
210
+/*
370
+/*
211
+ * Minimal user-environment for testing BTI.
371
+ * The maximum size of a (layer 2) ethernet frame as defined by 802.3.
212
+ *
372
+ * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload)
213
+ * Normal libc is not (yet) built with BTI support enabled,
373
+ * This does not include an additional 4 for the vlan field (802.1q).
214
+ * and so could generate a BTI TRAP before ever reaching main.
215
+ */
374
+ */
216
+
375
+#define MAX_ETH_FRAME_SIZE 1518
217
+#include <stdlib.h>
376
+
218
+#include <signal.h>
377
+static const char *emc_reg_name(int regno)
219
+#include <ucontext.h>
378
+{
220
+#include <asm/unistd.h>
379
+#define REG(name) case REG_ ## name: return #name;
221
+
380
+ switch (regno) {
222
+int main(void);
381
+ REG(CAMCMR)
223
+
382
+ REG(CAMEN)
224
+void _start(void)
383
+ REG(TXDLSA)
225
+{
384
+ REG(RXDLSA)
226
+ exit(main());
385
+ REG(MCMDR)
227
+}
386
+ REG(MIID)
228
+
387
+ REG(MIIDA)
229
+void exit(int ret)
388
+ REG(FFTCR)
230
+{
389
+ REG(TSDR)
231
+ register int x0 __asm__("x0") = ret;
390
+ REG(RSDR)
232
+ register int x8 __asm__("x8") = __NR_exit;
391
+ REG(DMARFC)
233
+
392
+ REG(MIEN)
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
393
+ REG(MISTA)
235
+ __builtin_unreachable();
394
+ REG(MGSTA)
236
+}
395
+ REG(MPCNT)
237
+
396
+ REG(MRPC)
238
+/*
397
+ REG(MRPCC)
239
+ * Irritatingly, the user API struct sigaction does not match the
398
+ REG(MREPC)
240
+ * kernel API struct sigaction. So for simplicity, isolate the
399
+ REG(DMARFS)
241
+ * kernel ABI here, and make this act like signal.
400
+ REG(CTXDSA)
242
+ */
401
+ REG(CTXBSA)
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
402
+ REG(CRXDSA)
244
+{
403
+ REG(CRXBSA)
245
+ struct kernel_sigaction {
404
+ case REG_CAMM_BASE + 0: return "CAM0M";
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
405
+ case REG_CAML_BASE + 0: return "CAM0L";
247
+ unsigned long flags;
406
+ case REG_CAMM_BASE + 2 ... REG_CAMML_LAST:
248
+ unsigned long restorer;
407
+ /* Only CAM0 is supported, fold the others into something simple. */
249
+ unsigned long mask;
408
+ if (regno & 1) {
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
409
+ return "CAM<n>L";
251
+
410
+ } else {
252
+ register int x0 __asm__("x0") = sig;
411
+ return "CAM<n>M";
253
+ register void *x1 __asm__("x1") = &sa;
412
+ }
254
+ register void *x2 __asm__("x2") = 0;
413
+ default: return "UNKNOWN";
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
414
+ }
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
415
+#undef REG
257
+
416
+}
258
+ asm volatile("svc #0"
417
+
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
418
+static void emc_reset(NPCM7xxEMCState *emc)
260
+}
419
+{
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
420
+ trace_npcm7xx_emc_reset(emc->emc_num);
421
+
422
+ memset(&emc->regs[0], 0, sizeof(emc->regs));
423
+
424
+ /* These regs have non-zero reset values. */
425
+ emc->regs[REG_TXDLSA] = 0xfffffffc;
426
+ emc->regs[REG_RXDLSA] = 0xfffffffc;
427
+ emc->regs[REG_MIIDA] = 0x00900000;
428
+ emc->regs[REG_FFTCR] = 0x0101;
429
+ emc->regs[REG_DMARFC] = 0x0800;
430
+ emc->regs[REG_MPCNT] = 0x7fff;
431
+
432
+ emc->tx_active = false;
433
+ emc->rx_active = false;
434
+}
435
+
436
+static void npcm7xx_emc_reset(DeviceState *dev)
437
+{
438
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
439
+ emc_reset(emc);
440
+}
441
+
442
+static void emc_soft_reset(NPCM7xxEMCState *emc)
443
+{
444
+ /*
445
+ * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a
446
+ * soft reset, but does not go into further detail. For now, KISS.
447
+ */
448
+ uint32_t mcmdr = emc->regs[REG_MCMDR];
449
+ emc_reset(emc);
450
+ emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD);
451
+
452
+ qemu_set_irq(emc->tx_irq, 0);
453
+ qemu_set_irq(emc->rx_irq, 0);
454
+}
455
+
456
+static void emc_set_link(NetClientState *nc)
457
+{
458
+ /* Nothing to do yet. */
459
+}
460
+
461
+/* MISTA.TXINTR is the union of the individual bits with their enables. */
462
+static void emc_update_mista_txintr(NPCM7xxEMCState *emc)
463
+{
464
+ /* Only look at the bits we support. */
465
+ uint32_t mask = (REG_MISTA_TXBERR |
466
+ REG_MISTA_TDU |
467
+ REG_MISTA_TXCP);
468
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
469
+ emc->regs[REG_MISTA] |= REG_MISTA_TXINTR;
470
+ } else {
471
+ emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR;
472
+ }
473
+}
474
+
475
+/* MISTA.RXINTR is the union of the individual bits with their enables. */
476
+static void emc_update_mista_rxintr(NPCM7xxEMCState *emc)
477
+{
478
+ /* Only look at the bits we support. */
479
+ uint32_t mask = (REG_MISTA_RXBERR |
480
+ REG_MISTA_RDU |
481
+ REG_MISTA_RXGD);
482
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
483
+ emc->regs[REG_MISTA] |= REG_MISTA_RXINTR;
484
+ } else {
485
+ emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR;
486
+ }
487
+}
488
+
489
+/* N.B. emc_update_mista_txintr must have already been called. */
490
+static void emc_update_tx_irq(NPCM7xxEMCState *emc)
491
+{
492
+ int level = !!(emc->regs[REG_MISTA] &
493
+ emc->regs[REG_MIEN] &
494
+ REG_MISTA_TXINTR);
495
+ trace_npcm7xx_emc_update_tx_irq(level);
496
+ qemu_set_irq(emc->tx_irq, level);
497
+}
498
+
499
+/* N.B. emc_update_mista_rxintr must have already been called. */
500
+static void emc_update_rx_irq(NPCM7xxEMCState *emc)
501
+{
502
+ int level = !!(emc->regs[REG_MISTA] &
503
+ emc->regs[REG_MIEN] &
504
+ REG_MISTA_RXINTR);
505
+ trace_npcm7xx_emc_update_rx_irq(level);
506
+ qemu_set_irq(emc->rx_irq, level);
507
+}
508
+
509
+/* Update IRQ states due to changes in MIEN,MISTA. */
510
+static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc)
511
+{
512
+ emc_update_mista_txintr(emc);
513
+ emc_update_tx_irq(emc);
514
+
515
+ emc_update_mista_rxintr(emc);
516
+ emc_update_rx_irq(emc);
517
+}
518
+
519
+static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc)
520
+{
521
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
522
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
523
+ HWADDR_PRIx "\n", __func__, addr);
524
+ return -1;
525
+ }
526
+ desc->flags = le32_to_cpu(desc->flags);
527
+ desc->txbsa = le32_to_cpu(desc->txbsa);
528
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
529
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
530
+ return 0;
531
+}
532
+
533
+static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr)
534
+{
535
+ NPCM7xxEMCTxDesc le_desc;
536
+
537
+ le_desc.flags = cpu_to_le32(desc->flags);
538
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
539
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
540
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
541
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
542
+ sizeof(le_desc))) {
543
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
544
+ HWADDR_PRIx "\n", __func__, addr);
545
+ return -1;
546
+ }
547
+ return 0;
548
+}
549
+
550
+static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc)
551
+{
552
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
553
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
554
+ HWADDR_PRIx "\n", __func__, addr);
555
+ return -1;
556
+ }
557
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
558
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
559
+ desc->reserved = le32_to_cpu(desc->reserved);
560
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
561
+ return 0;
562
+}
563
+
564
+static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr)
565
+{
566
+ NPCM7xxEMCRxDesc le_desc;
567
+
568
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
569
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
570
+ le_desc.reserved = cpu_to_le32(desc->reserved);
571
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
572
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
573
+ sizeof(le_desc))) {
574
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
575
+ HWADDR_PRIx "\n", __func__, addr);
576
+ return -1;
577
+ }
578
+ return 0;
579
+}
580
+
581
+static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags)
582
+{
583
+ trace_npcm7xx_emc_set_mista(flags);
584
+ emc->regs[REG_MISTA] |= flags;
585
+ if (extract32(flags, 16, 16)) {
586
+ emc_update_mista_txintr(emc);
587
+ }
588
+ if (extract32(flags, 0, 16)) {
589
+ emc_update_mista_rxintr(emc);
590
+ }
591
+}
592
+
593
+static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag)
594
+{
595
+ emc->tx_active = false;
596
+ emc_set_mista(emc, mista_flag);
597
+}
598
+
599
+static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
600
+{
601
+ emc->rx_active = false;
602
+ emc_set_mista(emc, mista_flag);
603
+}
604
+
605
+static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
606
+ const NPCM7xxEMCTxDesc *tx_desc,
607
+ uint32_t desc_addr)
608
+{
609
+ /* Update the current descriptor, if only to reset the owner flag. */
610
+ if (emc_write_tx_desc(tx_desc, desc_addr)) {
611
+ /*
612
+ * We just read it so this shouldn't generally happen.
613
+ * Error already reported.
614
+ */
615
+ emc_set_mista(emc, REG_MISTA_TXBERR);
616
+ }
617
+ emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa);
618
+}
619
+
620
+static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc,
621
+ const NPCM7xxEMCRxDesc *rx_desc,
622
+ uint32_t desc_addr)
623
+{
624
+ /* Update the current descriptor, if only to reset the owner flag. */
625
+ if (emc_write_rx_desc(rx_desc, desc_addr)) {
626
+ /*
627
+ * We just read it so this shouldn't generally happen.
628
+ * Error already reported.
629
+ */
630
+ emc_set_mista(emc, REG_MISTA_RXBERR);
631
+ }
632
+ emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa);
633
+}
634
+
635
+static void emc_try_send_next_packet(NPCM7xxEMCState *emc)
636
+{
637
+ /* Working buffer for sending out packets. Most packets fit in this. */
638
+#define TX_BUFFER_SIZE 2048
639
+ uint8_t tx_send_buffer[TX_BUFFER_SIZE];
640
+ uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]);
641
+ NPCM7xxEMCTxDesc tx_desc;
642
+ uint32_t next_buf_addr, length;
643
+ uint8_t *buf;
644
+ g_autofree uint8_t *malloced_buf = NULL;
645
+
646
+ if (emc_read_tx_desc(desc_addr, &tx_desc)) {
647
+ /* Error reading descriptor, already reported. */
648
+ emc_halt_tx(emc, REG_MISTA_TXBERR);
649
+ emc_update_tx_irq(emc);
650
+ return;
651
+ }
652
+
653
+ /* Nothing we can do if we don't own the descriptor. */
654
+ if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) {
655
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
656
+ emc_halt_tx(emc, REG_MISTA_TDU);
657
+ emc_update_tx_irq(emc);
658
+ return;
659
+ }
660
+
661
+ /* Give the descriptor back regardless of what happens. */
662
+ tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK;
663
+ tx_desc.status_and_length &= 0xffff;
664
+
665
+ /*
666
+ * Despite the h/w documentation saying the tx buffer is word aligned,
667
+ * the linux driver does not word align the buffer. There is value in not
668
+ * aligning the buffer: See the description of NET_IP_ALIGN in linux
669
+ * kernel sources.
670
+ */
671
+ next_buf_addr = tx_desc.txbsa;
672
+ emc->regs[REG_CTXBSA] = next_buf_addr;
673
+ length = TX_DESC_PKT_LEN(tx_desc.status_and_length);
674
+ buf = &tx_send_buffer[0];
675
+
676
+ if (length > sizeof(tx_send_buffer)) {
677
+ malloced_buf = g_malloc(length);
678
+ buf = malloced_buf;
679
+ }
680
+
681
+ if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) {
682
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
683
+ __func__, next_buf_addr);
684
+ emc_set_mista(emc, REG_MISTA_TXBERR);
685
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
686
+ emc_update_tx_irq(emc);
687
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
688
+ return;
689
+ }
690
+
691
+ if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) {
692
+ memset(buf + length, 0, MIN_PACKET_LENGTH - length);
693
+ length = MIN_PACKET_LENGTH;
694
+ }
695
+
696
+ /* N.B. emc_receive can get called here. */
697
+ qemu_send_packet(qemu_get_queue(emc->nic), buf, length);
698
+ trace_npcm7xx_emc_sent_packet(length);
699
+
700
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXCP;
701
+ if (tx_desc.flags & TX_DESC_FLAG_INTEN) {
702
+ emc_set_mista(emc, REG_MISTA_TXCP);
703
+ }
704
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) {
705
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR;
706
+ }
707
+
708
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
709
+ emc_update_tx_irq(emc);
710
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
711
+}
712
+
713
+static bool emc_can_receive(NetClientState *nc)
714
+{
715
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
716
+
717
+ bool can_receive = emc->rx_active;
718
+ trace_npcm7xx_emc_can_receive(can_receive);
719
+ return can_receive;
720
+}
721
+
722
+/* If result is false then *fail_reason contains the reason. */
723
+static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf,
724
+ size_t len, const char **fail_reason)
725
+{
726
+ eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf));
727
+
728
+ switch (pkt_type) {
729
+ case ETH_PKT_BCAST:
730
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
731
+ return true;
732
+ } else {
733
+ *fail_reason = "Broadcast packet disabled";
734
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP);
735
+ }
736
+ case ETH_PKT_MCAST:
737
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
738
+ return true;
739
+ } else {
740
+ *fail_reason = "Multicast packet disabled";
741
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP);
742
+ }
743
+ case ETH_PKT_UCAST: {
744
+ bool matches;
745
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) {
746
+ return true;
747
+ }
748
+ matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) &&
749
+ /* We only support one CAM register, CAM0. */
750
+ (emc->regs[REG_CAMEN] & (1 << 0)) &&
751
+ memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0);
752
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
753
+ *fail_reason = "MACADDR matched, comparison complemented";
754
+ return !matches;
755
+ } else {
756
+ *fail_reason = "MACADDR didn't match";
757
+ return matches;
758
+ }
759
+ }
760
+ default:
761
+ g_assert_not_reached();
762
+ }
763
+}
764
+
765
+static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf,
766
+ size_t len)
767
+{
768
+ const char *fail_reason = NULL;
769
+ bool ok = emc_receive_filter1(emc, buf, len, &fail_reason);
770
+ if (!ok) {
771
+ trace_npcm7xx_emc_packet_filtered_out(fail_reason);
772
+ }
773
+ return ok;
774
+}
775
+
776
+static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
777
+{
778
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
779
+ const uint32_t len = len1;
780
+ size_t max_frame_len;
781
+ bool long_frame;
782
+ uint32_t desc_addr;
783
+ NPCM7xxEMCRxDesc rx_desc;
784
+ uint32_t crc;
785
+ uint8_t *crc_ptr;
786
+ uint32_t buf_addr;
787
+
788
+ trace_npcm7xx_emc_receiving_packet(len);
789
+
790
+ if (!emc_can_receive(nc)) {
791
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
792
+ return -1;
793
+ }
794
+
795
+ if (len < ETH_HLEN ||
796
+ /* Defensive programming: drop unsupportable large packets. */
797
+ len > 0xffff - CRC_LENGTH) {
798
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n",
799
+ __func__, len);
800
+ return len;
801
+ }
802
+
803
+ /*
804
+ * DENI is set if EMC received the Length/Type field of the incoming
805
+ * packet, so it will be set regardless of what happens next.
806
+ */
807
+ emc_set_mista(emc, REG_MISTA_DENI);
808
+
809
+ if (!emc_receive_filter(emc, buf, len)) {
810
+ emc_update_rx_irq(emc);
811
+ return len;
812
+ }
813
+
814
+ /* Huge frames (> DMARFC) are dropped. */
815
+ max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]);
816
+ if (len + CRC_LENGTH > max_frame_len) {
817
+ trace_npcm7xx_emc_packet_dropped(len);
818
+ emc_set_mista(emc, REG_MISTA_DFOI);
819
+ emc_update_rx_irq(emc);
820
+ return len;
821
+ }
822
+
823
+ /*
824
+ * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP
825
+ * is set.
826
+ */
827
+ long_frame = false;
828
+ if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) {
829
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) {
830
+ long_frame = true;
831
+ } else {
832
+ trace_npcm7xx_emc_packet_dropped(len);
833
+ emc_set_mista(emc, REG_MISTA_PTLE);
834
+ emc_update_rx_irq(emc);
835
+ return len;
836
+ }
837
+ }
838
+
839
+ desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]);
840
+ if (emc_read_rx_desc(desc_addr, &rx_desc)) {
841
+ /* Error reading descriptor, already reported. */
842
+ emc_halt_rx(emc, REG_MISTA_RXBERR);
843
+ emc_update_rx_irq(emc);
844
+ return len;
845
+ }
846
+
847
+ /* Nothing we can do if we don't own the descriptor. */
848
+ if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) {
849
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
850
+ emc_halt_rx(emc, REG_MISTA_RDU);
851
+ emc_update_rx_irq(emc);
852
+ return len;
853
+ }
854
+
855
+ crc = 0;
856
+ crc_ptr = (uint8_t *) &crc;
857
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
858
+ crc = cpu_to_be32(crc32(~0, buf, len));
859
+ }
860
+
861
+ /* Give the descriptor back regardless of what happens. */
862
+ rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK;
863
+
864
+ buf_addr = rx_desc.rxbsa;
865
+ emc->regs[REG_CRXBSA] = buf_addr;
866
+ if (dma_memory_write(&address_space_memory, buf_addr, buf, len) ||
867
+ (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) &&
868
+ dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr,
869
+ 4))) {
870
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n",
871
+ __func__);
872
+ emc_set_mista(emc, REG_MISTA_RXBERR);
873
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
874
+ emc_update_rx_irq(emc);
875
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
876
+ return len;
877
+ }
878
+
879
+ trace_npcm7xx_emc_received_packet(len);
880
+
881
+ /* Note: We've already verified len+4 <= 0xffff. */
882
+ rx_desc.status_and_length = len;
883
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
884
+ rx_desc.status_and_length += 4;
885
+ }
886
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXGD;
887
+ emc_set_mista(emc, REG_MISTA_RXGD);
888
+
889
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) {
890
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR;
891
+ }
892
+ if (long_frame) {
893
+ rx_desc.status_and_length |= RX_DESC_STATUS_PTLE;
894
+ }
895
+
896
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
897
+ emc_update_rx_irq(emc);
898
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
899
+ return len;
900
+}
901
+
902
+static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
903
+{
904
+ if (emc_can_receive(qemu_get_queue(emc->nic))) {
905
+ qemu_flush_queued_packets(qemu_get_queue(emc->nic));
906
+ }
907
+}
908
+
909
+static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
910
+{
911
+ NPCM7xxEMCState *emc = opaque;
912
+ uint32_t reg = offset / sizeof(uint32_t);
913
+ uint32_t result;
914
+
915
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
916
+ qemu_log_mask(LOG_GUEST_ERROR,
917
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
918
+ __func__, offset);
919
+ return 0;
920
+ }
921
+
922
+ switch (reg) {
923
+ case REG_MIID:
924
+ /*
925
+ * We don't implement MII. For determinism, always return zero as
926
+ * writes record the last value written for debugging purposes.
927
+ */
928
+ qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__);
929
+ result = 0;
930
+ break;
931
+ case REG_TSDR:
932
+ case REG_RSDR:
933
+ qemu_log_mask(LOG_GUEST_ERROR,
934
+ "%s: Read of write-only reg, %s/%d\n",
935
+ __func__, emc_reg_name(reg), reg);
936
+ return 0;
937
+ default:
938
+ result = emc->regs[reg];
939
+ break;
940
+ }
941
+
942
+ trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg);
943
+ return result;
944
+}
945
+
946
+static void npcm7xx_emc_write(void *opaque, hwaddr offset,
947
+ uint64_t v, unsigned size)
948
+{
949
+ NPCM7xxEMCState *emc = opaque;
950
+ uint32_t reg = offset / sizeof(uint32_t);
951
+ uint32_t value = v;
952
+
953
+ g_assert(size == sizeof(uint32_t));
954
+
955
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
956
+ qemu_log_mask(LOG_GUEST_ERROR,
957
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
958
+ __func__, offset);
959
+ return;
960
+ }
961
+
962
+ trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value);
963
+
964
+ switch (reg) {
965
+ case REG_CAMCMR:
966
+ emc->regs[reg] = value;
967
+ break;
968
+ case REG_CAMEN:
969
+ /* Only CAM0 is supported, don't pretend otherwise. */
970
+ if (value & ~1) {
971
+ qemu_log_mask(LOG_GUEST_ERROR,
972
+ "%s: Only CAM0 is supported, cannot enable others"
973
+ ": 0x%x\n",
974
+ __func__, value);
975
+ }
976
+ emc->regs[reg] = value & 1;
977
+ break;
978
+ case REG_CAMM_BASE + 0:
979
+ emc->regs[reg] = value;
980
+ emc->conf.macaddr.a[0] = value >> 24;
981
+ emc->conf.macaddr.a[1] = value >> 16;
982
+ emc->conf.macaddr.a[2] = value >> 8;
983
+ emc->conf.macaddr.a[3] = value >> 0;
984
+ break;
985
+ case REG_CAML_BASE + 0:
986
+ emc->regs[reg] = value;
987
+ emc->conf.macaddr.a[4] = value >> 24;
988
+ emc->conf.macaddr.a[5] = value >> 16;
989
+ break;
990
+ case REG_MCMDR: {
991
+ uint32_t prev;
992
+ if (value & REG_MCMDR_SWR) {
993
+ emc_soft_reset(emc);
994
+ /* On h/w the reset happens over multiple cycles. For now KISS. */
995
+ break;
996
+ }
997
+ prev = emc->regs[reg];
998
+ emc->regs[reg] = value;
999
+ /* Update tx state. */
1000
+ if (!(prev & REG_MCMDR_TXON) &&
1001
+ (value & REG_MCMDR_TXON)) {
1002
+ emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA];
1003
+ /*
1004
+ * Linux kernel turns TX on with CPU still holding descriptor,
1005
+ * which suggests we should wait for a write to TSDR before trying
1006
+ * to send a packet: so we don't send one here.
1007
+ */
1008
+ } else if ((prev & REG_MCMDR_TXON) &&
1009
+ !(value & REG_MCMDR_TXON)) {
1010
+ emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA;
1011
+ }
1012
+ if (!(value & REG_MCMDR_TXON)) {
1013
+ emc_halt_tx(emc, 0);
1014
+ }
1015
+ /* Update rx state. */
1016
+ if (!(prev & REG_MCMDR_RXON) &&
1017
+ (value & REG_MCMDR_RXON)) {
1018
+ emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA];
1019
+ } else if ((prev & REG_MCMDR_RXON) &&
1020
+ !(value & REG_MCMDR_RXON)) {
1021
+ emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
1022
+ }
1023
+ if (!(value & REG_MCMDR_RXON)) {
1024
+ emc_halt_rx(emc, 0);
1025
+ }
1026
+ break;
1027
+ }
1028
+ case REG_TXDLSA:
1029
+ case REG_RXDLSA:
1030
+ case REG_DMARFC:
1031
+ case REG_MIID:
1032
+ emc->regs[reg] = value;
1033
+ break;
1034
+ case REG_MIEN:
1035
+ emc->regs[reg] = value;
1036
+ emc_update_irq_from_reg_change(emc);
1037
+ break;
1038
+ case REG_MISTA:
1039
+ /* Clear the bits that have 1 in "value". */
1040
+ emc->regs[reg] &= ~value;
1041
+ emc_update_irq_from_reg_change(emc);
1042
+ break;
1043
+ case REG_MGSTA:
1044
+ /* Clear the bits that have 1 in "value". */
1045
+ emc->regs[reg] &= ~value;
1046
+ break;
1047
+ case REG_TSDR:
1048
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) {
1049
+ emc->tx_active = true;
1050
+ /* Keep trying to send packets until we run out. */
1051
+ while (emc->tx_active) {
1052
+ emc_try_send_next_packet(emc);
1053
+ }
1054
+ }
1055
+ break;
1056
+ case REG_RSDR:
1057
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
1058
+ emc->rx_active = true;
1059
+ emc_try_receive_next_packet(emc);
1060
+ }
1061
+ break;
1062
+ case REG_MIIDA:
1063
+ emc->regs[reg] = value & ~REG_MIIDA_BUSY;
1064
+ break;
1065
+ case REG_MRPC:
1066
+ case REG_MRPCC:
1067
+ case REG_MREPC:
1068
+ case REG_CTXDSA:
1069
+ case REG_CTXBSA:
1070
+ case REG_CRXDSA:
1071
+ case REG_CRXBSA:
1072
+ qemu_log_mask(LOG_GUEST_ERROR,
1073
+ "%s: Write to read-only reg %s/%d\n",
1074
+ __func__, emc_reg_name(reg), reg);
1075
+ break;
1076
+ default:
1077
+ qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n",
1078
+ __func__, emc_reg_name(reg), reg);
1079
+ break;
1080
+ }
1081
+}
1082
+
1083
+static const struct MemoryRegionOps npcm7xx_emc_ops = {
1084
+ .read = npcm7xx_emc_read,
1085
+ .write = npcm7xx_emc_write,
1086
+ .endianness = DEVICE_LITTLE_ENDIAN,
1087
+ .valid = {
1088
+ .min_access_size = 4,
1089
+ .max_access_size = 4,
1090
+ .unaligned = false,
1091
+ },
1092
+};
1093
+
1094
+static void emc_cleanup(NetClientState *nc)
1095
+{
1096
+ /* Nothing to do yet. */
1097
+}
1098
+
1099
+static NetClientInfo net_npcm7xx_emc_info = {
1100
+ .type = NET_CLIENT_DRIVER_NIC,
1101
+ .size = sizeof(NICState),
1102
+ .can_receive = emc_can_receive,
1103
+ .receive = emc_receive,
1104
+ .cleanup = emc_cleanup,
1105
+ .link_status_changed = emc_set_link,
1106
+};
1107
+
1108
+static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
1109
+{
1110
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
1111
+ SysBusDevice *sbd = SYS_BUS_DEVICE(emc);
1112
+
1113
+ memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc,
1114
+ TYPE_NPCM7XX_EMC, 4 * KiB);
1115
+ sysbus_init_mmio(sbd, &emc->iomem);
1116
+ sysbus_init_irq(sbd, &emc->tx_irq);
1117
+ sysbus_init_irq(sbd, &emc->rx_irq);
1118
+
1119
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
1120
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
1121
+ object_get_typename(OBJECT(dev)), dev->id, emc);
1122
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
1123
+}
1124
+
1125
+static void npcm7xx_emc_unrealize(DeviceState *dev)
1126
+{
1127
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
1128
+
1129
+ qemu_del_nic(emc->nic);
1130
+}
1131
+
1132
+static const VMStateDescription vmstate_npcm7xx_emc = {
1133
+ .name = TYPE_NPCM7XX_EMC,
1134
+ .version_id = 0,
1135
+ .minimum_version_id = 0,
1136
+ .fields = (VMStateField[]) {
1137
+ VMSTATE_UINT8(emc_num, NPCM7xxEMCState),
1138
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS),
1139
+ VMSTATE_BOOL(tx_active, NPCM7xxEMCState),
1140
+ VMSTATE_BOOL(rx_active, NPCM7xxEMCState),
1141
+ VMSTATE_END_OF_LIST(),
1142
+ },
1143
+};
1144
+
1145
+static Property npcm7xx_emc_properties[] = {
1146
+ DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf),
1147
+ DEFINE_PROP_END_OF_LIST(),
1148
+};
1149
+
1150
+static void npcm7xx_emc_class_init(ObjectClass *klass, void *data)
1151
+{
1152
+ DeviceClass *dc = DEVICE_CLASS(klass);
1153
+
1154
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
1155
+ dc->desc = "NPCM7xx EMC Controller";
1156
+ dc->realize = npcm7xx_emc_realize;
1157
+ dc->unrealize = npcm7xx_emc_unrealize;
1158
+ dc->reset = npcm7xx_emc_reset;
1159
+ dc->vmsd = &vmstate_npcm7xx_emc;
1160
+ device_class_set_props(dc, npcm7xx_emc_properties);
1161
+}
1162
+
1163
+static const TypeInfo npcm7xx_emc_info = {
1164
+ .name = TYPE_NPCM7XX_EMC,
1165
+ .parent = TYPE_SYS_BUS_DEVICE,
1166
+ .instance_size = sizeof(NPCM7xxEMCState),
1167
+ .class_init = npcm7xx_emc_class_init,
1168
+};
1169
+
1170
+static void npcm7xx_emc_register_type(void)
1171
+{
1172
+ type_register_static(&npcm7xx_emc_info);
1173
+}
1174
+
1175
+type_init(npcm7xx_emc_register_type)
1176
diff --git a/hw/net/meson.build b/hw/net/meson.build
262
index XXXXXXX..XXXXXXX 100644
1177
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
1178
--- a/hw/net/meson.build
264
+++ b/tests/tcg/aarch64/Makefile.target
1179
+++ b/hw/net/meson.build
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
1180
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
1181
softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
267
endif
1182
softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
268
1183
softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
269
+# BTI Tests
1184
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
270
+# bti-1 tests the elf notes, so we require special compiler support.
1185
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
1186
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
272
+AARCH64_TESTS += bti-1
1187
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
273
+bti-1: CFLAGS += -mbranch-protection=standard
1188
diff --git a/hw/net/trace-events b/hw/net/trace-events
274
+bti-1: LDFLAGS += -nostdlib
1189
index XXXXXXX..XXXXXXX 100644
275
+endif
1190
--- a/hw/net/trace-events
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
1191
+++ b/hw/net/trace-events
277
+AARCH64_TESTS += bti-2
1192
@@ -XXX,XX +XXX,XX @@ imx_fec_receive_last(int last) "rx frame flags 0x%04x"
278
+
1193
imx_enet_receive(size_t size) "len %zu"
279
# Semihosting smoke test for linux-user
1194
imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
280
AARCH64_TESTS += semihosting
1195
imx_enet_receive_last(int last) "rx frame flags 0x%04x"
281
run-semihosting: semihosting
1196
+
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
1197
+# npcm7xx_emc.c
283
index XXXXXXX..XXXXXXX 100755
1198
+npcm7xx_emc_reset(int emc_num) "Resetting emc%d"
284
--- a/tests/tcg/configure.sh
1199
+npcm7xx_emc_update_tx_irq(int level) "Setting tx irq to %d"
285
+++ b/tests/tcg/configure.sh
1200
+npcm7xx_emc_update_rx_irq(int level) "Setting rx irq to %d"
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
1201
+npcm7xx_emc_set_mista(uint32_t flags) "ORing 0x%x into MISTA"
287
-march=armv8.3-a -o $TMPE $TMPC; then
1202
+npcm7xx_emc_cpu_owned_desc(uint32_t addr) "Can't process cpu-owned descriptor @0x%x"
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
1203
+npcm7xx_emc_sent_packet(uint32_t len) "Sent %u byte packet"
289
fi
1204
+npcm7xx_emc_tx_done(uint32_t ctxdsa) "TX done, CTXDSA=0x%x"
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
1205
+npcm7xx_emc_can_receive(int can_receive) "Can receive: %d"
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
1206
+npcm7xx_emc_packet_filtered_out(const char* fail_reason) "Packet filtered out: %s"
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
1207
+npcm7xx_emc_packet_dropped(uint32_t len) "%u byte packet dropped"
293
+ fi
1208
+npcm7xx_emc_receiving_packet(uint32_t len) "Receiving %u byte packet"
294
;;
1209
+npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
295
esac
1210
+npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
296
1211
+npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
1212
+npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
297
--
1213
--
298
2.20.1
1214
2.20.1
299
1215
300
1216
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Doug Evans <dje@google.com>
2
2
3
The kernel sets btype for the signal handler as if for a call.
3
This is a 10/100 ethernet device that has several features.
4
Only the ones needed by the Linux driver have been implemented.
5
See npcm7xx_emc.c for a list of unimplemented features.
4
6
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Doug Evans <dje@google.com>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
11
Message-id: 20210218212453.831406-3-dje@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
14
docs/system/arm/nuvoton.rst | 3 ++-
11
1 file changed, 8 insertions(+), 2 deletions(-)
15
include/hw/arm/npcm7xx.h | 2 ++
16
hw/arm/npcm7xx.c | 50 +++++++++++++++++++++++++++++++++++--
17
3 files changed, 52 insertions(+), 3 deletions(-)
12
18
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
21
--- a/docs/system/arm/nuvoton.rst
16
+++ b/linux-user/aarch64/signal.c
22
+++ b/docs/system/arm/nuvoton.rst
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
23
@@ -XXX,XX +XXX,XX @@ Supported devices
18
+ offsetof(struct target_rt_frame_record, tramp);
24
* Analog to Digital Converter (ADC)
25
* Pulse Width Modulation (PWM)
26
* SMBus controller (SMBF)
27
+ * Ethernet controller (EMC)
28
29
Missing devices
30
---------------
31
@@ -XXX,XX +XXX,XX @@ Missing devices
32
* Shared memory (SHM)
33
* eSPI slave interface
34
35
- * Ethernet controllers (GMAC and EMC)
36
+ * Ethernet controller (GMAC)
37
* USB device (USBD)
38
* Peripheral SPI controller (PSPI)
39
* SD/MMC host
40
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/arm/npcm7xx.h
43
+++ b/include/hw/arm/npcm7xx.h
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/misc/npcm7xx_gcr.h"
46
#include "hw/misc/npcm7xx_pwm.h"
47
#include "hw/misc/npcm7xx_rng.h"
48
+#include "hw/net/npcm7xx_emc.h"
49
#include "hw/nvram/npcm7xx_otp.h"
50
#include "hw/timer/npcm7xx_timer.h"
51
#include "hw/ssi/npcm7xx_fiu.h"
52
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
53
EHCISysBusState ehci;
54
OHCISysBusState ohci;
55
NPCM7xxFIUState fiu[2];
56
+ NPCM7xxEMCState emc[2];
57
} NPCM7xxState;
58
59
#define TYPE_NPCM7XX "npcm7xx"
60
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/npcm7xx.c
63
+++ b/hw/arm/npcm7xx.c
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
65
NPCM7XX_UART1_IRQ,
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_EMC1RX_IRQ = 15,
69
+ NPCM7XX_EMC1TX_IRQ,
70
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
71
NPCM7XX_TIMER1_IRQ,
72
NPCM7XX_TIMER2_IRQ,
73
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
74
NPCM7XX_SMBUS15_IRQ,
75
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
76
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
77
+ NPCM7XX_EMC2RX_IRQ = 114,
78
+ NPCM7XX_EMC2TX_IRQ,
79
NPCM7XX_GPIO0_IRQ = 116,
80
NPCM7XX_GPIO1_IRQ,
81
NPCM7XX_GPIO2_IRQ,
82
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_smbus_addr[] = {
83
0xf008f000,
84
};
85
86
+/* Register base address for each EMC Module */
87
+static const hwaddr npcm7xx_emc_addr[] = {
88
+ 0xf0825000,
89
+ 0xf0826000,
90
+};
91
+
92
static const struct {
93
hwaddr regs_addr;
94
uint32_t unconnected_pins;
95
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
96
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
19
}
98
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
99
+
28
+ /* Invoke the signal handler as if by indirect call. */
100
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
101
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
30
+ env->btype = 2;
102
+ }
103
}
104
105
static void npcm7xx_realize(DeviceState *dev, Error **errp)
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
108
}
109
110
+ /*
111
+ * EMC Modules. Cannot fail.
112
+ * The mapping of the device to its netdev backend works as follows:
113
+ * emc[i] = nd_table[i]
114
+ * This works around the inability to specify the netdev property for the
115
+ * emc device: it's not pluggable and thus the -device option can't be
116
+ * used.
117
+ */
118
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
119
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
120
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
121
+ s->emc[i].emc_num = i;
122
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
123
+ if (nd_table[i].used) {
124
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
125
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
126
+ }
127
+ /*
128
+ * The device exists regardless of whether it's connected to a QEMU
129
+ * netdev backend. So always instantiate it even if there is no
130
+ * backend.
131
+ */
132
+ sysbus_realize(sbd, &error_abort);
133
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
134
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
135
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
136
+ /*
137
+ * N.B. The values for the second argument sysbus_connect_irq are
138
+ * chosen to match the registration order in npcm7xx_emc_realize.
139
+ */
140
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
141
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
31
+ }
142
+ }
32
+
143
+
33
if (info) {
144
/*
34
tswap_siginfo(&frame->info, info);
145
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
146
* specified, but this is a programming error.
147
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
148
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
149
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
150
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
151
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
152
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
153
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
154
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
155
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
36
--
156
--
37
2.20.1
157
2.20.1
38
158
39
159
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Doug Evans <dje@google.com>
2
2
3
This test exercises the various modes of the npcm7xx timer. In
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
4
particular, it triggers the bug found by the fuzzer, as reported here:
4
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
5
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
6
Signed-off-by: Doug Evans <dje@google.com>
7
7
Message-id: 20210218212453.831406-4-dje@google.com
8
It also found several other bugs, especially related to interrupt
9
handling.
10
11
The test exercises all the timers in all the timer modules, which
12
expands to 180 test cases in total.
13
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
9
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
10
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
11
tests/qtest/meson.build | 3 +-
21
2 files changed, 563 insertions(+)
12
2 files changed, 864 insertions(+), 1 deletion(-)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
13
create mode 100644 tests/qtest/npcm7xx_emc-test.c
23
14
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
15
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
25
new file mode 100644
16
new file mode 100644
26
index XXXXXXX..XXXXXXX
17
index XXXXXXX..XXXXXXX
27
--- /dev/null
18
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
19
+++ b/tests/qtest/npcm7xx_emc-test.c
29
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
30
+/*
21
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
22
+ * QTests for Nuvoton NPCM7xx EMC Modules.
32
+ *
23
+ *
33
+ * Copyright 2020 Google LLC
24
+ * Copyright 2020 Google LLC
34
+ *
25
+ *
35
+ * This program is free software; you can redistribute it and/or modify it
26
+ * This program is free software; you can redistribute it and/or modify it
36
+ * under the terms of the GNU General Public License as published by the
27
+ * under the terms of the GNU General Public License as published by the
...
...
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43
+ * for more details.
34
+ * for more details.
44
+ */
35
+ */
45
+
36
+
46
+#include "qemu/osdep.h"
37
+#include "qemu/osdep.h"
47
+#include "qemu/timer.h"
38
+#include "qemu-common.h"
48
+#include "libqtest-single.h"
39
+#include "libqos/libqos.h"
49
+
40
+#include "qapi/qmp/qdict.h"
50
+#define TIM_REF_HZ (25000000)
41
+#include "qapi/qmp/qnum.h"
51
+
42
+#include "qemu/bitops.h"
52
+/* Bits in TCSRx */
43
+#include "qemu/iov.h"
53
+#define CEN BIT(30)
44
+
54
+#define IE BIT(29)
45
+/* Name of the emc device. */
55
+#define MODE_ONESHOT (0 << 27)
46
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
56
+#define MODE_PERIODIC (1 << 27)
47
+
57
+#define CRST BIT(26)
48
+/* Timeout for various operations, in seconds. */
58
+#define CACT BIT(25)
49
+#define TIMEOUT_SECONDS 10
59
+#define PRESCALE(x) (x)
50
+
60
+
51
+/* Address in memory of the descriptor. */
61
+/* Registers shared between all timers in a module. */
52
+#define DESC_ADDR (1 << 20) /* 1 MiB */
62
+#define TISR 0x18
53
+
63
+#define WTCR 0x1c
54
+/* Address in memory of the data packet. */
64
+# define WTCLK(x) ((x) << 10)
55
+#define DATA_ADDR (DESC_ADDR + 4096)
65
+
56
+
66
+/* Power-on default; used to re-initialize timers before each test. */
57
+#define CRC_LENGTH 4
67
+#define TCSR_DEFAULT PRESCALE(5)
58
+
68
+
59
+#define NUM_TX_DESCRIPTORS 3
69
+/* Register offsets for a timer within a timer block. */
60
+#define NUM_RX_DESCRIPTORS 2
70
+typedef struct Timer {
61
+
71
+ unsigned int tcsr_offset;
62
+/* Size of tx,rx test buffers. */
72
+ unsigned int ticr_offset;
63
+#define TX_DATA_LEN 64
73
+ unsigned int tdr_offset;
64
+#define RX_DATA_LEN 64
74
+} Timer;
65
+
75
+
66
+#define TX_STEP_COUNT 10000
76
+/* A timer block containing 5 timers. */
67
+#define RX_STEP_COUNT 10000
77
+typedef struct TimerBlock {
68
+
78
+ int irq_base;
69
+/* 32-bit register indices. */
70
+typedef enum NPCM7xxPWMRegister {
71
+ /* Control registers. */
72
+ REG_CAMCMR,
73
+ REG_CAMEN,
74
+
75
+ /* There are 16 CAMn[ML] registers. */
76
+ REG_CAMM_BASE,
77
+ REG_CAML_BASE,
78
+
79
+ REG_TXDLSA = 0x22,
80
+ REG_RXDLSA,
81
+ REG_MCMDR,
82
+ REG_MIID,
83
+ REG_MIIDA,
84
+ REG_FFTCR,
85
+ REG_TSDR,
86
+ REG_RSDR,
87
+ REG_DMARFC,
88
+ REG_MIEN,
89
+
90
+ /* Status registers. */
91
+ REG_MISTA,
92
+ REG_MGSTA,
93
+ REG_MPCNT,
94
+ REG_MRPC,
95
+ REG_MRPCC,
96
+ REG_MREPC,
97
+ REG_DMARFS,
98
+ REG_CTXDSA,
99
+ REG_CTXBSA,
100
+ REG_CRXDSA,
101
+ REG_CRXBSA,
102
+
103
+ NPCM7XX_NUM_EMC_REGS,
104
+} NPCM7xxPWMRegister;
105
+
106
+enum { NUM_CAMML_REGS = 16 };
107
+
108
+/* REG_CAMCMR fields */
109
+/* Enable CAM Compare */
110
+#define REG_CAMCMR_ECMP (1 << 4)
111
+/* Accept Unicast Packet */
112
+#define REG_CAMCMR_AUP (1 << 0)
113
+
114
+/* REG_MCMDR fields */
115
+/* Software Reset */
116
+#define REG_MCMDR_SWR (1 << 24)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Accept Long Packet */
120
+#define REG_MCMDR_ALP (1 << 1)
121
+/* Frame Reception On */
122
+#define REG_MCMDR_RXON (1 << 0)
123
+
124
+/* REG_MIEN fields */
125
+/* Enable Transmit Completion Interrupt */
126
+#define REG_MIEN_ENTXCP (1 << 18)
127
+/* Enable Transmit Interrupt */
128
+#define REG_MIEN_ENTXINTR (1 << 16)
129
+/* Enable Receive Good Interrupt */
130
+#define REG_MIEN_ENRXGD (1 << 4)
131
+/* ENable Receive Interrupt */
132
+#define REG_MIEN_ENRXINTR (1 << 0)
133
+
134
+/* REG_MISTA fields */
135
+/* Transmit Bus Error Interrupt */
136
+#define REG_MISTA_TXBERR (1 << 24)
137
+/* Transmit Descriptor Unavailable Interrupt */
138
+#define REG_MISTA_TDU (1 << 23)
139
+/* Transmit Completion Interrupt */
140
+#define REG_MISTA_TXCP (1 << 18)
141
+/* Transmit Interrupt */
142
+#define REG_MISTA_TXINTR (1 << 16)
143
+/* Receive Bus Error Interrupt */
144
+#define REG_MISTA_RXBERR (1 << 11)
145
+/* Receive Descriptor Unavailable Interrupt */
146
+#define REG_MISTA_RDU (1 << 10)
147
+/* DMA Early Notification Interrupt */
148
+#define REG_MISTA_DENI (1 << 9)
149
+/* Maximum Frame Length Interrupt */
150
+#define REG_MISTA_DFOI (1 << 8)
151
+/* Receive Good Interrupt */
152
+#define REG_MISTA_RXGD (1 << 4)
153
+/* Packet Too Long Interrupt */
154
+#define REG_MISTA_PTLE (1 << 3)
155
+/* Receive Interrupt */
156
+#define REG_MISTA_RXINTR (1 << 0)
157
+
158
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
159
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
160
+
161
+struct NPCM7xxEMCTxDesc {
162
+ uint32_t flags;
163
+ uint32_t txbsa;
164
+ uint32_t status_and_length;
165
+ uint32_t ntxdsa;
166
+};
167
+
168
+struct NPCM7xxEMCRxDesc {
169
+ uint32_t status_and_length;
170
+ uint32_t rxbsa;
171
+ uint32_t reserved;
172
+ uint32_t nrxdsa;
173
+};
174
+
175
+/* NPCM7xxEMCTxDesc.flags values */
176
+/* Owner: 0 = cpu, 1 = emc */
177
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
178
+/* Transmit interrupt enable */
179
+#define TX_DESC_FLAG_INTEN (1 << 2)
180
+
181
+/* NPCM7xxEMCTxDesc.status_and_length values */
182
+/* Transmission complete */
183
+#define TX_DESC_STATUS_TXCP (1 << 19)
184
+/* Transmit interrupt */
185
+#define TX_DESC_STATUS_TXINTR (1 << 16)
186
+
187
+/* NPCM7xxEMCRxDesc.status_and_length values */
188
+/* Owner: 0b00 = cpu, 0b10 = emc */
189
+#define RX_DESC_STATUS_OWNER_SHIFT 30
190
+#define RX_DESC_STATUS_OWNER_MASK 0xc0000000
191
+/* Frame Reception Complete */
192
+#define RX_DESC_STATUS_RXGD (1 << 20)
193
+/* Packet too long */
194
+#define RX_DESC_STATUS_PTLE (1 << 19)
195
+/* Receive Interrupt */
196
+#define RX_DESC_STATUS_RXINTR (1 << 16)
197
+
198
+#define RX_DESC_PKT_LEN(word) ((uint32_t) (word) & 0xffff)
199
+
200
+typedef struct EMCModule {
201
+ int rx_irq;
202
+ int tx_irq;
79
+ uint64_t base_addr;
203
+ uint64_t base_addr;
80
+} TimerBlock;
204
+} EMCModule;
81
+
205
+
82
+/* Testdata for testing a particular timer within a timer block. */
83
+typedef struct TestData {
206
+typedef struct TestData {
84
+ const TimerBlock *tim;
207
+ const EMCModule *module;
85
+ const Timer *timer;
86
+} TestData;
208
+} TestData;
87
+
209
+
88
+const TimerBlock timer_block[] = {
210
+static const EMCModule emc_module_list[] = {
89
+ {
211
+ {
90
+ .irq_base = 32,
212
+ .rx_irq = 15,
91
+ .base_addr = 0xf0008000,
213
+ .tx_irq = 16,
214
+ .base_addr = 0xf0825000
92
+ },
215
+ },
93
+ {
216
+ {
94
+ .irq_base = 37,
217
+ .rx_irq = 114,
95
+ .base_addr = 0xf0009000,
218
+ .tx_irq = 115,
96
+ },
219
+ .base_addr = 0xf0826000
220
+ }
221
+};
222
+
223
+/* Returns the index of the EMC module. */
224
+static int emc_module_index(const EMCModule *mod)
225
+{
226
+ ptrdiff_t diff = mod - emc_module_list;
227
+
228
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(emc_module_list));
229
+
230
+ return diff;
231
+}
232
+
233
+static void packet_test_clear(void *sockets)
234
+{
235
+ int *test_sockets = sockets;
236
+
237
+ close(test_sockets[0]);
238
+ g_free(test_sockets);
239
+}
240
+
241
+static int *packet_test_init(int module_num, GString *cmd_line)
242
+{
243
+ int *test_sockets = g_new(int, 2);
244
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
245
+ g_assert_cmpint(ret, != , -1);
246
+
247
+ /*
248
+ * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
249
+ * currently no way to specify only emc1: The driver implicitly relies on
250
+ * emc[i] == nd_table[i].
251
+ */
252
+ if (module_num == 0) {
253
+ g_string_append_printf(cmd_line,
254
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
255
+ " -nic user,model=" TYPE_NPCM7XX_EMC " ",
256
+ test_sockets[1]);
257
+ } else {
258
+ g_string_append_printf(cmd_line,
259
+ " -nic user,model=" TYPE_NPCM7XX_EMC " "
260
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " ",
261
+ test_sockets[1]);
262
+ }
263
+
264
+ g_test_queue_destroy(packet_test_clear, test_sockets);
265
+ return test_sockets;
266
+}
267
+
268
+static uint32_t emc_read(QTestState *qts, const EMCModule *mod,
269
+ NPCM7xxPWMRegister regno)
270
+{
271
+ return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t));
272
+}
273
+
274
+static void emc_write(QTestState *qts, const EMCModule *mod,
275
+ NPCM7xxPWMRegister regno, uint32_t value)
276
+{
277
+ qtest_writel(qts, mod->base_addr + regno * sizeof(uint32_t), value);
278
+}
279
+
280
+static void emc_read_tx_desc(QTestState *qts, uint32_t addr,
281
+ NPCM7xxEMCTxDesc *desc)
282
+{
283
+ qtest_memread(qts, addr, desc, sizeof(*desc));
284
+ desc->flags = le32_to_cpu(desc->flags);
285
+ desc->txbsa = le32_to_cpu(desc->txbsa);
286
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
287
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
288
+}
289
+
290
+static void emc_write_tx_desc(QTestState *qts, const NPCM7xxEMCTxDesc *desc,
291
+ uint32_t addr)
292
+{
293
+ NPCM7xxEMCTxDesc le_desc;
294
+
295
+ le_desc.flags = cpu_to_le32(desc->flags);
296
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
297
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
298
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
299
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
300
+}
301
+
302
+static void emc_read_rx_desc(QTestState *qts, uint32_t addr,
303
+ NPCM7xxEMCRxDesc *desc)
304
+{
305
+ qtest_memread(qts, addr, desc, sizeof(*desc));
306
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
307
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
308
+ desc->reserved = le32_to_cpu(desc->reserved);
309
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
310
+}
311
+
312
+static void emc_write_rx_desc(QTestState *qts, const NPCM7xxEMCRxDesc *desc,
313
+ uint32_t addr)
314
+{
315
+ NPCM7xxEMCRxDesc le_desc;
316
+
317
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
318
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
319
+ le_desc.reserved = cpu_to_le32(desc->reserved);
320
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
321
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
322
+}
323
+
324
+/*
325
+ * Reset the EMC module.
326
+ * The module must be reset before, e.g., TXDLSA,RXDLSA are changed.
327
+ */
328
+static bool emc_soft_reset(QTestState *qts, const EMCModule *mod)
329
+{
330
+ uint32_t val;
331
+ uint64_t end_time;
332
+
333
+ emc_write(qts, mod, REG_MCMDR, REG_MCMDR_SWR);
334
+
335
+ /*
336
+ * Wait for device to reset as the linux driver does.
337
+ * During reset the AHB reads 0 for all registers. So first wait for
338
+ * something that resets to non-zero, and then wait for SWR becoming 0.
339
+ */
340
+ end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
341
+
342
+ do {
343
+ qtest_clock_step(qts, 100);
344
+ val = emc_read(qts, mod, REG_FFTCR);
345
+ } while (val == 0 && g_get_monotonic_time() < end_time);
346
+ if (val != 0) {
347
+ do {
348
+ qtest_clock_step(qts, 100);
349
+ val = emc_read(qts, mod, REG_MCMDR);
350
+ if ((val & REG_MCMDR_SWR) == 0) {
351
+ /*
352
+ * N.B. The CAMs have been reset here, so macaddr matching of
353
+ * incoming packets will not work.
354
+ */
355
+ return true;
356
+ }
357
+ } while (g_get_monotonic_time() < end_time);
358
+ }
359
+
360
+ g_message("%s: Timeout expired", __func__);
361
+ return false;
362
+}
363
+
364
+/* Check emc registers are reset to default value. */
365
+static void test_init(gconstpointer test_data)
366
+{
367
+ const TestData *td = test_data;
368
+ const EMCModule *mod = td->module;
369
+ QTestState *qts = qtest_init("-machine quanta-gsj");
370
+ int i;
371
+
372
+#define CHECK_REG(regno, value) \
373
+ do { \
374
+ g_assert_cmphex(emc_read(qts, mod, (regno)), ==, (value)); \
375
+ } while (0)
376
+
377
+ CHECK_REG(REG_CAMCMR, 0);
378
+ CHECK_REG(REG_CAMEN, 0);
379
+ CHECK_REG(REG_TXDLSA, 0xfffffffc);
380
+ CHECK_REG(REG_RXDLSA, 0xfffffffc);
381
+ CHECK_REG(REG_MCMDR, 0);
382
+ CHECK_REG(REG_MIID, 0);
383
+ CHECK_REG(REG_MIIDA, 0x00900000);
384
+ CHECK_REG(REG_FFTCR, 0x0101);
385
+ CHECK_REG(REG_DMARFC, 0x0800);
386
+ CHECK_REG(REG_MIEN, 0);
387
+ CHECK_REG(REG_MISTA, 0);
388
+ CHECK_REG(REG_MGSTA, 0);
389
+ CHECK_REG(REG_MPCNT, 0x7fff);
390
+ CHECK_REG(REG_MRPC, 0);
391
+ CHECK_REG(REG_MRPCC, 0);
392
+ CHECK_REG(REG_MREPC, 0);
393
+ CHECK_REG(REG_DMARFS, 0);
394
+ CHECK_REG(REG_CTXDSA, 0);
395
+ CHECK_REG(REG_CTXBSA, 0);
396
+ CHECK_REG(REG_CRXDSA, 0);
397
+ CHECK_REG(REG_CRXBSA, 0);
398
+
399
+#undef CHECK_REG
400
+
401
+ for (i = 0; i < NUM_CAMML_REGS; ++i) {
402
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==,
403
+ 0);
404
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==,
405
+ 0);
406
+ }
407
+
408
+ qtest_quit(qts);
409
+}
410
+
411
+static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step,
412
+ bool is_tx)
413
+{
414
+ uint64_t end_time =
415
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
416
+
417
+ do {
418
+ if (qtest_get_irq(qts, is_tx ? mod->tx_irq : mod->rx_irq)) {
419
+ return true;
420
+ }
421
+ qtest_clock_step(qts, step);
422
+ } while (g_get_monotonic_time() < end_time);
423
+
424
+ g_message("%s: Timeout expired", __func__);
425
+ return false;
426
+}
427
+
428
+static bool emc_wait_mista(QTestState *qts, const EMCModule *mod, int step,
429
+ uint32_t flag)
430
+{
431
+ uint64_t end_time =
432
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
433
+
434
+ do {
435
+ uint32_t mista = emc_read(qts, mod, REG_MISTA);
436
+ if (mista & flag) {
437
+ return true;
438
+ }
439
+ qtest_clock_step(qts, step);
440
+ } while (g_get_monotonic_time() < end_time);
441
+
442
+ g_message("%s: Timeout expired", __func__);
443
+ return false;
444
+}
445
+
446
+static bool wait_socket_readable(int fd)
447
+{
448
+ fd_set read_fds;
449
+ struct timeval tv;
450
+ int rv;
451
+
452
+ FD_ZERO(&read_fds);
453
+ FD_SET(fd, &read_fds);
454
+ tv.tv_sec = TIMEOUT_SECONDS;
455
+ tv.tv_usec = 0;
456
+ rv = select(fd + 1, &read_fds, NULL, NULL, &tv);
457
+ if (rv == -1) {
458
+ perror("select");
459
+ } else if (rv == 0) {
460
+ g_message("%s: Timeout expired", __func__);
461
+ }
462
+ return rv == 1;
463
+}
464
+
465
+/* Initialize *desc (in host endian format). */
466
+static void init_tx_desc(NPCM7xxEMCTxDesc *desc, size_t count,
467
+ uint32_t desc_addr)
468
+{
469
+ g_assert(count >= 2);
470
+ memset(&desc[0], 0, sizeof(*desc) * count);
471
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
472
+ for (size_t i = 0; i < count - 1; ++i) {
473
+ desc[i].flags =
474
+ (TX_DESC_FLAG_OWNER_MASK | /* owner = 1: emc */
475
+ TX_DESC_FLAG_INTEN |
476
+ 0 | /* crc append = 0 */
477
+ 0 /* padding enable = 0 */);
478
+ desc[i].status_and_length =
479
+ (0 | /* collision count = 0 */
480
+ 0 | /* SQE = 0 */
481
+ 0 | /* PAU = 0 */
482
+ 0 | /* TXHA = 0 */
483
+ 0 | /* LC = 0 */
484
+ 0 | /* TXABT = 0 */
485
+ 0 | /* NCS = 0 */
486
+ 0 | /* EXDEF = 0 */
487
+ 0 | /* TXCP = 0 */
488
+ 0 | /* DEF = 0 */
489
+ 0 | /* TXINTR = 0 */
490
+ 0 /* length filled in later */);
491
+ desc[i].ntxdsa = desc_addr + (i + 1) * sizeof(*desc);
492
+ }
493
+}
494
+
495
+static void enable_tx(QTestState *qts, const EMCModule *mod,
496
+ const NPCM7xxEMCTxDesc *desc, size_t count,
497
+ uint32_t desc_addr, uint32_t mien_flags)
498
+{
499
+ /* Write the descriptors to guest memory. */
500
+ for (size_t i = 0; i < count; ++i) {
501
+ emc_write_tx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
502
+ }
503
+
504
+ /* Trigger sending the packet. */
505
+ /* The module must be reset before changing TXDLSA. */
506
+ g_assert(emc_soft_reset(qts, mod));
507
+ emc_write(qts, mod, REG_TXDLSA, desc_addr);
508
+ emc_write(qts, mod, REG_CTXDSA, ~0);
509
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENTXCP | mien_flags);
97
+ {
510
+ {
98
+ .irq_base = 42,
511
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
99
+ .base_addr = 0xf000a000,
512
+ mcmdr |= REG_MCMDR_TXON;
100
+ },
513
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
101
+};
514
+ }
102
+
515
+
103
+const Timer timer[] = {
516
+ /* Prod the device to send the packet. */
517
+ emc_write(qts, mod, REG_TSDR, 1);
518
+}
519
+
520
+static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
521
+ bool with_irq, uint32_t desc_addr,
522
+ uint32_t next_desc_addr,
523
+ const char *test_data, int test_size)
524
+{
525
+ NPCM7xxEMCTxDesc result_desc;
526
+ uint32_t expected_mask, expected_value, recv_len;
527
+ int ret;
528
+ char buffer[TX_DATA_LEN];
529
+
530
+ g_assert(wait_socket_readable(fd));
531
+
532
+ /* Read the descriptor back. */
533
+ emc_read_tx_desc(qts, desc_addr, &result_desc);
534
+ /* Descriptor should be owned by cpu now. */
535
+ g_assert((result_desc.flags & TX_DESC_FLAG_OWNER_MASK) == 0);
536
+ /* Test the status bits, ignoring the length field. */
537
+ expected_mask = 0xffff << 16;
538
+ expected_value = TX_DESC_STATUS_TXCP;
539
+ if (with_irq) {
540
+ expected_value |= TX_DESC_STATUS_TXINTR;
541
+ }
542
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
543
+ expected_value);
544
+
545
+ /* Check data sent to the backend. */
546
+ recv_len = ~0;
547
+ ret = qemu_recv(fd, &recv_len, sizeof(recv_len), MSG_DONTWAIT);
548
+ g_assert_cmpint(ret, == , sizeof(recv_len));
549
+
550
+ g_assert(wait_socket_readable(fd));
551
+ memset(buffer, 0xff, sizeof(buffer));
552
+ ret = qemu_recv(fd, buffer, test_size, MSG_DONTWAIT);
553
+ g_assert_cmpmem(buffer, ret, test_data, test_size);
554
+}
555
+
556
+static void emc_send_verify(QTestState *qts, const EMCModule *mod, int fd,
557
+ bool with_irq)
558
+{
559
+ NPCM7xxEMCTxDesc desc[NUM_TX_DESCRIPTORS];
560
+ uint32_t desc_addr = DESC_ADDR;
561
+ static const char test1_data[] = "TEST1";
562
+ static const char test2_data[] = "Testing 1 2 3 ...";
563
+ uint32_t data1_addr = DATA_ADDR;
564
+ uint32_t data2_addr = data1_addr + sizeof(test1_data);
565
+ bool got_tdu;
566
+ uint32_t end_desc_addr;
567
+
568
+ /* Prepare test data buffer. */
569
+ qtest_memwrite(qts, data1_addr, test1_data, sizeof(test1_data));
570
+ qtest_memwrite(qts, data2_addr, test2_data, sizeof(test2_data));
571
+
572
+ init_tx_desc(&desc[0], NUM_TX_DESCRIPTORS, desc_addr);
573
+ desc[0].txbsa = data1_addr;
574
+ desc[0].status_and_length |= sizeof(test1_data);
575
+ desc[1].txbsa = data2_addr;
576
+ desc[1].status_and_length |= sizeof(test2_data);
577
+
578
+ enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
579
+ with_irq ? REG_MIEN_ENTXINTR : 0);
580
+
581
+ /*
582
+ * It's problematic to observe the interrupt for each packet.
583
+ * Instead just wait until all the packets go out.
584
+ */
585
+ got_tdu = false;
586
+ while (!got_tdu) {
587
+ if (with_irq) {
588
+ g_assert_true(emc_wait_irq(qts, mod, TX_STEP_COUNT,
589
+ /*is_tx=*/true));
590
+ } else {
591
+ g_assert_true(emc_wait_mista(qts, mod, TX_STEP_COUNT,
592
+ REG_MISTA_TXINTR));
593
+ }
594
+ got_tdu = !!(emc_read(qts, mod, REG_MISTA) & REG_MISTA_TDU);
595
+ /* If we don't have TDU yet, reset the interrupt. */
596
+ if (!got_tdu) {
597
+ emc_write(qts, mod, REG_MISTA,
598
+ emc_read(qts, mod, REG_MISTA) & 0xffff0000);
599
+ }
600
+ }
601
+
602
+ end_desc_addr = desc_addr + 2 * sizeof(desc[0]);
603
+ g_assert_cmphex(emc_read(qts, mod, REG_CTXDSA), ==, end_desc_addr);
604
+ g_assert_cmphex(emc_read(qts, mod, REG_MISTA), ==,
605
+ REG_MISTA_TXCP | REG_MISTA_TXINTR | REG_MISTA_TDU);
606
+
607
+ emc_send_verify1(qts, mod, fd, with_irq,
608
+ desc_addr, end_desc_addr,
609
+ test1_data, sizeof(test1_data));
610
+ emc_send_verify1(qts, mod, fd, with_irq,
611
+ desc_addr + sizeof(desc[0]), end_desc_addr,
612
+ test2_data, sizeof(test2_data));
613
+}
614
+
615
+/* Initialize *desc (in host endian format). */
616
+static void init_rx_desc(NPCM7xxEMCRxDesc *desc, size_t count,
617
+ uint32_t desc_addr, uint32_t data_addr)
618
+{
619
+ g_assert_true(count >= 2);
620
+ memset(desc, 0, sizeof(*desc) * count);
621
+ desc[0].rxbsa = data_addr;
622
+ desc[0].status_and_length =
623
+ (0b10 << RX_DESC_STATUS_OWNER_SHIFT | /* owner = 10: emc */
624
+ 0 | /* RP = 0 */
625
+ 0 | /* ALIE = 0 */
626
+ 0 | /* RXGD = 0 */
627
+ 0 | /* PTLE = 0 */
628
+ 0 | /* CRCE = 0 */
629
+ 0 | /* RXINTR = 0 */
630
+ 0 /* length (filled in later) */);
631
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
632
+ desc[0].nrxdsa = desc_addr + sizeof(*desc);
633
+}
634
+
635
+static void enable_rx(QTestState *qts, const EMCModule *mod,
636
+ const NPCM7xxEMCRxDesc *desc, size_t count,
637
+ uint32_t desc_addr, uint32_t mien_flags,
638
+ uint32_t mcmdr_flags)
639
+{
640
+ /*
641
+ * Write the descriptor to guest memory.
642
+ * FWIW, IWBN if the docs said the buffer needs to be at least DMARFC
643
+ * bytes.
644
+ */
645
+ for (size_t i = 0; i < count; ++i) {
646
+ emc_write_rx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
647
+ }
648
+
649
+ /* Trigger receiving the packet. */
650
+ /* The module must be reset before changing RXDLSA. */
651
+ g_assert(emc_soft_reset(qts, mod));
652
+ emc_write(qts, mod, REG_RXDLSA, desc_addr);
653
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENRXGD | mien_flags);
654
+
655
+ /*
656
+ * We don't know what the device's macaddr is, so just accept all
657
+ * unicast packets (AUP).
658
+ */
659
+ emc_write(qts, mod, REG_CAMCMR, REG_CAMCMR_AUP);
660
+ emc_write(qts, mod, REG_CAMEN, 1 << 0);
104
+ {
661
+ {
105
+ .tcsr_offset = 0x00,
662
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
106
+ .ticr_offset = 0x08,
663
+ mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
107
+ .tdr_offset = 0x10,
664
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
108
+ }, {
665
+ }
109
+ .tcsr_offset = 0x04,
666
+
110
+ .ticr_offset = 0x0c,
667
+ /* Prod the device to accept a packet. */
111
+ .tdr_offset = 0x14,
668
+ emc_write(qts, mod, REG_RSDR, 1);
112
+ }, {
669
+}
113
+ .tcsr_offset = 0x20,
670
+
114
+ .ticr_offset = 0x28,
671
+static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
115
+ .tdr_offset = 0x30,
672
+ bool with_irq)
116
+ }, {
673
+{
117
+ .tcsr_offset = 0x24,
674
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
118
+ .ticr_offset = 0x2c,
675
+ uint32_t desc_addr = DESC_ADDR;
119
+ .tdr_offset = 0x34,
676
+ uint32_t data_addr = DATA_ADDR;
120
+ }, {
677
+ int ret;
121
+ .tcsr_offset = 0x40,
678
+ uint32_t expected_mask, expected_value;
122
+ .ticr_offset = 0x48,
679
+ NPCM7xxEMCRxDesc result_desc;
123
+ .tdr_offset = 0x50,
680
+
124
+ },
681
+ /* Prepare test data buffer. */
125
+};
682
+ const char test[RX_DATA_LEN] = "TEST";
126
+
683
+ int len = htonl(sizeof(test));
127
+/* Returns the index of the timer block. */
684
+ const struct iovec iov[] = {
128
+static int tim_index(const TimerBlock *tim)
685
+ {
129
+{
686
+ .iov_base = &len,
130
+ ptrdiff_t diff = tim - timer_block;
687
+ .iov_len = sizeof(len),
131
+
688
+ },{
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
689
+ .iov_base = (char *) test,
133
+
690
+ .iov_len = sizeof(test),
134
+ return diff;
691
+ },
135
+}
692
+ };
136
+
693
+
137
+/* Returns the index of a timer within a timer block. */
694
+ /*
138
+static int timer_index(const Timer *t)
695
+ * Reset the device BEFORE sending a test packet, otherwise the packet
139
+{
696
+ * may get swallowed by an active device of an earlier test.
140
+ ptrdiff_t diff = t - timer;
697
+ */
141
+
698
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
699
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
143
+
700
+ with_irq ? REG_MIEN_ENRXINTR : 0, 0);
144
+ return diff;
701
+
145
+}
702
+ /* Send test packet to device's socket. */
146
+
703
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
147
+/* Returns the irq line for a given timer. */
704
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
148
+static int tim_timer_irq(const TestData *td)
705
+
149
+{
706
+ /* Wait for RX interrupt. */
150
+ return td->tim->irq_base + timer_index(td->timer);
707
+ if (with_irq) {
151
+}
708
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
152
+
709
+ } else {
153
+/* Register read/write accessors. */
710
+ g_assert_true(emc_wait_mista(qts, mod, RX_STEP_COUNT, REG_MISTA_RXGD));
154
+
711
+ }
155
+static void tim_write(const TestData *td,
712
+
156
+ unsigned int offset, uint32_t value)
713
+ g_assert_cmphex(emc_read(qts, mod, REG_CRXDSA), ==,
157
+{
714
+ desc_addr + sizeof(desc[0]));
158
+ writel(td->tim->base_addr + offset, value);
715
+
159
+}
716
+ expected_mask = 0xffff;
160
+
717
+ expected_value = (REG_MISTA_DENI |
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
718
+ REG_MISTA_RXGD |
162
+{
719
+ REG_MISTA_RXINTR);
163
+ return readl(td->tim->base_addr + offset);
720
+ g_assert_cmphex((emc_read(qts, mod, REG_MISTA) & expected_mask),
164
+}
721
+ ==, expected_value);
165
+
722
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
723
+ /* Read the descriptor back. */
167
+{
724
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
168
+ tim_write(td, td->timer->tcsr_offset, value);
725
+ /* Descriptor should be owned by cpu now. */
169
+}
726
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
170
+
727
+ /* Test the status bits, ignoring the length field. */
171
+static uint32_t tim_read_tcsr(const TestData *td)
728
+ expected_mask = 0xffff << 16;
172
+{
729
+ expected_value = RX_DESC_STATUS_RXGD;
173
+ return tim_read(td, td->timer->tcsr_offset);
730
+ if (with_irq) {
174
+}
731
+ expected_value |= RX_DESC_STATUS_RXINTR;
175
+
732
+ }
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
733
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
177
+{
734
+ expected_value);
178
+ tim_write(td, td->timer->ticr_offset, value);
735
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
179
+}
736
+ RX_DATA_LEN + CRC_LENGTH);
180
+
737
+
181
+static uint32_t tim_read_ticr(const TestData *td)
738
+ {
182
+{
739
+ char buffer[RX_DATA_LEN];
183
+ return tim_read(td, td->timer->ticr_offset);
740
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
184
+}
741
+ g_assert_cmpstr(buffer, == , "TEST");
185
+
742
+ }
186
+static uint32_t tim_read_tdr(const TestData *td)
743
+}
187
+{
744
+
188
+ return tim_read(td, td->timer->tdr_offset);
745
+static void emc_test_ptle(QTestState *qts, const EMCModule *mod, int fd)
189
+}
746
+{
190
+
747
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
748
+ uint32_t desc_addr = DESC_ADDR;
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
749
+ uint32_t data_addr = DATA_ADDR;
193
+{
750
+ int ret;
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
751
+ NPCM7xxEMCRxDesc result_desc;
195
+}
752
+ uint32_t expected_mask, expected_value;
196
+
753
+
197
+/* Returns a bitmask corresponding to the timer under test. */
754
+ /* Prepare test data buffer. */
198
+static uint32_t tim_timer_bit(const TestData *td)
755
+#define PTLE_DATA_LEN 1600
199
+{
756
+ char test_data[PTLE_DATA_LEN];
200
+ return BIT(timer_index(td->timer));
757
+ int len = htonl(sizeof(test_data));
201
+}
758
+ const struct iovec iov[] = {
202
+
759
+ {
203
+/* Resets all timers to power-on defaults. */
760
+ .iov_base = &len,
204
+static void tim_reset(const TestData *td)
761
+ .iov_len = sizeof(len),
205
+{
762
+ },{
206
+ int i, j;
763
+ .iov_base = (char *) test_data,
207
+
764
+ .iov_len = sizeof(test_data),
208
+ /* Reset all the timers, in case a previous test left a timer running. */
765
+ },
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
766
+ };
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
767
+ memset(test_data, 42, sizeof(test_data));
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
768
+
212
+ CRST | TCSR_DEFAULT);
769
+ /*
213
+ }
770
+ * Reset the device BEFORE sending a test packet, otherwise the packet
214
+ writel(timer_block[i].base_addr + TISR, -1);
771
+ * may get swallowed by an active device of an earlier test.
215
+ }
772
+ */
216
+}
773
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
217
+
774
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
218
+/* Verifies the reset state of a timer. */
775
+ REG_MIEN_ENRXINTR, REG_MCMDR_ALP);
219
+static void test_reset(gconstpointer test_data)
776
+
777
+ /* Send test packet to device's socket. */
778
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test_data));
779
+ g_assert_cmpint(ret, == , sizeof(test_data) + sizeof(len));
780
+
781
+ /* Wait for RX interrupt. */
782
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
783
+
784
+ /* Read the descriptor back. */
785
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
786
+ /* Descriptor should be owned by cpu now. */
787
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
788
+ /* Test the status bits, ignoring the length field. */
789
+ expected_mask = 0xffff << 16;
790
+ expected_value = (RX_DESC_STATUS_RXGD |
791
+ RX_DESC_STATUS_PTLE |
792
+ RX_DESC_STATUS_RXINTR);
793
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
794
+ expected_value);
795
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
796
+ PTLE_DATA_LEN + CRC_LENGTH);
797
+
798
+ {
799
+ char buffer[PTLE_DATA_LEN];
800
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
801
+ g_assert(memcmp(buffer, test_data, PTLE_DATA_LEN) == 0);
802
+ }
803
+}
804
+
805
+static void test_tx(gconstpointer test_data)
220
+{
806
+{
221
+ const TestData *td = test_data;
807
+ const TestData *td = test_data;
222
+
808
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
223
+ tim_reset(td);
809
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
224
+
810
+ cmd_line);
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
811
+ QTestState *qts = qtest_init(cmd_line->str);
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
812
+
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
813
+ /*
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
814
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
815
+ * the fork and before the exec, but that will require some harness
230
+}
816
+ * improvements.
231
+
817
+ */
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
818
+ close(test_sockets[1]);
233
+static void test_reset_overrides_enable(gconstpointer test_data)
819
+ /* Defensive programming */
820
+ test_sockets[1] = -1;
821
+
822
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
823
+
824
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
825
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
826
+
827
+ qtest_quit(qts);
828
+}
829
+
830
+static void test_rx(gconstpointer test_data)
234
+{
831
+{
235
+ const TestData *td = test_data;
832
+ const TestData *td = test_data;
236
+
833
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
237
+ tim_reset(td);
834
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
238
+
835
+ cmd_line);
239
+ /* CRST should force CEN to 0 */
836
+ QTestState *qts = qtest_init(cmd_line->str);
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
837
+
241
+
838
+ /*
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
839
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
840
+ * the fork and before the exec, but that will require some harness
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
841
+ * improvements.
245
+}
842
+ */
246
+
843
+ close(test_sockets[1]);
247
+/* Verifies the behavior when CEN is set and then cleared. */
844
+ /* Defensive programming */
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
845
+ test_sockets[1] = -1;
249
+{
846
+
250
+ const TestData *td = test_data;
847
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
251
+
848
+
252
+ tim_reset(td);
849
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
253
+
850
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
254
+ /* Enable the timer with zero initial count, then disable it again. */
851
+ emc_test_ptle(qts, td->module, test_sockets[0]);
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
852
+
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
853
+ qtest_quit(qts);
257
+
854
+}
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
855
+
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
856
+static void emc_add_test(const char *name, const TestData* td,
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
857
+ GTestDataFunc fn)
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
858
+{
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
859
+ g_autofree char *full_name = g_strdup_printf(
263
+}
860
+ "npcm7xx_emc/emc[%d]/%s", emc_module_index(td->module), name);
264
+
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
266
+static void test_oneshot_ps5(gconstpointer test_data)
267
+{
268
+ const TestData *td = test_data;
269
+ unsigned int count = 256;
270
+ unsigned int ps = 5;
271
+
272
+ tim_reset(td);
273
+
274
+ tim_write_ticr(td, count);
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
278
+
279
+ clock_step(tim_calculate_step(count, ps) - 1);
280
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
284
+
285
+ clock_step(1);
286
+
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
291
+
292
+ /* Clear the interrupt flag. */
293
+ tim_write(td, TISR, tim_timer_bit(td));
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
296
+
297
+ /* Verify that this isn't a periodic timer. */
298
+ clock_step(2 * tim_calculate_step(count, ps));
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
301
+}
302
+
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
304
+static void test_oneshot_ps0(gconstpointer test_data)
305
+{
306
+ const TestData *td = test_data;
307
+ unsigned int count = 1;
308
+ unsigned int ps = 0;
309
+
310
+ tim_reset(td);
311
+
312
+ tim_write_ticr(td, count);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
316
+
317
+ clock_step(tim_calculate_step(count, ps) - 1);
318
+
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
322
+
323
+ clock_step(1);
324
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
329
+}
330
+
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
332
+static void test_oneshot_ps255(gconstpointer test_data)
333
+{
334
+ const TestData *td = test_data;
335
+ unsigned int count = (1U << 24) - 1;
336
+ unsigned int ps = 255;
337
+
338
+ tim_reset(td);
339
+
340
+ tim_write_ticr(td, count);
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
344
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
346
+
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
350
+
351
+ clock_step(1);
352
+
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
357
+}
358
+
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
360
+static void test_oneshot_interrupt(gconstpointer test_data)
361
+{
362
+ const TestData *td = test_data;
363
+ unsigned int count = 256;
364
+ unsigned int ps = 7;
365
+
366
+ tim_reset(td);
367
+
368
+ tim_write_ticr(td, count);
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
370
+
371
+ clock_step_next();
372
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
375
+}
376
+
377
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
379
+ * at the right moment.
380
+ */
381
+static void test_pause_resume(gconstpointer test_data)
382
+{
383
+ const TestData *td = test_data;
384
+ unsigned int count = 256;
385
+ unsigned int ps = 1;
386
+
387
+ tim_reset(td);
388
+
389
+ tim_write_ticr(td, count);
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
391
+
392
+ /* Pause the timer halfway to expiration. */
393
+ clock_step(tim_calculate_step(count / 2, ps));
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
396
+
397
+ /* Counter should not advance during the following step. */
398
+ clock_step(2 * tim_calculate_step(count, ps));
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
402
+
403
+ /* Resume the timer and run _almost_ to expiration. */
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
409
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
411
+ clock_step(1);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
414
+}
415
+
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
417
+static void test_prescaler_change(gconstpointer test_data)
418
+{
419
+ const TestData *td = test_data;
420
+ unsigned int count = 256;
421
+ unsigned int ps = 5;
422
+
423
+ tim_reset(td);
424
+
425
+ tim_write_ticr(td, count);
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
428
+ /* Run a quarter of the way, and change the prescaler. */
429
+ clock_step(tim_calculate_step(count / 4, ps));
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
431
+ ps = 2;
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
433
+ /* The counter must not change. */
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
435
+
436
+ /* Run another quarter of the way, and change the prescaler again. */
437
+ clock_step(tim_calculate_step(count / 4, ps));
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
439
+ ps = 8;
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
441
+ /* The counter must not change. */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
443
+
444
+ /* Run another quarter of the way, and change the prescaler again. */
445
+ clock_step(tim_calculate_step(count / 4, ps));
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
447
+ ps = 0;
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
449
+ /* The counter must not change. */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
451
+
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
456
+
457
+ /* Now, run the rest of the way and verify that the timer fires. */
458
+ clock_step(1);
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
460
+}
461
+
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
464
+{
465
+ const TestData *td = test_data;
466
+ unsigned int count = 2;
467
+ unsigned int ps = 3;
468
+ int i;
469
+
470
+ tim_reset(td);
471
+
472
+ tim_write_ticr(td, count);
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
474
+
475
+ for (i = 0; i < 4; i++) {
476
+ clock_step_next();
477
+
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
480
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
482
+
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
485
+ }
486
+}
487
+
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
489
+static void test_periodic_interrupt(gconstpointer test_data)
490
+{
491
+ const TestData *td = test_data;
492
+ unsigned int count = 65535;
493
+ unsigned int ps = 2;
494
+ int i;
495
+
496
+ tim_reset(td);
497
+
498
+ tim_write_ticr(td, count);
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
500
+
501
+ for (i = 0; i < 4; i++) {
502
+ clock_step_next();
503
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
506
+
507
+ tim_write(td, TISR, tim_timer_bit(td));
508
+
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
511
+ }
512
+}
513
+
514
+/*
515
+ * Verifies that the timer behaves correctly when disabled right before and
516
+ * exactly when it's supposed to expire.
517
+ */
518
+static void test_disable_on_expiration(gconstpointer test_data)
519
+{
520
+ const TestData *td = test_data;
521
+ unsigned int count = 8;
522
+ unsigned int ps = 255;
523
+
524
+ tim_reset(td);
525
+
526
+ tim_write_ticr(td, count);
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
528
+
529
+ clock_step(tim_calculate_step(count, ps) - 1);
530
+
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
533
+ clock_step(1);
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
536
+}
537
+
538
+/*
539
+ * Constructs a name that includes the timer block, timer and testcase name,
540
+ * and adds the test to the test suite.
541
+ */
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
543
+{
544
+ g_autofree char *full_name;
545
+
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
547
+ tim_index(td->tim), timer_index(td->timer),
548
+ name);
549
+ qtest_add_data_func(full_name, td, fn);
861
+ qtest_add_data_func(full_name, td, fn);
550
+}
862
+}
551
+
863
+#define add_test(name, td) emc_add_test(#name, td, test_##name)
552
+/* Convenience macro for adding a test with a predictable function name. */
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
554
+
864
+
555
+int main(int argc, char **argv)
865
+int main(int argc, char **argv)
556
+{
866
+{
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
867
+ TestData test_data_list[ARRAY_SIZE(emc_module_list)];
558
+ int ret;
559
+ int i, j;
560
+
868
+
561
+ g_test_init(&argc, &argv, NULL);
869
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
870
+
563
+
871
+ for (int i = 0; i < ARRAY_SIZE(emc_module_list); ++i) {
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
872
+ TestData *td = &test_data_list[i];
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
873
+
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
874
+ td->module = &emc_module_list[i];
567
+ td->tim = &timer_block[i];
875
+
568
+ td->timer = &timer[j];
876
+ add_test(init, td);
569
+
877
+ add_test(tx, td);
570
+ add_test(reset, td);
878
+ add_test(rx, td);
571
+ add_test(reset_overrides_enable, td);
879
+ }
572
+ add_test(oneshot_enable_then_disable, td);
880
+
573
+ add_test(oneshot_ps5, td);
881
+ return g_test_run();
574
+ add_test(oneshot_ps0, td);
575
+ add_test(oneshot_ps255, td);
576
+ add_test(oneshot_interrupt, td);
577
+ add_test(pause_resume, td);
578
+ add_test(prescaler_change, td);
579
+ add_test(periodic_no_interrupt, td);
580
+ add_test(periodic_interrupt, td);
581
+ add_test(disable_on_expiration, td);
582
+ }
583
+ }
584
+
585
+ qtest_start("-machine npcm750-evb");
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
587
+ ret = g_test_run();
588
+ qtest_end();
589
+
590
+ return ret;
591
+}
882
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
883
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
index XXXXXXX..XXXXXXX 100644
884
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
885
--- a/tests/qtest/meson.build
595
+++ b/tests/qtest/meson.build
886
+++ b/tests/qtest/meson.build
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
887
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
597
['arm-cpu-features',
888
'npcm7xx_rng-test',
598
'microbit-test',
889
'npcm7xx_smbus-test',
599
'm25p80-test',
890
'npcm7xx_timer-test',
600
+ 'npcm7xx_timer-test',
891
- 'npcm7xx_watchdog_timer-test']
601
'test-arm-mptimer',
892
+ 'npcm7xx_watchdog_timer-test'] + \
602
'boot-serial-test',
893
+ (slirp.found() ? ['npcm7xx_emc-test'] : [])
603
'hexloader-test']
894
qtests_arm = \
895
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
896
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
604
--
897
--
605
2.20.1
898
2.20.1
606
899
607
900
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Fix an unlikely memory leak in load_elf_image().
3
We hint the 'has_rpu' property is no longer required since commit
4
6908ec448b4 ("xlnx-zynqmp: Properly support the smp command line
5
option") which was released in QEMU v2.11.0.
4
6
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
7
Beside, this device is marked 'user_creatable = false', so the
8
only thing that could be setting the property is the board code
9
that creates the device.
10
11
Since the property is not user-facing, we can remove it without
12
going through the deprecation process.
13
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210219144350.1979905-1-f4bug@amsat.org
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
18
---
14
linux-user/elfload.c | 8 ++++----
19
include/hw/arm/xlnx-zynqmp.h | 2 --
15
1 file changed, 4 insertions(+), 4 deletions(-)
20
hw/arm/xlnx-zynqmp.c | 6 ------
21
2 files changed, 8 deletions(-)
16
22
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
23
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
25
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/linux-user/elfload.c
26
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
27
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
22
info->brk = vaddr_em;
28
bool secure;
23
}
29
/* Has the ARM Virtualization extensions? */
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
30
bool virt;
25
- char *interp_name;
31
- /* Has the RPU subsystem? */
26
+ g_autofree char *interp_name = NULL;
32
- bool has_rpu;
27
33
28
if (*pinterp_name) {
34
/* CAN bus. */
29
errmsg = "Multiple PT_INTERP entries";
35
CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
30
goto exit_errmsg;
36
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
31
}
37
index XXXXXXX..XXXXXXX 100644
32
- interp_name = malloc(eppnt->p_filesz);
38
--- a/hw/arm/xlnx-zynqmp.c
33
+ interp_name = g_malloc(eppnt->p_filesz);
39
+++ b/hw/arm/xlnx-zynqmp.c
34
if (!interp_name) {
40
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
35
goto exit_perror;
41
}
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
42
}
53
43
54
#ifdef USE_ELF_CORE_DUMP
44
- if (s->has_rpu) {
45
- info_report("The 'has_rpu' property is no longer required, to use the "
46
- "RPUs just use -smp 6.");
47
- }
48
-
49
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
50
if (err) {
51
error_propagate(errp, err);
52
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
53
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
54
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
55
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
56
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
57
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
58
MemoryRegion *),
59
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
55
--
60
--
56
2.20.1
61
2.20.1
57
62
58
63
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is slightly clearer than just using strerror, though
3
Always perform one call instead of two for 16-byte operands.
4
the different forms produced by error_setg_file_open and
4
Use byte loads/stores directly into the vector register file
5
error_setg_errno isn't entirely convenient.
5
instead of extractions and deposits to a 64-bit local variable.
6
7
In order to easily receive pointers into the vector register file,
8
convert the helper to the gvec out-of-line signature. Move the
9
helper into vec_helper.c, where it can make use of H1 and clear_tail.
6
10
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
13
Tested-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20210224230532.276878-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
linux-user/elfload.c | 15 ++++++++-------
17
target/arm/helper-a64.h | 2 +-
13
1 file changed, 8 insertions(+), 7 deletions(-)
18
target/arm/helper-a64.c | 32 ---------------------
14
19
target/arm/translate-a64.c | 58 +++++---------------------------------
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
20
target/arm/vec_helper.c | 48 +++++++++++++++++++++++++++++++
16
index XXXXXXX..XXXXXXX 100644
21
4 files changed, 56 insertions(+), 84 deletions(-)
17
--- a/linux-user/elfload.c
22
18
+++ b/linux-user/elfload.c
23
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
24
index XXXXXXX..XXXXXXX 100644
20
char bprm_buf[BPRM_BUF_SIZE])
25
--- a/target/arm/helper-a64.h
26
+++ b/target/arm/helper-a64.h
27
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
28
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
29
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
30
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
31
-DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
32
+DEF_HELPER_FLAGS_4(simd_tblx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
34
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
35
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
36
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/helper-a64.c
39
+++ b/target/arm/helper-a64.c
40
@@ -XXX,XX +XXX,XX @@ float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp)
41
return float64_mul(a, b, fpst);
42
}
43
44
-uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
45
- uint32_t rn, uint32_t numregs)
46
-{
47
- /* Helper function for SIMD TBL and TBX. We have to do the table
48
- * lookup part for the 64 bits worth of indices we're passed in.
49
- * result is the initial results vector (either zeroes for TBL
50
- * or some guest values for TBX), rn the register number where
51
- * the table starts, and numregs the number of registers in the table.
52
- * We return the results of the lookups.
53
- */
54
- int shift;
55
-
56
- for (shift = 0; shift < 64; shift += 8) {
57
- int index = extract64(indices, shift, 8);
58
- if (index < 16 * numregs) {
59
- /* Convert index (a byte offset into the virtual table
60
- * which is a series of 128-bit vectors concatenated)
61
- * into the correct register element plus a bit offset
62
- * into that element, bearing in mind that the table
63
- * can wrap around from V31 to V0.
64
- */
65
- int elt = (rn * 2 + (index >> 3)) % 64;
66
- int bitidx = (index & 7) * 8;
67
- uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
68
- uint64_t val = extract64(q[elt & 1], bitidx, 8);
69
-
70
- result = deposit64(result, shift, 8, val);
71
- }
72
- }
73
- return result;
74
-}
75
-
76
/* 64bit/double versions of the neon float compare functions */
77
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
21
{
78
{
22
int fd, retval;
79
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
+ Error *err = NULL;
80
index XXXXXXX..XXXXXXX 100644
24
81
--- a/target/arm/translate-a64.c
25
fd = open(path(filename), O_RDONLY);
82
+++ b/target/arm/translate-a64.c
26
if (fd < 0) {
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
27
- goto exit_perror;
84
int rm = extract32(insn, 16, 5);
28
+ error_setg_file_open(&err, errno, filename);
85
int rn = extract32(insn, 5, 5);
29
+ error_report_err(err);
86
int rd = extract32(insn, 0, 5);
30
+ exit(-1);
87
- int is_tblx = extract32(insn, 12, 1);
88
- int len = extract32(insn, 13, 2);
89
- TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
90
- TCGv_i32 tcg_regno, tcg_numregs;
91
+ int is_tbx = extract32(insn, 12, 1);
92
+ int len = (extract32(insn, 13, 2) + 1) * 16;
93
94
if (op2 != 0) {
95
unallocated_encoding(s);
96
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
97
return;
31
}
98
}
32
99
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
100
- /* This does a table lookup: for every byte element in the input
34
if (retval < 0) {
101
- * we index into a table formed from up to four vector registers,
35
- goto exit_perror;
102
- * and then the output is the result of the lookups. Our helper
36
+ error_setg_errno(&err, errno, "Error reading file header");
103
- * function does the lookup operation for a single 64 bit part of
37
+ error_reportf_err(err, "%s: ", filename);
104
- * the input.
38
+ exit(-1);
105
- */
39
}
106
- tcg_resl = tcg_temp_new_i64();
40
+
107
- tcg_resh = NULL;
41
if (retval < BPRM_BUF_SIZE) {
108
-
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
109
- if (is_tblx) {
43
}
110
- read_vec_element(s, tcg_resl, rd, 0, MO_64);
44
111
- } else {
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
112
- tcg_gen_movi_i64(tcg_resl, 0);
46
- return;
113
- }
47
-
114
-
48
- exit_perror:
115
- if (is_q) {
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
116
- tcg_resh = tcg_temp_new_i64();
50
- exit(-1);
117
- if (is_tblx) {
118
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
119
- } else {
120
- tcg_gen_movi_i64(tcg_resh, 0);
121
- }
122
- }
123
-
124
- tcg_idx = tcg_temp_new_i64();
125
- tcg_regno = tcg_const_i32(rn);
126
- tcg_numregs = tcg_const_i32(len + 1);
127
- read_vec_element(s, tcg_idx, rm, 0, MO_64);
128
- gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
129
- tcg_regno, tcg_numregs);
130
- if (is_q) {
131
- read_vec_element(s, tcg_idx, rm, 1, MO_64);
132
- gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
133
- tcg_regno, tcg_numregs);
134
- }
135
- tcg_temp_free_i64(tcg_idx);
136
- tcg_temp_free_i32(tcg_regno);
137
- tcg_temp_free_i32(tcg_numregs);
138
-
139
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
140
- tcg_temp_free_i64(tcg_resl);
141
-
142
- if (is_q) {
143
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
144
- tcg_temp_free_i64(tcg_resh);
145
- }
146
- clear_vec_high(s, is_q, rd);
147
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
148
+ vec_full_reg_offset(s, rm), cpu_env,
149
+ is_q ? 16 : 8, vec_full_reg_size(s),
150
+ (len << 6) | (is_tbx << 5) | rn,
151
+ gen_helper_simd_tblx);
51
}
152
}
52
153
53
static int symfind(const void *s0, const void *s1)
154
/* ZIP/UZP/TRN
155
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/vec_helper.c
158
+++ b/target/arm/vec_helper.c
159
@@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
160
DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
161
162
#undef DO_VRINT_RMODE
163
+
164
+#ifdef TARGET_AARCH64
165
+void HELPER(simd_tblx)(void *vd, void *vm, void *venv, uint32_t desc)
166
+{
167
+ const uint8_t *indices = vm;
168
+ CPUARMState *env = venv;
169
+ size_t oprsz = simd_oprsz(desc);
170
+ uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5);
171
+ bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1);
172
+ uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6);
173
+ union {
174
+ uint8_t b[16];
175
+ uint64_t d[2];
176
+ } result;
177
+
178
+ /*
179
+ * We must construct the final result in a temp, lest the output
180
+ * overlaps the input table. For TBL, begin with zero; for TBX,
181
+ * begin with the original register contents. Note that we always
182
+ * copy 16 bytes here to avoid an extra branch; clearing the high
183
+ * bits of the register for oprsz == 8 is handled below.
184
+ */
185
+ if (is_tbx) {
186
+ memcpy(&result, vd, 16);
187
+ } else {
188
+ memset(&result, 0, 16);
189
+ }
190
+
191
+ for (size_t i = 0; i < oprsz; ++i) {
192
+ uint32_t index = indices[H1(i)];
193
+
194
+ if (index < table_len) {
195
+ /*
196
+ * Convert index (a byte offset into the virtual table
197
+ * which is a series of 128-bit vectors concatenated)
198
+ * into the correct register element, bearing in mind
199
+ * that the table can wrap around from V31 to V0.
200
+ */
201
+ const uint8_t *table = (const uint8_t *)
202
+ aa64_vfp_qreg(env, (rn + (index >> 4)) % 32);
203
+ result.b[H1(i)] = table[H1(index % 16)];
204
+ }
205
+ }
206
+
207
+ memcpy(vd, &result, 16);
208
+ clear_tail(vd, oprsz, simd_maxsz(desc));
209
+}
210
+#endif
54
--
211
--
55
2.20.1
212
2.20.1
56
213
57
214
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Add trace events for GPU and CPU IRQs.
3
The STATUS register will be reset to IDLE in
4
cnpcm7xx_smbus_enter_reset(), no need to preset
5
it in instance_init().
4
6
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210228224813.312532-1-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
hw/intc/bcm2835_ic.c | 4 +++-
12
hw/i2c/npcm7xx_smbus.c | 1 -
11
hw/intc/trace-events | 4 ++++
13
1 file changed, 1 deletion(-)
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
14
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
17
--- a/hw/i2c/npcm7xx_smbus.c
17
+++ b/hw/intc/bcm2835_ic.c
18
+++ b/hw/i2c/npcm7xx_smbus.c
18
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_init(Object *obj)
19
#include "migration/vmstate.h"
20
sysbus_init_mmio(sbd, &s->iomem);
20
#include "qemu/log.h"
21
21
#include "qemu/module.h"
22
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
22
+#include "trace.h"
23
- s->status = NPCM7XX_SMBUS_STATUS_IDLE;
23
24
#define GPU_IRQS 64
25
#define ARM_IRQS 8
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
31
}
24
}
32
25
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
26
static const VMStateDescription vmstate_npcm7xx_smbus = {
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
35
BCM2835ICState *s = opaque;
36
37
assert(irq >= 0 && irq < 64);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
40
bcm2835_ic_update(s);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
43
BCM2835ICState *s = opaque;
44
45
assert(irq >= 0 && irq < 8);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
48
bcm2835_ic_update(s);
49
}
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
27
--
63
2.20.1
28
2.20.1
64
29
65
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: schspa <schspa@gmail.com>
2
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
3
At the moment the following QEMU command line triggers an assertion
4
failure On xlnx-versal SOC:
5
qemu-system-aarch64 \
6
-machine xlnx-versal-virt -nographic -smp 2 -m 128 \
7
-fsdev local,id=shareid,path=${HOME}/work,security_model=none \
8
-device virtio-9p-device,fsdev=shareid,mount_tag=share \
9
-fsdev local,id=shareid1,path=${HOME}/Music,security_model=none \
10
-device virtio-9p-device,fsdev=shareid1,mount_tag=share1
4
11
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
qemu-system-aarch64: ../migration/savevm.c:860:
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
13
vmstate_register_with_alias_id:
14
Assertion `!se->compat || se->instance_id == 0' failed.
15
16
This problem was fixed on arm virt platform in commit f58b39d2d5b
17
("virtio-mmio: format transport base address in BusClass.get_dev_path")
18
19
It works perfectly on arm virt platform. but there is still there on
20
xlnx-versal SOC.
21
22
The main difference between arm virt and xlnx-versal is they use
23
different way to create virtio-mmio qdev. on arm virt, it calls
24
sysbus_create_simple("virtio-mmio", base, pic[irq]); which will call
25
sysbus_mmio_map internally and assign base address to subsys device
26
mmio correctly. but xlnx-versal's implements won't do this.
27
28
However, xlnx-versal can't switch to sysbus_create_simple() to create
29
virtio-mmio device. It's because xlnx-versal's cpu use
30
VersalVirt.soc.fpd.apu.mr as it's memory. which is subregion of
31
system_memory. sysbus_create_simple will add virtio to system_memory,
32
which can't be accessed by cpu.
33
34
Besides, xlnx-versal can't add sysbus_mmio_map api call too, because
35
this will add memory region to system_memory, and it can't be added
36
to VersalVirt.soc.fpd.apu.mr again.
37
38
We can solve this by assign correct base address offset on dev_path.
39
40
This path was test on aarch64 virt & xlnx-versal platform.
41
42
Signed-off-by: schspa <schspa@gmail.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
45
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
46
hw/virtio/virtio-mmio.c | 13 +++++++------
11
1 file changed, 46 insertions(+), 2 deletions(-)
47
1 file changed, 7 insertions(+), 6 deletions(-)
12
48
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
49
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
14
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
51
--- a/hw/virtio/virtio-mmio.c
16
+++ b/linux-user/elfload.c
52
+++ b/hw/virtio/virtio-mmio.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
53
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
18
54
BusState *virtio_mmio_bus;
19
#include "elf.h"
55
VirtIOMMIOProxy *virtio_mmio_proxy;
20
56
char *proxy_path;
21
+/* We must delay the following stanzas until after "elf.h". */
57
- SysBusDevice *proxy_sbd;
22
+#if defined(TARGET_AARCH64)
58
char *path;
59
+ MemoryRegionSection section;
60
61
virtio_mmio_bus = qdev_get_parent_bus(dev);
62
virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
63
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
64
}
65
66
/* Otherwise, we append the base address of the transport. */
67
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
68
- assert(proxy_sbd->num_mmio == 1);
69
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
70
+ section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
71
+ assert(section.mr);
72
73
if (proxy_path) {
74
path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
75
- proxy_sbd->mmio[0].addr);
76
+ section.offset_within_address_space);
77
} else {
78
path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
79
- proxy_sbd->mmio[0].addr);
80
+ section.offset_within_address_space);
81
}
82
+ memory_region_unref(section.mr);
23
+
83
+
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
84
g_free(proxy_path);
25
+ const uint32_t *data,
85
return path;
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
86
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
87
--
101
2.20.1
88
2.20.1
102
89
103
90
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Peter Collingbourne <pcc@google.com>
2
2
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
3
Section D6.7 of the ARM ARM states:
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
6
4
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
5
For the purpose of determining Tag Check Fault handling, unprivileged
8
(2) Report "data abort same el" not "data abort lower el".
6
load and store instructions are treated as if executed at EL0 when
7
executed at either:
8
- EL1, when the Effective value of PSTATE.UAO is 0.
9
- EL2, when both the Effective value of HCR_EL2.{E2H, TGE} is {1, 1}
10
and the Effective value of PSTATE.UAO is 0.
9
11
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
ARM has confirmed a defect in the pseudocode function
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
AArch64.TagCheckFault that makes it inconsistent with the above
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
wording. The remedy is to adjust references to PSTATE.EL in that
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
function to instead refer to AArch64.AccessUsesEL(acctype), so
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
16
that unprivileged instructions use SCTLR_EL1.TCF0 and TFSRE0_EL1.
17
The exception type for synchronous tag check faults remains unchanged.
18
19
This patch implements the described change by partially reverting
20
commits 50244cc76abc and cc97b0019bb5.
21
22
Signed-off-by: Peter Collingbourne <pcc@google.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210219201820.2672077-1-pcc@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
27
---
17
target/arm/mte_helper.c | 10 +++-------
28
target/arm/helper.c | 2 +-
18
1 file changed, 3 insertions(+), 7 deletions(-)
29
target/arm/mte_helper.c | 13 +++++++++----
30
2 files changed, 10 insertions(+), 5 deletions(-)
19
31
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
35
+++ b/target/arm/helper.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
37
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
38
&& tbid
39
&& !(env->pstate & PSTATE_TCO)
40
- && (sctlr & SCTLR_TCF)
41
+ && (sctlr & SCTLR_TCF0)
42
&& allocation_tag_access_enabled(env, 0, sctlr)) {
43
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
44
}
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
45
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
21
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
47
--- a/target/arm/mte_helper.c
23
+++ b/target/arm/mte_helper.c
48
+++ b/target/arm/mte_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
49
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
25
reg_el = regime_el(env, arm_mmu_idx);
50
reg_el = regime_el(env, arm_mmu_idx);
26
sctlr = env->cp15.sctlr_el[reg_el];
51
sctlr = env->cp15.sctlr_el[reg_el];
27
52
28
- switch (arm_mmu_idx) {
53
- el = arm_current_el(env);
29
- case ARMMMUIdx_E10_0:
54
- if (el == 0) {
30
- case ARMMMUIdx_E20_0:
55
+ switch (arm_mmu_idx) {
31
- el = 0;
56
+ case ARMMMUIdx_E10_0:
32
+ el = arm_current_el(env);
57
+ case ARMMMUIdx_E20_0:
33
+ if (el == 0) {
58
+ el = 0;
34
tcf = extract64(sctlr, 38, 2);
59
tcf = extract64(sctlr, 38, 2);
35
- break;
60
- } else {
36
- default:
61
+ break;
37
- el = reg_el;
62
+ default:
38
+ } else {
63
+ el = reg_el;
39
tcf = extract64(sctlr, 40, 2);
64
tcf = extract64(sctlr, 40, 2);
40
}
65
}
66
67
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
68
env->exception.vaddress = dirty_ptr;
69
70
is_write = FIELD_EX32(desc, MTEDESC, WRITE);
71
- syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11);
72
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
73
+ is_write, 0x11);
74
raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env));
75
/* noreturn, but fall through to the assert anyway */
41
76
42
--
77
--
43
2.20.1
78
2.20.1
44
79
45
80
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
The variable holding the CTRL_STATUS register is misnamed
3
IDAU is specific to M-profile. KVM only supports A-profile.
4
'status'. Rename it 'ctrl_status' to make it more obvious
4
Restrict this interface to TCG, as it is pointless (and
5
this register is also used to control the peripheral.
5
confusing) on a KVM-only build.
6
6
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
10
Message-id: 20210221222617.2579610-2-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
13
target/arm/cpu.c | 7 -------
14
hw/timer/bcm2835_systmr.c | 8 ++++----
14
target/arm/cpu_tcg.c | 8 ++++++++
15
2 files changed, 5 insertions(+), 5 deletions(-)
15
2 files changed, 8 insertions(+), 7 deletions(-)
16
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
19
--- a/target/arm/cpu.c
20
+++ b/include/hw/timer/bcm2835_systmr.h
20
+++ b/target/arm/cpu.c
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
22
qemu_irq irq;
22
.class_init = arm_cpu_class_init,
23
24
struct {
25
- uint32_t status;
26
+ uint32_t ctrl_status;
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
28
} reg;
29
};
23
};
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
24
25
-static const TypeInfo idau_interface_type_info = {
26
- .name = TYPE_IDAU_INTERFACE,
27
- .parent = TYPE_INTERFACE,
28
- .class_size = sizeof(IDAUInterfaceClass),
29
-};
30
-
31
static void arm_cpu_register_types(void)
32
{
33
const size_t cpu_count = ARRAY_SIZE(arm_cpus);
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
35
if (cpu_count) {
36
size_t i;
37
38
- type_register_static(&idau_interface_type_info);
39
for (i = 0; i < cpu_count; ++i) {
40
arm_cpu_register(&arm_cpus[i]);
41
}
42
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
31
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
44
--- a/target/arm/cpu_tcg.c
33
+++ b/hw/timer/bcm2835_systmr.c
45
+++ b/target/arm/cpu_tcg.c
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
46
@@ -XXX,XX +XXX,XX @@
35
47
#include "hw/core/tcg-cpu-ops.h"
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
48
#endif /* CONFIG_TCG */
49
#include "internals.h"
50
+#include "target/arm/idau.h"
51
52
/* CPU models. These are not needed for the AArch64 linux-user build. */
53
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
55
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
56
};
57
58
+static const TypeInfo idau_interface_type_info = {
59
+ .name = TYPE_IDAU_INTERFACE,
60
+ .parent = TYPE_INTERFACE,
61
+ .class_size = sizeof(IDAUInterfaceClass),
62
+};
63
+
64
static void arm_tcg_cpu_register_types(void)
37
{
65
{
38
- bool enable = !!s->reg.status;
66
size_t i;
39
+ bool enable = !!s->reg.ctrl_status;
67
40
68
+ type_register_static(&idau_interface_type_info);
41
trace_bcm2835_systmr_irq(enable);
69
for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) {
42
qemu_set_irq(s->irq, enable);
70
arm_cpu_register(&arm_tcg_cpus[i]);
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
71
}
44
45
switch (offset) {
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
70
--
72
--
71
2.20.1
73
2.20.1
72
74
73
75
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
3
We will move this code in the next commit. Clean it up
4
first to avoid checkpatch.pl errors.
4
5
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Message-id: 20210221222617.2579610-3-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
hw/arm/strongarm.c | 2 +-
11
target/arm/cpu.c | 12 ++++++++----
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 8 insertions(+), 4 deletions(-)
12
13
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
16
--- a/target/arm/cpu.c
16
+++ b/hw/arm/strongarm.c
17
+++ b/target/arm/cpu.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
18
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
18
uint8_t rx_start;
19
}
19
uint8_t rx_len;
20
20
21
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
22
- /* power_control should be set to maximum latency. Again,
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
23
+ /*
23
bool wait_break_end;
24
+ * power_control should be set to maximum latency. Again,
24
QEMUTimer *rx_timeout_timer;
25
* default to 0 and set by private hook
25
QEMUTimer *tx_timer;
26
*/
27
{ .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
28
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
29
set_feature(&cpu->env, ARM_FEATURE_NEON);
30
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
31
set_feature(&cpu->env, ARM_FEATURE_EL3);
32
- /* Note that A9 supports the MP extensions even for
33
+ /*
34
+ * Note that A9 supports the MP extensions even for
35
* A9UP and single-core A9MP (which are both different
36
* and valid configurations; we don't model A9UP).
37
*/
38
@@ -XXX,XX +XXX,XX @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
39
{
40
MachineState *ms = MACHINE(qdev_get_machine());
41
42
- /* Linux wants the number of processors from here.
43
+ /*
44
+ * Linux wants the number of processors from here.
45
* Might as well set the interrupt-controller bit too.
46
*/
47
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
48
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
49
cpu->isar.id_mmfr1 = 0x40000000;
50
cpu->isar.id_mmfr2 = 0x01240000;
51
cpu->isar.id_mmfr3 = 0x02102211;
52
- /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
53
+ /*
54
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
55
* table 4-41 gives 0x02101110, which includes the arm div insns.
56
*/
57
cpu->isar.id_isar0 = 0x02101110;
26
--
58
--
27
2.20.1
59
2.20.1
28
60
29
61
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
code from the milkymist display device which was handling the
4
possibility that the console surface was some other format.
2
5
3
Unlike many other bits in HCR_EL2, the description for this
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
bit does not contain the phrase "if ... this field behaves
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
as 0 for all purposes other than", so do not squash the bit
8
Message-id: 20210215103215.4944-2-peter.maydell@linaro.org
6
in arm_hcr_el2_eff.
9
---
10
hw/arm/musicpal.c | 64 ++++++++++++++++++-----------------------------
11
1 file changed, 24 insertions(+), 40 deletions(-)
7
12
8
Instead, replicate the E2H+TGE test in the two places that
13
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/internals.h | 9 +++++----
19
target/arm/helper.c | 9 +++++----
20
2 files changed, 10 insertions(+), 8 deletions(-)
21
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
15
--- a/hw/arm/musicpal.c
25
+++ b/target/arm/internals.h
16
+++ b/hw/arm/musicpal.c
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
17
@@ -XXX,XX +XXX,XX @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
28
return false;
29
}
18
}
30
- if (el < 2
19
}
31
- && arm_feature(env, ARM_FEATURE_EL2)
20
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
21
-#define SET_LCD_PIXEL(depth, type) \
33
- return false;
22
-static inline void glue(set_lcd_pixel, depth) \
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
23
- (musicpal_lcd_state *s, int x, int y, type col) \
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
24
-{ \
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
25
- int dx, dy; \
37
+ return false;
26
- DisplaySurface *surface = qemu_console_surface(s->con); \
27
- type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
28
-\
29
- for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
30
- for (dx = 0; dx < 3; dx++, pixel++) \
31
- *pixel = col; \
32
+static inline void set_lcd_pixel32(musicpal_lcd_state *s,
33
+ int x, int y, uint32_t col)
34
+{
35
+ int dx, dy;
36
+ DisplaySurface *surface = qemu_console_surface(s->con);
37
+ uint32_t *pixel =
38
+ &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
39
+
40
+ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
41
+ for (dx = 0; dx < 3; dx++, pixel++) {
42
+ *pixel = col;
43
+ }
44
+ }
45
}
46
-SET_LCD_PIXEL(8, uint8_t)
47
-SET_LCD_PIXEL(16, uint16_t)
48
-SET_LCD_PIXEL(32, uint32_t)
49
50
static void lcd_refresh(void *opaque)
51
{
52
musicpal_lcd_state *s = opaque;
53
- DisplaySurface *surface = qemu_console_surface(s->con);
54
int x, y, col;
55
56
- switch (surface_bits_per_pixel(surface)) {
57
- case 0:
58
- return;
59
-#define LCD_REFRESH(depth, func) \
60
- case depth: \
61
- col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
62
- scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
63
- scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
64
- for (x = 0; x < 128; x++) { \
65
- for (y = 0; y < 64; y++) { \
66
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
67
- glue(set_lcd_pixel, depth)(s, x, y, col); \
68
- } else { \
69
- glue(set_lcd_pixel, depth)(s, x, y, 0); \
70
- } \
71
- } \
72
- } \
73
- break;
74
- LCD_REFRESH(8, rgb_to_pixel8)
75
- LCD_REFRESH(16, rgb_to_pixel16)
76
- LCD_REFRESH(32, (is_surface_bgr(surface) ?
77
- rgb_to_pixel32bgr : rgb_to_pixel32))
78
- default:
79
- hw_error("unsupported colour depth %i\n",
80
- surface_bits_per_pixel(surface));
81
+ col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
82
+ scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
83
+ scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
84
+ for (x = 0; x < 128; x++) {
85
+ for (y = 0; y < 64; y++) {
86
+ if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
87
+ set_lcd_pixel32(s, x, y, col);
88
+ } else {
89
+ set_lcd_pixel32(s, x, y, 0);
90
+ }
38
+ }
91
+ }
39
}
92
}
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
93
41
return sctlr != 0;
94
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
47
{
48
int el = arm_current_el(env);
49
50
- if (el < 2 &&
51
- arm_feature(env, ARM_FEATURE_EL2) &&
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
53
- return CP_ACCESS_TRAP_EL2;
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
57
+ return CP_ACCESS_TRAP_EL2;
58
+ }
59
}
60
if (el < 3 &&
61
arm_feature(env, ARM_FEATURE_EL3) &&
62
--
95
--
63
2.20.1
96
2.20.1
64
97
65
98
diff view generated by jsdifflib
New patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
code from the tc6393xb display device which was handling the
4
possibility that the console surface was some other format.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-3-peter.maydell@linaro.org
9
---
10
include/ui/console.h | 10 ----------
11
hw/display/tc6393xb.c | 33 +--------------------------------
12
2 files changed, 1 insertion(+), 42 deletions(-)
13
14
diff --git a/include/ui/console.h b/include/ui/console.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/ui/console.h
17
+++ b/include/ui/console.h
18
@@ -XXX,XX +XXX,XX @@ PixelFormat qemu_default_pixelformat(int bpp);
19
DisplaySurface *qemu_create_displaysurface(int width, int height);
20
void qemu_free_displaysurface(DisplaySurface *surface);
21
22
-static inline int is_surface_bgr(DisplaySurface *surface)
23
-{
24
- if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
25
- PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
26
- return 1;
27
- } else {
28
- return 0;
29
- }
30
-}
31
-
32
static inline int is_buffer_shared(DisplaySurface *surface)
33
{
34
return !(surface->flags & QEMU_ALLOCATED_FLAG);
35
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/display/tc6393xb.c
38
+++ b/hw/display/tc6393xb.c
39
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
40
(uint32_t) addr, value & 0xff);
41
}
42
43
-#define BITS 8
44
-#include "tc6393xb_template.h"
45
-#define BITS 15
46
-#include "tc6393xb_template.h"
47
-#define BITS 16
48
-#include "tc6393xb_template.h"
49
-#define BITS 24
50
-#include "tc6393xb_template.h"
51
#define BITS 32
52
#include "tc6393xb_template.h"
53
54
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
55
{
56
- DisplaySurface *surface = qemu_console_surface(s->con);
57
-
58
- switch (surface_bits_per_pixel(surface)) {
59
- case 8:
60
- tc6393xb_draw_graphic8(s);
61
- break;
62
- case 15:
63
- tc6393xb_draw_graphic15(s);
64
- break;
65
- case 16:
66
- tc6393xb_draw_graphic16(s);
67
- break;
68
- case 24:
69
- tc6393xb_draw_graphic24(s);
70
- break;
71
- case 32:
72
- tc6393xb_draw_graphic32(s);
73
- break;
74
- default:
75
- printf("tc6393xb: unknown depth %d\n",
76
- surface_bits_per_pixel(surface));
77
- return;
78
- }
79
-
80
+ tc6393xb_draw_graphic32(s);
81
dpy_gfx_update_full(s->con);
82
}
83
84
--
85
2.20.1
86
87
diff view generated by jsdifflib
New patch
1
Now the template header is included only for BITS==32, expand
2
out all the macros that depended on the BITS setting.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215103215.4944-4-peter.maydell@linaro.org
7
---
8
hw/display/tc6393xb_template.h | 35 ++++------------------------------
9
1 file changed, 4 insertions(+), 31 deletions(-)
10
11
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/tc6393xb_template.h
14
+++ b/hw/display/tc6393xb_template.h
15
@@ -XXX,XX +XXX,XX @@
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
-#if BITS == 8
20
-# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
21
-#elif BITS == 15 || BITS == 16
22
-# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
23
-#elif BITS == 24
24
-# define SET_PIXEL(addr, color) \
25
- do { \
26
- addr[0] = color; \
27
- addr[1] = (color) >> 8; \
28
- addr[2] = (color) >> 16; \
29
- } while (0)
30
-#elif BITS == 32
31
-# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
32
-#else
33
-# error unknown bit depth
34
-#endif
35
-
36
-
37
-static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
38
+static void tc6393xb_draw_graphic32(TC6393xbState *s)
39
{
40
DisplaySurface *surface = qemu_console_surface(s->con);
41
int i;
42
@@ -XXX,XX +XXX,XX @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
43
data_buffer = s->vram_ptr;
44
data_display = surface_data(surface);
45
for(i = 0; i < s->scr_height; i++) {
46
-#if (BITS == 16)
47
- memcpy(data_display, data_buffer, s->scr_width * 2);
48
- data_buffer += s->scr_width;
49
- data_display += surface_stride(surface);
50
-#else
51
int j;
52
- for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
53
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
54
uint16_t color = *data_buffer;
55
- uint32_t dest_color = glue(rgb_to_pixel, BITS)(
56
+ uint32_t dest_color = rgb_to_pixel32(
57
((color & 0xf800) * 0x108) >> 11,
58
((color & 0x7e0) * 0x41) >> 9,
59
((color & 0x1f) * 0x21) >> 2
60
);
61
- SET_PIXEL(data_display, dest_color);
62
+ *(uint32_t *)data_display = dest_color;
63
}
64
-#endif
65
}
66
}
67
-
68
-#undef BITS
69
-#undef SET_PIXEL
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The function tc6393xb_draw_graphic32() is called in exactly one place,
2
so just inline the function body at its callsite. This allows us to
3
drop the template header entirely.
2
4
3
This is a bit clearer than open-coding some of this
5
The code move includes a single added space after 'for' to fix
4
with a bare c string.
6
the coding style.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
11
Message-id: 20210215103215.4944-5-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
13
hw/display/tc6393xb_template.h | 45 ----------------------------------
12
1 file changed, 20 insertions(+), 17 deletions(-)
14
hw/display/tc6393xb.c | 23 ++++++++++++++---
15
2 files changed, 19 insertions(+), 49 deletions(-)
16
delete mode 100644 hw/display/tc6393xb_template.h
13
17
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
19
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- a/hw/display/tc6393xb_template.h
22
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
24
-/*
25
- * Toshiba TC6393XB I/O Controller.
26
- * Found in Sharp Zaurus SL-6000 (tosa) or some
27
- * Toshiba e-Series PDAs.
28
- *
29
- * FB support code. Based on G364 fb emulator
30
- *
31
- * Copyright (c) 2007 Hervé Poussineau
32
- *
33
- * This program is free software; you can redistribute it and/or
34
- * modify it under the terms of the GNU General Public License as
35
- * published by the Free Software Foundation; either version 2 of
36
- * the License, or (at your option) any later version.
37
- *
38
- * This program is distributed in the hope that it will be useful,
39
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- * GNU General Public License for more details.
42
- *
43
- * You should have received a copy of the GNU General Public License along
44
- * with this program; if not, see <http://www.gnu.org/licenses/>.
45
- */
46
-
47
-static void tc6393xb_draw_graphic32(TC6393xbState *s)
48
-{
49
- DisplaySurface *surface = qemu_console_surface(s->con);
50
- int i;
51
- uint16_t *data_buffer;
52
- uint8_t *data_display;
53
-
54
- data_buffer = s->vram_ptr;
55
- data_display = surface_data(surface);
56
- for(i = 0; i < s->scr_height; i++) {
57
- int j;
58
- for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
59
- uint16_t color = *data_buffer;
60
- uint32_t dest_color = rgb_to_pixel32(
61
- ((color & 0xf800) * 0x108) >> 11,
62
- ((color & 0x7e0) * 0x41) >> 9,
63
- ((color & 0x1f) * 0x21) >> 2
64
- );
65
- *(uint32_t *)data_display = dest_color;
66
- }
67
- }
68
-}
69
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
15
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
71
--- a/hw/display/tc6393xb.c
17
+++ b/linux-user/elfload.c
72
+++ b/hw/display/tc6393xb.c
18
@@ -XXX,XX +XXX,XX @@
73
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
19
#include "qemu/guest-random.h"
74
(uint32_t) addr, value & 0xff);
20
#include "qemu/units.h"
75
}
21
#include "qemu/selfmap.h"
76
22
+#include "qapi/error.h"
77
-#define BITS 32
23
78
-#include "tc6393xb_template.h"
24
#ifdef _ARCH_PPC64
79
-
25
#undef ARCH_DLINFO
80
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
81
{
27
struct elf_phdr *phdr;
82
- tc6393xb_draw_graphic32(s);
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
83
+ DisplaySurface *surface = qemu_console_surface(s->con);
29
int i, retval;
84
+ int i;
30
- const char *errmsg;
85
+ uint16_t *data_buffer;
31
+ Error *err = NULL;
86
+ uint8_t *data_display;
32
33
/* First of all, some simple consistency checks */
34
- errmsg = "Invalid ELF image for this architecture";
35
if (!elf_check_ident(ehdr)) {
36
+ error_setg(&err, "Invalid ELF image for this architecture");
37
goto exit_errmsg;
38
}
39
bswap_ehdr(ehdr);
40
if (!elf_check_ehdr(ehdr)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
87
+
54
interp_name = g_malloc(eppnt->p_filesz);
88
+ data_buffer = s->vram_ptr;
55
- if (!interp_name) {
89
+ data_display = surface_data(surface);
56
- goto exit_perror;
90
+ for (i = 0; i < s->scr_height; i++) {
57
- }
91
+ int j;
58
92
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
93
+ uint16_t color = *data_buffer;
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
94
+ uint32_t dest_color = rgb_to_pixel32(
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
95
+ ((color & 0xf800) * 0x108) >> 11,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
96
+ ((color & 0x7e0) * 0x41) >> 9,
63
eppnt->p_offset);
97
+ ((color & 0x1f) * 0x21) >> 2
64
if (retval != eppnt->p_filesz) {
98
+ );
65
- goto exit_perror;
99
+ *(uint32_t *)data_display = dest_color;
66
+ goto exit_read;
100
+ }
67
}
101
+ }
68
}
102
dpy_gfx_update_full(s->con);
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
103
}
132
104
133
--
105
--
134
2.20.1
106
2.20.1
135
107
136
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The omap_lcdc template header is already only included once, for
2
DEPTH==32, but it still has all the macro-driven parameterization
3
for other depths. Expand out all the macros in the header.
2
4
3
Fixing this now will clarify following patches.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210215103215.4944-6-peter.maydell@linaro.org
9
---
10
hw/display/omap_lcd_template.h | 67 ++++++++++++++--------------------
11
1 file changed, 28 insertions(+), 39 deletions(-)
4
12
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 12 +++++++++---
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
15
--- a/hw/display/omap_lcd_template.h
16
+++ b/linux-user/elfload.c
16
+++ b/hw/display/omap_lcd_template.h
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
17
@@ -XXX,XX +XXX,XX @@
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
18
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
int elf_prot = 0;
19
*/
20
20
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
21
-#if DEPTH == 32
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
22
-# define BPP 4
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
23
-# define PIXEL_TYPE uint32_t
24
+ if (eppnt->p_flags & PF_R) {
24
-#else
25
+ elf_prot |= PROT_READ;
25
-# error unsupport depth
26
+ }
26
-#endif
27
+ if (eppnt->p_flags & PF_W) {
27
-
28
+ elf_prot |= PROT_WRITE;
28
/*
29
+ }
29
* 2-bit colour
30
+ if (eppnt->p_flags & PF_X) {
30
*/
31
+ elf_prot |= PROT_EXEC;
31
-static void glue(draw_line2_, DEPTH)(void *opaque,
32
+ }
32
- uint8_t *d, const uint8_t *s, int width, int deststep)
33
33
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
34
vaddr = load_bias + eppnt->p_vaddr;
34
+ int width, int deststep)
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
35
{
36
uint16_t *pal = opaque;
37
uint8_t v, r, g, b;
38
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
39
r = (pal[v & 3] >> 4) & 0xf0;
40
g = pal[v & 3] & 0xf0;
41
b = (pal[v & 3] << 4) & 0xf0;
42
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
43
- d += BPP;
44
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
45
+ d += 4;
46
v >>= 2;
47
r = (pal[v & 3] >> 4) & 0xf0;
48
g = pal[v & 3] & 0xf0;
49
b = (pal[v & 3] << 4) & 0xf0;
50
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
51
- d += BPP;
52
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
53
+ d += 4;
54
v >>= 2;
55
r = (pal[v & 3] >> 4) & 0xf0;
56
g = pal[v & 3] & 0xf0;
57
b = (pal[v & 3] << 4) & 0xf0;
58
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
59
- d += BPP;
60
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
61
+ d += 4;
62
v >>= 2;
63
r = (pal[v & 3] >> 4) & 0xf0;
64
g = pal[v & 3] & 0xf0;
65
b = (pal[v & 3] << 4) & 0xf0;
66
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
67
- d += BPP;
68
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
69
+ d += 4;
70
s ++;
71
width -= 4;
72
} while (width > 0);
73
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
74
/*
75
* 4-bit colour
76
*/
77
-static void glue(draw_line4_, DEPTH)(void *opaque,
78
- uint8_t *d, const uint8_t *s, int width, int deststep)
79
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
80
+ int width, int deststep)
81
{
82
uint16_t *pal = opaque;
83
uint8_t v, r, g, b;
84
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
85
r = (pal[v & 0xf] >> 4) & 0xf0;
86
g = pal[v & 0xf] & 0xf0;
87
b = (pal[v & 0xf] << 4) & 0xf0;
88
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
89
- d += BPP;
90
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
91
+ d += 4;
92
v >>= 4;
93
r = (pal[v & 0xf] >> 4) & 0xf0;
94
g = pal[v & 0xf] & 0xf0;
95
b = (pal[v & 0xf] << 4) & 0xf0;
96
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
97
- d += BPP;
98
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
99
+ d += 4;
100
s ++;
101
width -= 2;
102
} while (width > 0);
103
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
104
/*
105
* 8-bit colour
106
*/
107
-static void glue(draw_line8_, DEPTH)(void *opaque,
108
- uint8_t *d, const uint8_t *s, int width, int deststep)
109
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
110
+ int width, int deststep)
111
{
112
uint16_t *pal = opaque;
113
uint8_t v, r, g, b;
114
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line8_, DEPTH)(void *opaque,
115
r = (pal[v] >> 4) & 0xf0;
116
g = pal[v] & 0xf0;
117
b = (pal[v] << 4) & 0xf0;
118
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
119
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
120
s ++;
121
- d += BPP;
122
+ d += 4;
123
} while (-- width != 0);
124
}
125
126
/*
127
* 12-bit colour
128
*/
129
-static void glue(draw_line12_, DEPTH)(void *opaque,
130
- uint8_t *d, const uint8_t *s, int width, int deststep)
131
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
132
+ int width, int deststep)
133
{
134
uint16_t v;
135
uint8_t r, g, b;
136
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line12_, DEPTH)(void *opaque,
137
r = (v >> 4) & 0xf0;
138
g = v & 0xf0;
139
b = (v << 4) & 0xf0;
140
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
141
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
142
s += 2;
143
- d += BPP;
144
+ d += 4;
145
} while (-- width != 0);
146
}
147
148
/*
149
* 16-bit colour
150
*/
151
-static void glue(draw_line16_, DEPTH)(void *opaque,
152
- uint8_t *d, const uint8_t *s, int width, int deststep)
153
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
154
+ int width, int deststep)
155
{
156
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
157
memcpy(d, s, width * 2);
158
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line16_, DEPTH)(void *opaque,
159
r = (v >> 8) & 0xf8;
160
g = (v >> 3) & 0xfc;
161
b = (v << 3) & 0xf8;
162
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
163
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
164
s += 2;
165
- d += BPP;
166
+ d += 4;
167
} while (-- width != 0);
168
#endif
169
}
170
-
171
-#undef DEPTH
172
-#undef BPP
173
-#undef PIXEL_TYPE
36
--
174
--
37
2.20.1
175
2.20.1
38
176
39
177
diff view generated by jsdifflib
New patch
1
The draw_line16_32() function in the omap_lcdc template header
2
includes an ifdef for the case where HOST_WORDS_BIGENDIAN matches
3
TARGET_WORDS_BIGENDIAN. This is trying to optimise for "source
4
bitmap and destination bitmap format match", but it is broken,
5
because in this function the formats don't match: the source is
6
16-bit colour and the destination is 32-bit colour, so a memcpy()
7
will produce corrupted graphics output. Drop the bogus ifdef.
1
8
9
This bug was introduced in commit ea644cf343129, when we dropped
10
support for DEPTH values other than 32 from the template header.
11
The old #if line was
12
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
13
and this was mistakenly changed to
14
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
15
rather than deleting the #if as now having an always-false condition.
16
17
Fixes: ea644cf343129
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210215103215.4944-7-peter.maydell@linaro.org
22
---
23
hw/display/omap_lcd_template.h | 4 ----
24
1 file changed, 4 deletions(-)
25
26
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/display/omap_lcd_template.h
29
+++ b/hw/display/omap_lcd_template.h
30
@@ -XXX,XX +XXX,XX @@ static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
31
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
32
int width, int deststep)
33
{
34
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
35
- memcpy(d, s, width * 2);
36
-#else
37
uint16_t v;
38
uint8_t r, g, b;
39
40
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
41
s += 2;
42
d += 4;
43
} while (-- width != 0);
44
-#endif
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
New patch
1
Fix some minor coding style issues in the template header,
2
so checkpatch doesn't complain when we move the code.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210215103215.4944-8-peter.maydell@linaro.org
8
---
9
hw/display/omap_lcd_template.h | 6 +++---
10
1 file changed, 3 insertions(+), 3 deletions(-)
11
12
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/display/omap_lcd_template.h
15
+++ b/hw/display/omap_lcd_template.h
16
@@ -XXX,XX +XXX,XX @@ static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
17
b = (pal[v & 3] << 4) & 0xf0;
18
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
19
d += 4;
20
- s ++;
21
+ s++;
22
width -= 4;
23
} while (width > 0);
24
}
25
@@ -XXX,XX +XXX,XX @@ static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
26
b = (pal[v & 0xf] << 4) & 0xf0;
27
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
28
d += 4;
29
- s ++;
30
+ s++;
31
width -= 2;
32
} while (width > 0);
33
}
34
@@ -XXX,XX +XXX,XX @@ static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
35
g = pal[v] & 0xf0;
36
b = (pal[v] << 4) & 0xf0;
37
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
38
- s ++;
39
+ s++;
40
d += 4;
41
} while (-- width != 0);
42
}
43
--
44
2.20.1
45
46
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We only include the template header once, so just inline it into the
2
source file for the device.
2
3
3
These are all of the defines required to parse
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Other missing defines related to other GNU program headers
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
and notes are elided for now.
7
Message-id: 20210215103215.4944-9-peter.maydell@linaro.org
8
---
9
hw/display/omap_lcd_template.h | 154 ---------------------------------
10
hw/display/omap_lcdc.c | 127 ++++++++++++++++++++++++++-
11
2 files changed, 125 insertions(+), 156 deletions(-)
12
delete mode 100644 hw/display/omap_lcd_template.h
7
13
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
deleted file mode 100644
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
16
index XXXXXXX..XXXXXXX
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
--- a/hw/display/omap_lcd_template.h
12
---
18
+++ /dev/null
13
include/elf.h | 22 ++++++++++++++++++++++
19
@@ -XXX,XX +XXX,XX @@
14
1 file changed, 22 insertions(+)
20
-/*
15
21
- * QEMU OMAP LCD Emulator templates
16
diff --git a/include/elf.h b/include/elf.h
22
- *
23
- * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * Redistribution and use in source and binary forms, with or without
26
- * modification, are permitted provided that the following conditions
27
- * are met:
28
- *
29
- * 1. Redistributions of source code must retain the above copyright
30
- * notice, this list of conditions and the following disclaimer.
31
- * 2. Redistributions in binary form must reproduce the above copyright
32
- * notice, this list of conditions and the following disclaimer in
33
- * the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
37
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
38
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
40
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
- */
48
-
49
-/*
50
- * 2-bit colour
51
- */
52
-static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
53
- int width, int deststep)
54
-{
55
- uint16_t *pal = opaque;
56
- uint8_t v, r, g, b;
57
-
58
- do {
59
- v = ldub_p((void *) s);
60
- r = (pal[v & 3] >> 4) & 0xf0;
61
- g = pal[v & 3] & 0xf0;
62
- b = (pal[v & 3] << 4) & 0xf0;
63
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
64
- d += 4;
65
- v >>= 2;
66
- r = (pal[v & 3] >> 4) & 0xf0;
67
- g = pal[v & 3] & 0xf0;
68
- b = (pal[v & 3] << 4) & 0xf0;
69
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
70
- d += 4;
71
- v >>= 2;
72
- r = (pal[v & 3] >> 4) & 0xf0;
73
- g = pal[v & 3] & 0xf0;
74
- b = (pal[v & 3] << 4) & 0xf0;
75
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
76
- d += 4;
77
- v >>= 2;
78
- r = (pal[v & 3] >> 4) & 0xf0;
79
- g = pal[v & 3] & 0xf0;
80
- b = (pal[v & 3] << 4) & 0xf0;
81
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
82
- d += 4;
83
- s++;
84
- width -= 4;
85
- } while (width > 0);
86
-}
87
-
88
-/*
89
- * 4-bit colour
90
- */
91
-static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
92
- int width, int deststep)
93
-{
94
- uint16_t *pal = opaque;
95
- uint8_t v, r, g, b;
96
-
97
- do {
98
- v = ldub_p((void *) s);
99
- r = (pal[v & 0xf] >> 4) & 0xf0;
100
- g = pal[v & 0xf] & 0xf0;
101
- b = (pal[v & 0xf] << 4) & 0xf0;
102
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
103
- d += 4;
104
- v >>= 4;
105
- r = (pal[v & 0xf] >> 4) & 0xf0;
106
- g = pal[v & 0xf] & 0xf0;
107
- b = (pal[v & 0xf] << 4) & 0xf0;
108
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
109
- d += 4;
110
- s++;
111
- width -= 2;
112
- } while (width > 0);
113
-}
114
-
115
-/*
116
- * 8-bit colour
117
- */
118
-static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
119
- int width, int deststep)
120
-{
121
- uint16_t *pal = opaque;
122
- uint8_t v, r, g, b;
123
-
124
- do {
125
- v = ldub_p((void *) s);
126
- r = (pal[v] >> 4) & 0xf0;
127
- g = pal[v] & 0xf0;
128
- b = (pal[v] << 4) & 0xf0;
129
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
130
- s++;
131
- d += 4;
132
- } while (-- width != 0);
133
-}
134
-
135
-/*
136
- * 12-bit colour
137
- */
138
-static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
139
- int width, int deststep)
140
-{
141
- uint16_t v;
142
- uint8_t r, g, b;
143
-
144
- do {
145
- v = lduw_le_p((void *) s);
146
- r = (v >> 4) & 0xf0;
147
- g = v & 0xf0;
148
- b = (v << 4) & 0xf0;
149
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
150
- s += 2;
151
- d += 4;
152
- } while (-- width != 0);
153
-}
154
-
155
-/*
156
- * 16-bit colour
157
- */
158
-static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
159
- int width, int deststep)
160
-{
161
- uint16_t v;
162
- uint8_t r, g, b;
163
-
164
- do {
165
- v = lduw_le_p((void *) s);
166
- r = (v >> 8) & 0xf8;
167
- g = (v >> 3) & 0xfc;
168
- b = (v << 3) & 0xf8;
169
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
170
- s += 2;
171
- d += 4;
172
- } while (-- width != 0);
173
-}
174
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
17
index XXXXXXX..XXXXXXX 100644
175
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
176
--- a/hw/display/omap_lcdc.c
19
+++ b/include/elf.h
177
+++ b/hw/display/omap_lcdc.c
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
178
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
21
#define PT_NOTE 4
179
22
#define PT_SHLIB 5
180
#define draw_line_func drawfn
23
#define PT_PHDR 6
181
24
+#define PT_LOOS 0x60000000
182
-#define DEPTH 32
25
+#define PT_HIOS 0x6fffffff
183
-#include "omap_lcd_template.h"
26
#define PT_LOPROC 0x70000000
184
+/*
27
#define PT_HIPROC 0x7fffffff
185
+ * 2-bit colour
28
186
+ */
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
187
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
30
+
188
+ int width, int deststep)
31
#define PT_MIPS_REGINFO 0x70000000
189
+{
32
#define PT_MIPS_RTPROC 0x70000001
190
+ uint16_t *pal = opaque;
33
#define PT_MIPS_OPTIONS 0x70000002
191
+ uint8_t v, r, g, b;
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
192
+
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
193
+ do {
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
194
+ v = ldub_p((void *) s);
37
195
+ r = (pal[v & 3] >> 4) & 0xf0;
38
+/* Defined note types for GNU systems. */
196
+ g = pal[v & 3] & 0xf0;
39
+
197
+ b = (pal[v & 3] << 4) & 0xf0;
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
198
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
41
+
199
+ d += 4;
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
200
+ v >>= 2;
43
+
201
+ r = (pal[v & 3] >> 4) & 0xf0;
44
+#define GNU_PROPERTY_STACK_SIZE 1
202
+ g = pal[v & 3] & 0xf0;
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
203
+ b = (pal[v & 3] << 4) & 0xf0;
46
+
204
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
205
+ d += 4;
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
206
+ v >>= 2;
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
207
+ r = (pal[v & 3] >> 4) & 0xf0;
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
208
+ g = pal[v & 3] & 0xf0;
51
+
209
+ b = (pal[v & 3] << 4) & 0xf0;
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
210
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
211
+ d += 4;
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
212
+ v >>= 2;
55
+
213
+ r = (pal[v & 3] >> 4) & 0xf0;
56
/*
214
+ g = pal[v & 3] & 0xf0;
57
* Physical entry point into the kernel.
215
+ b = (pal[v & 3] << 4) & 0xf0;
58
*
216
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
217
+ d += 4;
218
+ s++;
219
+ width -= 4;
220
+ } while (width > 0);
221
+}
222
+
223
+/*
224
+ * 4-bit colour
225
+ */
226
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
227
+ int width, int deststep)
228
+{
229
+ uint16_t *pal = opaque;
230
+ uint8_t v, r, g, b;
231
+
232
+ do {
233
+ v = ldub_p((void *) s);
234
+ r = (pal[v & 0xf] >> 4) & 0xf0;
235
+ g = pal[v & 0xf] & 0xf0;
236
+ b = (pal[v & 0xf] << 4) & 0xf0;
237
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
238
+ d += 4;
239
+ v >>= 4;
240
+ r = (pal[v & 0xf] >> 4) & 0xf0;
241
+ g = pal[v & 0xf] & 0xf0;
242
+ b = (pal[v & 0xf] << 4) & 0xf0;
243
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
244
+ d += 4;
245
+ s++;
246
+ width -= 2;
247
+ } while (width > 0);
248
+}
249
+
250
+/*
251
+ * 8-bit colour
252
+ */
253
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
254
+ int width, int deststep)
255
+{
256
+ uint16_t *pal = opaque;
257
+ uint8_t v, r, g, b;
258
+
259
+ do {
260
+ v = ldub_p((void *) s);
261
+ r = (pal[v] >> 4) & 0xf0;
262
+ g = pal[v] & 0xf0;
263
+ b = (pal[v] << 4) & 0xf0;
264
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
265
+ s++;
266
+ d += 4;
267
+ } while (-- width != 0);
268
+}
269
+
270
+/*
271
+ * 12-bit colour
272
+ */
273
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
274
+ int width, int deststep)
275
+{
276
+ uint16_t v;
277
+ uint8_t r, g, b;
278
+
279
+ do {
280
+ v = lduw_le_p((void *) s);
281
+ r = (v >> 4) & 0xf0;
282
+ g = v & 0xf0;
283
+ b = (v << 4) & 0xf0;
284
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
285
+ s += 2;
286
+ d += 4;
287
+ } while (-- width != 0);
288
+}
289
+
290
+/*
291
+ * 16-bit colour
292
+ */
293
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
294
+ int width, int deststep)
295
+{
296
+ uint16_t v;
297
+ uint8_t r, g, b;
298
+
299
+ do {
300
+ v = lduw_le_p((void *) s);
301
+ r = (v >> 8) & 0xf8;
302
+ g = (v >> 3) & 0xfc;
303
+ b = (v << 3) & 0xf8;
304
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
305
+ s += 2;
306
+ d += 4;
307
+ } while (-- width != 0);
308
+}
309
310
static void omap_update_display(void *opaque)
311
{
59
--
312
--
60
2.20.1
313
2.20.1
61
314
62
315
diff view generated by jsdifflib
New patch
1
The macro draw_line_func is used only once; just expand it.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210215103215.4944-10-peter.maydell@linaro.org
7
---
8
hw/display/omap_lcdc.c | 4 +---
9
1 file changed, 1 insertion(+), 3 deletions(-)
10
11
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/omap_lcdc.c
14
+++ b/hw/display/omap_lcdc.c
15
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
16
qemu_irq_lower(s->irq);
17
}
18
19
-#define draw_line_func drawfn
20
-
21
/*
22
* 2-bit colour
23
*/
24
@@ -XXX,XX +XXX,XX @@ static void omap_update_display(void *opaque)
25
{
26
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
27
DisplaySurface *surface;
28
- draw_line_func draw_line;
29
+ drawfn draw_line;
30
int size, height, first, last;
31
int width, linesize, step, bpp, frame_offset;
32
hwaddr frame_base;
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
New patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel, RGB. The TCX code already
3
assumes 32bpp, but it still has some checks of is_surface_bgr()
4
in an attempt to support 32bpp BGR. is_surface_bgr() will always
5
return false for the qemu_console_surface(), unless the display
6
device itself has deliberately created an alternate-format
7
surface via a function like qemu_create_displaysurface_from().
1
8
9
Drop the never-used BGR-handling code, and assert that we have
10
a 32-bit surface rather than just doing nothing if it isn't.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210215102149.20513-1-peter.maydell@linaro.org
16
---
17
hw/display/tcx.c | 31 ++++++++-----------------------
18
1 file changed, 8 insertions(+), 23 deletions(-)
19
20
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/display/tcx.c
23
+++ b/hw/display/tcx.c
24
@@ -XXX,XX +XXX,XX @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
25
26
static void update_palette_entries(TCXState *s, int start, int end)
27
{
28
- DisplaySurface *surface = qemu_console_surface(s->con);
29
int i;
30
31
for (i = start; i < end; i++) {
32
- if (is_surface_bgr(surface)) {
33
- s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
34
- } else {
35
- s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
36
- }
37
+ s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
38
}
39
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
40
}
41
@@ -XXX,XX +XXX,XX @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
42
}
43
44
/*
45
- XXX Could be much more optimal:
46
- * detect if line/page/whole screen is in 24 bit mode
47
- * if destination is also BGR, use memcpy
48
- */
49
+ * XXX Could be much more optimal:
50
+ * detect if line/page/whole screen is in 24 bit mode
51
+ */
52
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
53
const uint8_t *s, int width,
54
const uint32_t *cplane,
55
const uint32_t *s24)
56
{
57
- DisplaySurface *surface = qemu_console_surface(s1->con);
58
- int x, bgr, r, g, b;
59
+ int x, r, g, b;
60
uint8_t val, *p8;
61
uint32_t *p = (uint32_t *)d;
62
uint32_t dval;
63
- bgr = is_surface_bgr(surface);
64
for(x = 0; x < width; x++, s++, s24++) {
65
if (be32_to_cpu(*cplane) & 0x03000000) {
66
/* 24-bit direct, BGR order */
67
@@ -XXX,XX +XXX,XX @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
68
b = *p8++;
69
g = *p8++;
70
r = *p8;
71
- if (bgr)
72
- dval = rgb_to_pixel32bgr(r, g, b);
73
- else
74
- dval = rgb_to_pixel32(r, g, b);
75
+ dval = rgb_to_pixel32(r, g, b);
76
} else {
77
/* 8-bit pseudocolor */
78
val = *s;
79
@@ -XXX,XX +XXX,XX @@ static void tcx_update_display(void *opaque)
80
int y, y_start, dd, ds;
81
uint8_t *d, *s;
82
83
- if (surface_bits_per_pixel(surface) != 32) {
84
- return;
85
- }
86
+ assert(surface_bits_per_pixel(surface) == 32);
87
88
page = 0;
89
y_start = -1;
90
@@ -XXX,XX +XXX,XX @@ static void tcx24_update_display(void *opaque)
91
uint8_t *d, *s;
92
uint32_t *cptr, *s24;
93
94
- if (surface_bits_per_pixel(surface) != 32) {
95
- return;
96
- }
97
+ assert(surface_bits_per_pixel(surface) == 32);
98
99
page = 0;
100
y_start = -1;
101
--
102
2.20.1
103
104
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN524 has a different SYSCLK frequency from the AN505 and AN521;
2
make the SYSCLK frequency a field in the MPS2TZMachineClass rather
3
than a compile-time constant so we can support the AN524.
2
4
3
The second loop uses a loop induction variable, and the first
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
does not. Transform the first to match the second, to simplify
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
a following patch moving code between them.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-2-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 10 ++++++----
11
1 file changed, 6 insertions(+), 4 deletions(-)
6
12
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 9 +++++----
13
1 file changed, 5 insertions(+), 4 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
15
--- a/hw/arm/mps2-tz.c
18
+++ b/linux-user/elfload.c
16
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
20
loaddr = -1, hiaddr = 0;
18
MachineClass parent;
21
info->alignment = 0;
19
MPS2TZFPGAType fpga_type;
22
for (i = 0; i < ehdr->e_phnum; ++i) {
20
uint32_t scc_id;
23
- if (phdr[i].p_type == PT_LOAD) {
21
+ uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
22
const char *armsse_type;
25
+ struct elf_phdr *eppnt = phdr + i;
23
};
26
+ if (eppnt->p_type == PT_LOAD) {
24
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
28
if (a < loaddr) {
26
29
loaddr = a;
27
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
30
}
28
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
29
-/* Main SYSCLK frequency in Hz */
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
30
-#define SYSCLK_FRQ 20000000
33
if (a > hiaddr) {
31
/* Slow 32Khz S32KCLK frequency in Hz */
34
hiaddr = a;
32
#define S32KCLK_FRQ (32 * 1000)
35
}
33
36
++info->nsegs;
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
37
- info->alignment |= phdr[i].p_align;
35
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
38
+ info->alignment |= eppnt->p_align;
36
const char *name, hwaddr size)
39
}
37
{
40
}
38
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
39
CMSDKAPBUART *uart = opaque;
40
int i = uart - &mms->uart[0];
41
int rxirqno = i * 2;
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
43
44
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
45
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
46
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
47
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
48
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
49
s = SYS_BUS_DEVICE(uart);
50
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
51
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
52
53
/* These clocks don't need migration because they are fixed-frequency */
54
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
55
- clock_set_hz(mms->sysclk, SYSCLK_FRQ);
56
+ clock_set_hz(mms->sysclk, mmc->sysclk_frq);
57
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
58
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
59
60
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
61
mmc->fpga_type = FPGA_AN505;
62
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
63
mmc->scc_id = 0x41045050;
64
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
65
mmc->armsse_type = TYPE_IOTKIT;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
69
mmc->fpga_type = FPGA_AN521;
70
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
71
mmc->scc_id = 0x41045210;
72
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
73
mmc->armsse_type = TYPE_SSE200;
74
}
41
75
42
--
76
--
43
2.20.1
77
2.20.1
44
78
45
79
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Currently the MPS2 SCC device implements a fixed number of OSCCLK
2
values (3). The variant of this device in the MPS3 AN524 board has 6
3
OSCCLK values. Switch to using a PROP_ARRAY, which allows board code
4
to specify how large the OSCCLK array should be as well as its
5
values.
2
6
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
7
With a variable-length property array, the SCC no longer specifies
4
magic '4' value.
8
default values for the OSCCLKs, so we must set them explicitly in the
9
board code. This defaults are actually incorrect for the an521 and
10
an505; we will correct this bug in a following patch.
5
11
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
This is a migration compatibility break for all the mps boards.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20210215115138.20465-3-peter.maydell@linaro.org
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
18
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
19
include/hw/misc/mps2-scc.h | 7 +++----
13
hw/timer/bcm2835_systmr.c | 3 ++-
20
hw/arm/mps2-tz.c | 5 +++++
14
2 files changed, 5 insertions(+), 2 deletions(-)
21
hw/arm/mps2.c | 5 +++++
22
hw/misc/mps2-scc.c | 24 +++++++++++++-----------
23
4 files changed, 26 insertions(+), 15 deletions(-)
15
24
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
27
--- a/include/hw/misc/mps2-scc.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
28
+++ b/include/hw/misc/mps2-scc.h
20
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
30
#define TYPE_MPS2_SCC "mps2-scc"
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
31
OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
23
32
24
+#define BCM2835_SYSTIMER_COUNT 4
33
-#define NUM_OSCCLK 3
25
+
34
-
26
struct BCM2835SystemTimerState {
35
struct MPS2SCC {
27
/*< private >*/
36
/*< private >*/
28
SysBusDevice parent_obj;
37
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
38
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
30
39
uint32_t dll;
31
struct {
40
uint32_t aid;
32
uint32_t status;
41
uint32_t id;
33
- uint32_t compare[4];
42
- uint32_t oscclk[NUM_OSCCLK];
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
43
- uint32_t oscclk_reset[NUM_OSCCLK];
35
} reg;
44
+ uint32_t num_oscclk;
45
+ uint32_t *oscclk;
46
+ uint32_t *oscclk_reset;
36
};
47
};
37
48
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
49
#endif
50
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
39
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
52
--- a/hw/arm/mps2-tz.c
41
+++ b/hw/timer/bcm2835_systmr.c
53
+++ b/hw/arm/mps2-tz.c
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
54
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
43
.minimum_version_id = 1,
55
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
56
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
57
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
58
+ /* This will need to be per-FPGA image eventually */
59
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
60
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
61
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
62
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
63
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
64
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
65
}
66
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/mps2.c
69
+++ b/hw/arm/mps2.c
70
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
71
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
72
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
73
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
74
+ /* All these FPGA images have the same OSCCLK configuration */
75
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
76
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
77
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
78
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
79
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
80
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
81
object_initialize_child(OBJECT(mms), "fpgaio",
82
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/misc/mps2-scc.c
85
+++ b/hw/misc/mps2-scc.c
86
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
87
{
88
trace_mps2_scc_cfg_write(function, device, value);
89
90
- if (function != 1 || device >= NUM_OSCCLK) {
91
+ if (function != 1 || device >= s->num_oscclk) {
92
qemu_log_mask(LOG_GUEST_ERROR,
93
"MPS2 SCC config write: bad function %d device %d\n",
94
function, device);
95
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
96
static bool scc_cfg_read(MPS2SCC *s, unsigned function,
97
unsigned device, uint32_t *value)
98
{
99
- if (function != 1 || device >= NUM_OSCCLK) {
100
+ if (function != 1 || device >= s->num_oscclk) {
101
qemu_log_mask(LOG_GUEST_ERROR,
102
"MPS2 SCC config read: bad function %d device %d\n",
103
function, device);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
105
s->cfgctrl = 0x100000;
106
s->cfgstat = 0;
107
s->dll = 0xffff0001;
108
- for (i = 0; i < NUM_OSCCLK; i++) {
109
+ for (i = 0; i < s->num_oscclk; i++) {
110
s->oscclk[i] = s->oscclk_reset[i];
111
}
112
for (i = 0; i < ARRAY_SIZE(s->led); i++) {
113
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
114
LED_COLOR_GREEN, name);
115
g_free(name);
116
}
117
+
118
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
119
}
120
121
static const VMStateDescription mps2_scc_vmstate = {
122
.name = "mps2-scc",
123
- .version_id = 1,
124
- .minimum_version_id = 1,
125
+ .version_id = 2,
126
+ .minimum_version_id = 2,
44
.fields = (VMStateField[]) {
127
.fields = (VMStateField[]) {
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
128
VMSTATE_UINT32(cfg0, MPS2SCC),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
129
VMSTATE_UINT32(cfg1, MPS2SCC),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
48
+ BCM2835_SYSTIMER_COUNT),
131
VMSTATE_UINT32(cfgctrl, MPS2SCC),
132
VMSTATE_UINT32(cfgstat, MPS2SCC),
133
VMSTATE_UINT32(dll, MPS2SCC),
134
- VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
135
+ VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
136
+ 0, vmstate_info_uint32, uint32_t),
49
VMSTATE_END_OF_LIST()
137
VMSTATE_END_OF_LIST()
50
}
138
}
51
};
139
};
140
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
141
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
142
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
143
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
144
- /* These are the initial settings for the source clocks on the board.
145
+ /*
146
+ * These are the initial settings for the source clocks on the board.
147
* In hardware they can be configured via a config file read by the
148
* motherboard configuration controller to suit the FPGA image.
149
- * These default values are used by most of the standard FPGA images.
150
*/
151
- DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
152
- DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
153
- DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
154
+ DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset,
155
+ qdev_prop_uint32, uint32_t),
156
DEFINE_PROP_END_OF_LIST(),
157
};
158
52
--
159
--
53
2.20.1
160
2.20.1
54
161
55
162
diff view generated by jsdifflib
New patch
1
We were previously using the default OSCCLK settings, which are
2
correct for the older MPS2 boards (mps2-an385, mps2-an386,
3
mps2-an500, mps2-an511), but wrong for the mps2-an505 and mps2-511
4
implemented in mps2-tz.c. Now we're setting the values explicitly we
5
can fix them to be correct.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-4-peter.maydell@linaro.org
11
---
12
hw/arm/mps2-tz.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
20
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
21
/* This will need to be per-FPGA image eventually */
22
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
23
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
24
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
25
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
26
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
27
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
28
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
29
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN505 and AN511 happen to share the same OSCCLK values, but the
2
AN524 will have a different set (and more of them), so split the
3
settings out to be per-board.
2
4
3
This is generic support, with the code disabled for all targets.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-5-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
11
1 file changed, 18 insertions(+), 5 deletions(-)
4
12
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/qemu.h | 4 ++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 161 insertions(+)
13
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
15
--- a/hw/arm/mps2-tz.c
17
+++ b/linux-user/qemu.h
16
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
19
abi_ulong interpreter_loadmap_addr;
18
MPS2TZFPGAType fpga_type;
20
abi_ulong interpreter_pt_dynamic_addr;
19
uint32_t scc_id;
21
struct image_info *other_info;
20
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
22
+
21
+ uint32_t len_oscclk;
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
22
+ const uint32_t *oscclk;
24
+ uint32_t note_flags;
23
const char *armsse_type;
25
+
24
};
26
#ifdef TARGET_MIPS
25
27
int fp_abi;
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
28
int interp_fp_abi;
27
/* Slow 32Khz S32KCLK frequency in Hz */
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
#define S32KCLK_FRQ (32 * 1000)
30
index XXXXXXX..XXXXXXX 100644
29
31
--- a/linux-user/elfload.c
30
+static const uint32_t an505_oscclk[] = {
32
+++ b/linux-user/elfload.c
31
+ 40000000,
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
32
+ 24580000,
34
33
+ 25000000,
35
#include "elf.h"
36
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
41
+{
42
+ g_assert_not_reached();
43
+}
44
+#define ARCH_USE_GNU_PROPERTY 0
45
+
46
struct exec
47
{
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
51
}
52
53
+enum {
54
+ /* The string "GNU\0" as a magic number. */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
56
+ NOTE_DATA_SZ = 1 * KiB,
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
34
+};
60
+
35
+
61
+/*
36
/* Create an alias of an entire original MemoryRegion @orig
62
+ * Process a single gnu_property entry.
37
* located at @base in the memory map.
63
+ * Return false for error.
38
*/
64
+ */
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
40
MPS2SCC *scc = opaque;
66
+ struct image_info *info, bool have_prev_type,
41
DeviceState *sccdev;
67
+ uint32_t *prev_type, Error **errp)
42
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
68
+{
43
+ uint32_t i;
69
+ uint32_t pr_type, pr_datasz, step;
44
70
+
45
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
46
sccdev = DEVICE(scc);
72
+ goto error_data;
47
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
48
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
49
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
50
- /* This will need to be per-FPGA image eventually */
51
- qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
52
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
53
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
54
- qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
55
+ qdev_prop_set_uint32(sccdev, "len-oscclk", mmc->len_oscclk);
56
+ for (i = 0; i < mmc->len_oscclk; i++) {
57
+ g_autofree char *propname = g_strdup_printf("oscclk[%u]", i);
58
+ qdev_prop_set_uint32(sccdev, propname, mmc->oscclk[i]);
73
+ }
59
+ }
74
+ datasz -= *off;
60
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
75
+ data += *off / sizeof(uint32_t);
61
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
76
+
62
}
77
+ if (datasz < 2 * sizeof(uint32_t)) {
63
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
78
+ goto error_data;
64
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
79
+ }
65
mmc->scc_id = 0x41045050;
80
+ pr_type = data[0];
66
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
81
+ pr_datasz = data[1];
67
+ mmc->oscclk = an505_oscclk;
82
+ data += 2;
68
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
83
+ datasz -= 2 * sizeof(uint32_t);
69
mmc->armsse_type = TYPE_IOTKIT;
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
70
}
85
+ if (step > datasz) {
71
86
+ goto error_data;
72
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
87
+ }
73
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
88
+
74
mmc->scc_id = 0x41045210;
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
75
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
90
+ if (have_prev_type && pr_type <= *prev_type) {
76
+ mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
91
+ if (pr_type == *prev_type) {
77
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
78
mmc->armsse_type = TYPE_SSE200;
93
+ } else {
79
}
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
152
+ }
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
203
*pinterp_name = g_steal_pointer(&interp_name);
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
206
+ goto exit_errmsg;
207
+ }
208
}
209
}
210
80
211
--
81
--
212
2.20.1
82
2.20.1
213
83
214
84
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
The MPS2 board has 2 LEDs, but the MPS3 board has 10 LEDs. The
2
FPGAIO device is similar on both sets of boards, but the LED0
3
register has correspondingly more bits that have an effect. Add a
4
device property for number of LEDs.
2
5
3
This peripheral has 1 free-running timer and 4 compare registers.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-6-peter.maydell@linaro.org
10
---
11
include/hw/misc/mps2-fpgaio.h | 5 ++++-
12
hw/misc/mps2-fpgaio.c | 31 +++++++++++++++++++++++--------
13
2 files changed, 27 insertions(+), 9 deletions(-)
4
14
5
Only the free-running timer is implemented. Add support the
15
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
6
COMPARE registers (each register is wired to an IRQ).
7
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
31
hw/timer/trace-events | 6 ++--
32
3 files changed, 44 insertions(+), 21 deletions(-)
33
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
35
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
17
--- a/include/hw/misc/mps2-fpgaio.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
18
+++ b/include/hw/misc/mps2-fpgaio.h
38
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
39
20
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
40
#include "hw/sysbus.h"
21
OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
41
#include "hw/irq.h"
22
42
+#include "qemu/timer.h"
23
+#define MPS2FPGAIO_MAX_LEDS 32
43
#include "qom/object.h"
44
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
47
48
#define BCM2835_SYSTIMER_COUNT 4
49
50
+typedef struct {
51
+ unsigned id;
52
+ QEMUTimer timer;
53
+ qemu_irq irq;
54
+ BCM2835SystemTimerState *state;
55
+} BCM2835SystemTimerCompare;
56
+
24
+
57
struct BCM2835SystemTimerState {
25
struct MPS2FPGAIO {
58
/*< private >*/
26
/*< private >*/
59
SysBusDevice parent_obj;
27
SysBusDevice parent_obj;
60
28
61
/*< public >*/
29
/*< public >*/
62
MemoryRegion iomem;
30
MemoryRegion iomem;
63
- qemu_irq irq;
31
- LEDState *led[2];
64
-
32
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
65
struct {
33
+ uint32_t num_leds;
66
uint32_t ctrl_status;
34
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
35
uint32_t led0;
68
} reg;
36
uint32_t prescale;
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
37
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
70
};
71
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
74
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
39
--- a/hw/misc/mps2-fpgaio.c
76
+++ b/hw/timer/bcm2835_systmr.c
40
+++ b/hw/misc/mps2-fpgaio.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
41
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
78
REG32(COMPARE2, 0x14)
42
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
100
}
101
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
43
switch (offset) {
118
case A_CTRL_STATUS:
44
case A_LED0:
119
s->reg.ctrl_status &= ~value; /* Ack */
45
- s->led0 = value & 0x3;
120
- bcm2835_systmr_update_irq(s);
46
- led_set_state(s->led[0], value & 0x01);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
47
- led_set_state(s->led[1], value & 0x02);
122
+ if (extract32(value, index, 1)) {
48
+ if (s->num_leds != 0) {
123
+ trace_bcm2835_systmr_irq_ack(index);
49
+ uint32_t i;
124
+ qemu_set_irq(s->tmr[index].irq, 0);
50
+
51
+ s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds);
52
+ for (i = 0; i < s->num_leds; i++) {
53
+ led_set_state(s->led[i], value & (1 << i));
125
+ }
54
+ }
126
+ }
55
+ }
127
break;
56
break;
128
case A_COMPARE0 ... A_COMPARE3:
57
case A_PRESCALE:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
58
resync_counter(s);
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
59
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
131
+ index = (offset - A_COMPARE0) >> 2;
60
s->pscntr = 0;
132
+ s->reg.compare[index] = value;
61
s->pscntr_sync_ticks = now;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
62
134
+ /* Compare lower 32-bits of the free-running counter. */
63
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
135
+ triggers_delay_us = value - now;
64
+ for (size_t i = 0; i < s->num_leds; i++) {
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
65
device_cold_reset(DEVICE(s->led[i]));
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
66
}
138
break;
67
}
139
case A_COUNTER_LOW:
68
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
140
case A_COUNTER_HIGH:
69
static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
70
{
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
71
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
143
s, "bcm2835-sys-timer", 0x20);
72
+ uint32_t i;
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
73
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
74
- s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
75
- LED_COLOR_GREEN, "USERLED0");
76
- s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
77
- LED_COLOR_GREEN, "USERLED1");
78
+ if (s->num_leds > MPS2FPGAIO_MAX_LEDS) {
79
+ error_setg(errp, "num-leds cannot be greater than %d",
80
+ MPS2FPGAIO_MAX_LEDS);
81
+ return;
82
+ }
146
+
83
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
84
+ for (i = 0; i < s->num_leds; i++) {
148
+ s->tmr[i].id = i;
85
+ g_autofree char *ledname = g_strdup_printf("USERLED%d", i);
149
+ s->tmr[i].state = s;
86
+ s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
87
+ LED_COLOR_GREEN, ledname);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
153
+ }
88
+ }
154
}
89
}
155
90
156
static const VMStateDescription bcm2835_systmr_vmstate = {
91
static bool mps2_fpgaio_counters_needed(void *opaque)
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
158
index XXXXXXX..XXXXXXX 100644
93
static Property mps2_fpgaio_properties[] = {
159
--- a/hw/timer/trace-events
94
/* Frequency of the prescale counter */
160
+++ b/hw/timer/trace-events
95
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
96
+ /* Number of LEDs controlled by LED0 register */
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
97
+ DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
163
98
DEFINE_PROP_END_OF_LIST(),
164
# bcm2835_systmr.c
99
};
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
100
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
101
--
176
2.20.1
102
2.20.1
177
103
178
104
diff view generated by jsdifflib
1
From: Peng Liang <liangpeng10@huawei.com>
1
MPS3 boards have an extra SWITCH register in the FPGAIO block which
2
reports the value of some switches. Implement this, governed by a
3
property the board code can use to specify whether whether it exists.
2
4
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-7-peter.maydell@linaro.org
9
---
10
include/hw/misc/mps2-fpgaio.h | 1 +
11
hw/misc/mps2-fpgaio.c | 10 ++++++++++
12
2 files changed, 11 insertions(+)
5
13
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
14
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/i2c/microbit_i2c.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
16
--- a/include/hw/misc/mps2-fpgaio.h
19
+++ b/hw/i2c/microbit_i2c.c
17
+++ b/include/hw/misc/mps2-fpgaio.h
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
18
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
21
.fields = (VMStateField[]) {
19
MemoryRegion iomem;
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
20
LEDState *led[MPS2FPGAIO_MAX_LEDS];
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
21
uint32_t num_leds;
24
+ VMSTATE_END_OF_LIST()
22
+ bool has_switches;
25
},
23
24
uint32_t led0;
25
uint32_t prescale;
26
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/mps2-fpgaio.c
29
+++ b/hw/misc/mps2-fpgaio.c
30
@@ -XXX,XX +XXX,XX @@ REG32(CLK100HZ, 0x14)
31
REG32(COUNTER, 0x18)
32
REG32(PRESCALE, 0x1c)
33
REG32(PSCNTR, 0x20)
34
+REG32(SWITCH, 0x28)
35
REG32(MISC, 0x4c)
36
37
static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
38
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
39
resync_counter(s);
40
r = s->pscntr;
41
break;
42
+ case A_SWITCH:
43
+ if (!s->has_switches) {
44
+ goto bad_offset;
45
+ }
46
+ /* User-togglable board switches. We don't model that, so report 0. */
47
+ r = 0;
48
+ break;
49
default:
50
+ bad_offset:
51
qemu_log_mask(LOG_GUEST_ERROR,
52
"MPS2 FPGAIO read: bad offset %x\n", (int) offset);
53
r = 0;
54
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
55
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
56
/* Number of LEDs controlled by LED0 register */
57
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
58
+ DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
59
DEFINE_PROP_END_OF_LIST(),
26
};
60
};
27
61
28
--
62
--
29
2.20.1
63
2.20.1
30
64
31
65
diff view generated by jsdifflib
1
From v8.1M, disabled-coprocessor handling changes slightly:
1
Set the FPGAIO num-leds and have-switches properties explicitly
2
* coprocessors 8, 9, 14 and 15 are also governed by the
2
per-board, rather than relying on the defaults. The AN505 and AN521
3
cp10 enable bit, like cp11
3
both have the same settings as the default values, but the AN524 will
4
* an extra range of instruction patterns is considered
4
be different.
5
to be inside the coprocessor space
6
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
16
5
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
9
Message-id: 20210215115138.20465-8-peter.maydell@linaro.org
20
---
10
---
21
target/arm/cpu.h | 1 +
11
hw/arm/mps2-tz.c | 9 +++++++++
22
target/arm/m-nocp.decode | 10 ++++++----
12
1 file changed, 9 insertions(+)
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
24
3 files changed, 22 insertions(+), 6 deletions(-)
25
13
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
16
--- a/hw/arm/mps2-tz.c
29
+++ b/target/arm/cpu.h
17
+++ b/hw/arm/mps2-tz.c
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
18
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
19
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
20
uint32_t len_oscclk;
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
21
const uint32_t *oscclk;
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
22
+ uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
23
+ bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
24
const char *armsse_type;
35
};
25
};
36
26
37
static inline int arm_feature(CPUARMState *env, int feature)
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
28
const char *name, hwaddr size)
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
41
+++ b/target/arm/m-nocp.decode
42
@@ -XXX,XX +XXX,XX @@
43
# If the coprocessor is not present or disabled then we will generate
44
# the NOCP exception; otherwise we let the insn through to the main decode.
45
46
+&nocp cp
47
+
48
{
29
{
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
30
MPS2FPGAIO *fpgaio = opaque;
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
31
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
51
# TODO: VSCCLRM (new in v8.1M) is similar:
32
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
33
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
53
34
+ qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
35
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
36
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
37
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
60
+ # From v8.1M onwards this range will also NOCP:
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
62
}
38
}
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
39
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
64
index XXXXXXX..XXXXXXX 100644
40
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
65
--- a/target/arm/translate-vfp.c.inc
41
mmc->oscclk = an505_oscclk;
66
+++ b/target/arm/translate-vfp.c.inc
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
43
+ mmc->fpgaio_num_leds = 2;
68
return true;
44
+ mmc->fpgaio_has_switches = false;
45
mmc->armsse_type = TYPE_IOTKIT;
69
}
46
}
70
47
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
48
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
49
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
73
{
50
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
74
/*
51
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
75
* Handle M-profile early check for disabled coprocessor:
52
+ mmc->fpgaio_num_leds = 2;
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
53
+ mmc->fpgaio_has_switches = false;
77
if (a->cp == 11) {
54
mmc->armsse_type = TYPE_SSE200;
78
a->cp = 10;
79
}
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
84
+ a->cp = 10;
85
+ }
86
87
if (a->cp != 10) {
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
90
return false;
91
}
55
}
92
56
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
94
+{
95
+ /* This range needs a coprocessor check for v8.1M and later only */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
97
+ return false;
98
+ }
99
+ return trans_NOCP(s, a);
100
+}
101
+
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
103
{
104
TCGv_i32 rd, rm;
105
--
57
--
106
2.20.1
58
2.20.1
107
59
108
60
diff view generated by jsdifflib
New patch
1
In the mps2-tz board code, we handle devices whose interrupt lines
2
must be wired to all CPUs by creating IRQ splitter devices for the
3
AN521, because it has 2 CPUs, but wiring the device IRQ directly to
4
the SSE/IoTKit input for the AN505, which has only 1 CPU.
1
5
6
We can avoid making an explicit check on the board type constant by
7
instead creating and using the IRQ splitters for any board with more
8
than 1 CPU. This avoids having to add extra cases to the
9
conditionals every time we add new boards.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210215115138.20465-9-peter.maydell@linaro.org
15
---
16
hw/arm/mps2-tz.c | 19 +++++++++----------
17
1 file changed, 9 insertions(+), 10 deletions(-)
18
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/mps2-tz.c
22
+++ b/hw/arm/mps2-tz.c
23
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
24
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
25
{
26
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
27
- MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
28
+ MachineClass *mc = MACHINE_GET_CLASS(mms);
29
30
assert(irqno < MPS2TZ_NUMIRQ);
31
32
- switch (mmc->fpga_type) {
33
- case FPGA_AN505:
34
- return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
35
- case FPGA_AN521:
36
+ if (mc->max_cpus > 1) {
37
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
38
- default:
39
- g_assert_not_reached();
40
+ } else {
41
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
42
}
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
46
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
47
48
/*
49
- * The AN521 needs us to create splitters to feed the IRQ inputs
50
- * for each CPU in the SSE-200 from each device in the board.
51
+ * If this board has more than one CPU, then we need to create splitters
52
+ * to feed the IRQ inputs for each CPU in the SSE from each device in the
53
+ * board. If there is only one CPU, we can just wire the device IRQ
54
+ * directly to the SSE's IRQ input.
55
*/
56
- if (mmc->fpga_type == FPGA_AN521) {
57
+ if (mc->max_cpus > 1) {
58
for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
59
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
60
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
1
For nested groups like:
1
The AN524 has more interrupt lines than the AN505 and AN521; make
2
numirq board-specific rather than a compile-time constant.
2
3
3
{
4
Since the difference is small (92 on the current boards and 95 on the
4
[
5
new one) we don't dynamically allocate the cpu_irq_splitter[] array
5
pattern 1
6
but leave it as a fixed length array whose size is the maximum needed
6
pattern 2
7
for any of the boards.
7
]
8
pattern 3
9
}
10
8
11
the intended behaviour is that patterns 1 and 2 must not
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
overlap with each other; if the insn matches neither then
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
we fall through to pattern 3 as the next thing in the
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
outer overlapping group.
12
Message-id: 20210215115138.20465-10-peter.maydell@linaro.org
13
---
14
hw/arm/mps2-tz.c | 15 ++++++++++-----
15
1 file changed, 10 insertions(+), 5 deletions(-)
15
16
16
Currently we generate incorrect code for this situation,
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
30
scripts/decodetree.py | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
19
--- a/hw/arm/mps2-tz.c
36
+++ b/scripts/decodetree.py
20
+++ b/hw/arm/mps2-tz.c
37
@@ -XXX,XX +XXX,XX @@ class Tree:
21
@@ -XXX,XX +XXX,XX @@
38
output(ind, ' /* ',
22
#include "hw/qdev-clock.h"
39
str_match_bits(innerbits, innermask), ' */\n')
23
#include "qom/object.h"
40
s.output_code(i + 4, extracted, innerbits, innermask)
24
41
- output(ind, ' return false;\n')
25
-#define MPS2TZ_NUMIRQ 92
42
+ output(ind, ' break;\n')
26
+#define MPS2TZ_NUMIRQ_MAX 92
43
output(ind, '}\n')
27
44
# end Tree
28
typedef enum MPS2TZFPGAType {
29
FPGA_AN505,
30
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
31
const uint32_t *oscclk;
32
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
33
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
34
+ int numirq; /* Number of external interrupts */
35
const char *armsse_type;
36
};
37
38
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
39
SplitIRQ sec_resp_splitter;
40
qemu_or_irq uart_irq_orgate;
41
DeviceState *lan9118;
42
- SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
43
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
44
Clock *sysclk;
45
Clock *s32kclk;
46
};
47
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
48
{
49
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
50
MachineClass *mc = MACHINE_GET_CLASS(mms);
51
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
52
53
- assert(irqno < MPS2TZ_NUMIRQ);
54
+ assert(irqno < mmc->numirq);
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
iotkitdev = DEVICE(&mms->iotkit);
60
object_property_set_link(OBJECT(&mms->iotkit), "memory",
61
OBJECT(system_memory), &error_abort);
62
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
63
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
64
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
65
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
* board. If there is only one CPU, we can just wire the device IRQ
69
* directly to the SSE's IRQ input.
70
*/
71
+ assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
72
if (mc->max_cpus > 1) {
73
- for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
74
+ for (i = 0; i < mmc->numirq; i++) {
75
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
76
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
77
78
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
mmc->fpgaio_num_leds = 2;
81
mmc->fpgaio_has_switches = false;
82
+ mmc->numirq = 92;
83
mmc->armsse_type = TYPE_IOTKIT;
84
}
85
86
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
87
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
88
mmc->fpgaio_num_leds = 2;
89
mmc->fpgaio_has_switches = false;
90
+ mmc->numirq = 92;
91
mmc->armsse_type = TYPE_SSE200;
92
}
45
93
46
--
94
--
47
2.20.1
95
2.20.1
48
96
49
97
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
The AN524 version of the SCC interface has different behaviour for
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
2
some of the CFG registers; implement it.
3
(currently always true for us) then this field always reads as 4 and
4
ignores writes.
5
3
6
These bits used to be the vector-length field for the old
4
Each board in this family can have minor differences in the meaning
7
short-vector extension, so we need to take care that they are not
5
of the CFG registers, so rather than trying to specify all the
8
misinterpreted as setting vec_len. We do this with a rearrangement
6
possible semantics via individual device properties, we make the
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
7
behaviour conditional on the part-number field of the SCC_ID register
10
and also the QC bit; this obviates the need for the M-profile
8
which the board code already passes us.
11
only masking step that we used to have at the start of the function.
12
9
13
We provide a new field in CPUState for LTPSIZE, even though this
10
For the AN524, the differences are:
14
will always be 4, in preparation for MVE, so we don't have to
11
* CFG3 is reserved rather than being board switches
15
come back later and split it out of the vfp.xregs[FPSCR] value.
12
* CFG5 is a new register ("ACLK Frequency in Hz")
16
(This state struct field will be saved and restored as part of
13
* CFG6 is a new register ("Clock divider for BRAM")
17
the FPSCR value via the vmstate_fpscr in machine.c.)
14
15
We implement both of the new registers as reads-as-written.
18
16
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
19
Message-id: 20210215115138.20465-11-peter.maydell@linaro.org
22
---
20
---
23
target/arm/cpu.h | 1 +
21
include/hw/misc/mps2-scc.h | 3 ++
24
target/arm/cpu.c | 9 +++++++++
22
hw/misc/mps2-scc.c | 71 ++++++++++++++++++++++++++++++++++++--
25
target/arm/vfp_helper.c | 6 ++++++
23
2 files changed, 72 insertions(+), 2 deletions(-)
26
3 files changed, 16 insertions(+)
27
24
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
29
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
27
--- a/include/hw/misc/mps2-scc.h
31
+++ b/target/arm/cpu.h
28
+++ b/include/hw/misc/mps2-scc.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
29
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
33
uint32_t fpdscr[M_REG_NUM_BANKS];
30
34
uint32_t cpacr[M_REG_NUM_BANKS];
31
uint32_t cfg0;
35
uint32_t nsacr;
32
uint32_t cfg1;
36
+ int ltpsize;
33
+ uint32_t cfg2;
37
} v7m;
34
uint32_t cfg4;
38
35
+ uint32_t cfg5;
39
/* Information associated with an exception about to be taken:
36
+ uint32_t cfg6;
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
37
uint32_t cfgdata_rtn;
38
uint32_t cfgdata_out;
39
uint32_t cfgctrl;
40
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
41
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
42
--- a/hw/misc/mps2-scc.c
43
+++ b/target/arm/cpu.c
43
+++ b/hw/misc/mps2-scc.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
44
@@ -XXX,XX +XXX,XX @@
45
uint8_t *rom;
45
46
uint32_t vecbase;
46
REG32(CFG0, 0)
47
47
REG32(CFG1, 4)
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
48
+REG32(CFG2, 8)
49
+ /*
49
REG32(CFG3, 0xc)
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
50
REG32(CFG4, 0x10)
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
51
+REG32(CFG5, 0x14)
52
+ * always reset to 4.
52
+REG32(CFG6, 0x18)
53
+ */
53
REG32(CFGDATA_RTN, 0xa0)
54
+ env->v7m.ltpsize = 4;
54
REG32(CFGDATA_OUT, 0xa4)
55
REG32(CFGCTRL, 0xa8)
56
@@ -XXX,XX +XXX,XX @@ REG32(DLL, 0x100)
57
REG32(AID, 0xFF8)
58
REG32(ID, 0xFFC)
59
60
+static int scc_partno(MPS2SCC *s)
61
+{
62
+ /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */
63
+ return extract32(s->id, 4, 8);
64
+}
65
+
66
/* Handle a write via the SYS_CFG channel to the specified function/device.
67
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
68
*/
69
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
70
case A_CFG1:
71
r = s->cfg1;
72
break;
73
+ case A_CFG2:
74
+ if (scc_partno(s) != 0x524) {
75
+ /* CFG2 reserved on other boards */
76
+ goto bad_offset;
55
+ }
77
+ }
56
+
78
+ r = s->cfg2;
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
79
+ break;
58
env->v7m.secure = true;
80
case A_CFG3:
59
} else {
81
+ if (scc_partno(s) == 0x524) {
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
82
+ /* CFG3 reserved on AN524 */
61
index XXXXXXX..XXXXXXX 100644
83
+ goto bad_offset;
62
--- a/target/arm/vfp_helper.c
84
+ }
63
+++ b/target/arm/vfp_helper.c
85
/* These are user-settable DIP switches on the board. We don't
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
86
* model that, so just return zeroes.
65
| (env->vfp.vec_len << 16)
87
*/
66
| (env->vfp.vec_stride << 20);
88
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
67
89
case A_CFG4:
68
+ /*
90
r = s->cfg4;
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
91
break;
70
+ * two is not applicable to this CPU will always be zero.
92
+ case A_CFG5:
71
+ */
93
+ if (scc_partno(s) != 0x524) {
72
+ fpscr |= env->v7m.ltpsize << 16;
94
+ /* CFG5 reserved on other boards */
73
+
95
+ goto bad_offset;
74
fpscr |= vfp_get_fpscr_from_host(env);
96
+ }
75
97
+ r = s->cfg5;
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
98
+ break;
99
+ case A_CFG6:
100
+ if (scc_partno(s) != 0x524) {
101
+ /* CFG6 reserved on other boards */
102
+ goto bad_offset;
103
+ }
104
+ r = s->cfg6;
105
+ break;
106
case A_CFGDATA_RTN:
107
r = s->cfgdata_rtn;
108
break;
109
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
110
r = s->id;
111
break;
112
default:
113
+ bad_offset:
114
qemu_log_mask(LOG_GUEST_ERROR,
115
"MPS2 SCC read: bad offset %x\n", (int) offset);
116
r = 0;
117
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
118
led_set_state(s->led[i], extract32(value, i, 1));
119
}
120
break;
121
+ case A_CFG2:
122
+ if (scc_partno(s) != 0x524) {
123
+ /* CFG2 reserved on other boards */
124
+ goto bad_offset;
125
+ }
126
+ /* AN524: QSPI Select signal */
127
+ s->cfg2 = value;
128
+ break;
129
+ case A_CFG5:
130
+ if (scc_partno(s) != 0x524) {
131
+ /* CFG5 reserved on other boards */
132
+ goto bad_offset;
133
+ }
134
+ /* AN524: ACLK frequency in Hz */
135
+ s->cfg5 = value;
136
+ break;
137
+ case A_CFG6:
138
+ if (scc_partno(s) != 0x524) {
139
+ /* CFG6 reserved on other boards */
140
+ goto bad_offset;
141
+ }
142
+ /* AN524: Clock divider for BRAM */
143
+ s->cfg6 = value;
144
+ break;
145
case A_CFGDATA_OUT:
146
s->cfgdata_out = value;
147
break;
148
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
149
s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
150
break;
151
default:
152
+ bad_offset:
153
qemu_log_mask(LOG_GUEST_ERROR,
154
"MPS2 SCC write: bad offset 0x%x\n", (int) offset);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
157
trace_mps2_scc_reset();
158
s->cfg0 = 0;
159
s->cfg1 = 0;
160
+ s->cfg2 = 0;
161
+ s->cfg5 = 0;
162
+ s->cfg6 = 0;
163
s->cfgdata_rtn = 0;
164
s->cfgdata_out = 0;
165
s->cfgctrl = 0x100000;
166
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
167
168
static const VMStateDescription mps2_scc_vmstate = {
169
.name = "mps2-scc",
170
- .version_id = 2,
171
- .minimum_version_id = 2,
172
+ .version_id = 3,
173
+ .minimum_version_id = 3,
174
.fields = (VMStateField[]) {
175
VMSTATE_UINT32(cfg0, MPS2SCC),
176
VMSTATE_UINT32(cfg1, MPS2SCC),
177
+ VMSTATE_UINT32(cfg2, MPS2SCC),
178
+ /* cfg3, cfg4 are read-only so need not be migrated */
179
+ VMSTATE_UINT32(cfg5, MPS2SCC),
180
+ VMSTATE_UINT32(cfg6, MPS2SCC),
181
VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
182
VMSTATE_UINT32(cfgdata_out, MPS2SCC),
183
VMSTATE_UINT32(cfgctrl, MPS2SCC),
77
--
184
--
78
2.20.1
185
2.20.1
79
186
80
187
diff view generated by jsdifflib
1
M-profile CPUs with half-precision floating point support should
1
On the MPS2 boards, the first 32 interrupt lines are entirely
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
2
internal to the SSE; interrupt lines for devices outside the SSE
3
of the value at the top of vfp_set_fpscr() currently prevents that.
3
start at 32. In the application notes that document each FPGA image,
4
This is not yet an active bug because we have no M-profile
4
the interrupt wiring is documented from the point of view of the CPU,
5
FP16 CPUs, but needs to be fixed before we can add any.
5
so '0' is the first of the SSE's interrupts and the devices in the
6
FPGA image itself are '32' and up: so the UART 0 Receive interrupt is
7
32, the SPI #0 interrupt is 51, and so on.
6
8
7
The bits that the masking is effectively preventing from being
9
Within our implementation, because the external interrupts must be
8
set are the A-profile only short-vector Len and Stride fields,
10
connected to the EXP_IRQ[0...n] lines of the SSE object, we made the
9
plus the Neon QC bit. Rearrange the order of the function so
11
get_sse_irq_in() function take an irqno whose values start at 0 for
10
that those fields are handled earlier and only under a suitable
12
the first FPGA device interrupt. In this numbering scheme the UART 0
11
guard; this allows us to drop the M-profile specific masking,
13
Receive interrupt is 0, the SPI #0 interrupt is 19, and so on.
12
making FZ16 writeable.
13
14
14
This change also makes the QC bit correctly RAZ/WI for older
15
The result of these two different numbering schemes has been that
15
no-Neon A-profile cores.
16
half of the devices were wired up to the wrong IRQs: the UART IRQs
17
are wired up correctly, but the DMA and SPI devices were passing
18
start-at-32 values to get_sse_irq_in() and so being mis-connected.
16
19
17
This refactoring also paves the way for the low-overhead-branch
20
Fix the bug by making get_sse_irq_in() take values specified with the
18
LTPSIZE field, which uses some of the bits that are used for
21
same scheme that the hardware manuals use, to avoid confusion.
19
A-profile Stride and Len.
20
22
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
25
Message-id: 20210215115138.20465-12-peter.maydell@linaro.org
24
---
26
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
27
hw/arm/mps2-tz.c | 24 +++++++++++++++++-------
26
1 file changed, 28 insertions(+), 19 deletions(-)
28
1 file changed, 17 insertions(+), 7 deletions(-)
27
29
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
30
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
29
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
32
--- a/hw/arm/mps2-tz.c
31
+++ b/target/arm/vfp_helper.c
33
+++ b/hw/arm/mps2-tz.c
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
34
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
33
val &= ~FPCR_FZ16;
35
34
}
36
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
35
37
{
36
- if (arm_feature(env, ARM_FEATURE_M)) {
38
- /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
37
+ vfp_set_fpscr_to_host(env, val);
39
+ /*
40
+ * Return a qemu_irq which will signal IRQ n to all CPUs in the
41
+ * SSE. The irqno should be as the CPU sees it, so the first
42
+ * external-to-the-SSE interrupt is 32.
43
+ */
44
MachineClass *mc = MACHINE_GET_CLASS(mms);
45
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
46
47
- assert(irqno < mmc->numirq);
48
+ assert(irqno >= 32 && irqno < (mmc->numirq + 32));
38
+
49
+
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
50
+ /*
40
/*
51
+ * Convert from "CPU irq number" (as listed in the FPGA image
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
52
+ * documentation) to the SSE external-interrupt number.
42
- * and also for the trapped-exception-handling bits IxE.
53
+ */
43
+ * Short-vector length and stride; on M-profile these bits
54
+ irqno -= 32;
44
+ * are used for different purposes.
55
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
56
if (mc->max_cpus > 1) {
46
+ * because in v7A no-short-vector-support cores still had to
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
47
+ * allow Stride/Len to be written with the only effect that
58
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
48
+ * some insns are required to UNDEF if the guest sets them.
59
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
49
+ *
60
CMSDKAPBUART *uart = opaque;
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
61
int i = uart - &mms->uart[0];
51
*/
62
- int rxirqno = i * 2;
52
- val &= 0xf7c0009f;
63
- int txirqno = i * 2 + 1;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
64
- int combirqno = i + 10;
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
65
+ int rxirqno = i * 2 + 32;
55
}
66
+ int txirqno = i * 2 + 33;
56
67
+ int combirqno = i + 42;
57
- vfp_set_fpscr_to_host(env, val);
68
SysBusDevice *s;
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
59
+ /*
70
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
71
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
61
+ * whole being zero/non-zero is what counts.
72
62
+ * TODO: M-profile MVE also has a QC bit.
73
s = SYS_BUS_DEVICE(mms->lan9118);
63
+ */
74
sysbus_realize_and_unref(s, &error_fatal);
64
+ env->vfp.qc[0] = val & FPCR_QC;
75
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
65
+ env->vfp.qc[1] = 0;
76
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
66
+ env->vfp.qc[2] = 0;
77
return sysbus_mmio_get_region(s, 0);
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
94
}
78
}
95
79
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
80
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
81
&error_fatal);
82
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
83
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
84
- get_sse_irq_in(mms, 15));
85
+ get_sse_irq_in(mms, 47));
86
87
/* Most of the devices in the FPGA are behind Peripheral Protection
88
* Controllers. The required order for initializing things is:
97
--
89
--
98
2.20.1
90
2.20.1
99
91
100
92
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
The mps2-tz code uses PPCPortInfo data structures to define what
2
devices are present and how they are wired up. Currently we use
3
these to specify device types and addresses, but hard-code the
4
interrupt line wiring in each make_* helper function. This works for
5
the two boards we have at the moment, but the AN524 has some devices
6
with different interrupt assignments.
2
7
3
The IRQ values are defined few lines earlier, use them instead of
8
This commit adds the framework to allow PPCPortInfo structures to
4
the magic numbers.
9
specify interrupt numbers. We add an array of interrupt numbers to
10
the PPCPortInfo struct, and pass it through to the make_* helpers.
11
The following commit will change the make_* helpers over to using the
12
framework.
5
13
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210215115138.20465-13-peter.maydell@linaro.org
10
---
17
---
11
hw/intc/bcm2836_control.c | 8 ++++----
18
hw/arm/mps2-tz.c | 36 ++++++++++++++++++++++++------------
12
1 file changed, 4 insertions(+), 4 deletions(-)
19
1 file changed, 24 insertions(+), 12 deletions(-)
13
20
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
23
--- a/hw/arm/mps2-tz.c
17
+++ b/hw/intc/bcm2836_control.c
24
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
25
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
26
* needs to be plugged into the downstream end of the PPC port.
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
27
*/
28
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
29
- const char *name, hwaddr size);
30
+ const char *name, hwaddr size,
31
+ const int *irqs);
32
33
typedef struct PPCPortInfo {
34
const char *name;
35
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
36
void *opaque;
37
hwaddr addr;
38
hwaddr size;
39
+ int irqs[3]; /* currently no device needs more IRQ lines than this */
40
} PPCPortInfo;
41
42
typedef struct PPCInfo {
43
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
44
} PPCInfo;
45
46
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
47
- void *opaque,
48
- const char *name, hwaddr size)
49
+ void *opaque,
50
+ const char *name, hwaddr size,
51
+ const int *irqs)
21
{
52
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
53
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
54
* and return a pointer to its MemoryRegion.
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
24
}
56
}
25
57
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
58
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
59
- const char *name, hwaddr size)
60
+ const char *name, hwaddr size,
61
+ const int *irqs)
27
{
62
{
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
63
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
64
CMSDKAPBUART *uart = opaque;
65
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
30
}
66
}
31
67
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
68
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
69
- const char *name, hwaddr size)
70
+ const char *name, hwaddr size,
71
+ const int *irqs)
33
{
72
{
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
73
MPS2SCC *scc = opaque;
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
74
DeviceState *sccdev;
75
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
36
}
76
}
37
77
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
78
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
79
- const char *name, hwaddr size)
80
+ const char *name, hwaddr size,
81
+ const int *irqs)
39
{
82
{
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
83
MPS2FPGAIO *fpgaio = opaque;
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
84
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
85
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
42
}
86
}
43
87
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
88
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
89
- const char *name, hwaddr size)
90
+ const char *name, hwaddr size,
91
+ const int *irqs)
92
{
93
SysBusDevice *s;
94
NICInfo *nd = &nd_table[0];
95
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
96
}
97
98
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
99
- const char *name, hwaddr size)
100
+ const char *name, hwaddr size,
101
+ const int *irqs)
102
{
103
TZMPC *mpc = opaque;
104
int i = mpc - &mms->ssram_mpc[0];
105
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
106
}
107
108
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
109
- const char *name, hwaddr size)
110
+ const char *name, hwaddr size,
111
+ const int *irqs)
112
{
113
PL080State *dma = opaque;
114
int i = dma - &mms->dma[0];
115
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
116
}
117
118
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
119
- const char *name, hwaddr size)
120
+ const char *name, hwaddr size,
121
+ const int *irqs)
122
{
123
/*
124
* The AN505 has five PL022 SPI controllers.
125
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
126
}
127
128
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
129
- const char *name, hwaddr size)
130
+ const char *name, hwaddr size,
131
+ const int *irqs)
132
{
133
ArmSbconI2CState *i2c = opaque;
134
SysBusDevice *s;
135
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
136
continue;
137
}
138
139
- mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
141
+ pinfo->irqs);
142
portname = g_strdup_printf("port[%d]", port);
143
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
144
&error_fatal);
45
--
145
--
46
2.20.1
146
2.20.1
47
147
48
148
diff view generated by jsdifflib
1
For AArch32, unlike the VCVT of integer to float, which honours the
1
Move the specification of the IRQ information for the uart, ethernet,
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
2
dma and spi devices to the data structures. (The other devices
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
3
handled by the PPCPortInfo structures don't have any interrupt lines
4
always honour the FPCR rounding mode.)
4
we need to wire up.)
5
6
Implement this by providing _round_to_nearest versions of the
7
relevant helpers which set the rounding mode temporarily when making
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
5
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
8
Message-id: 20210215115138.20465-14-peter.maydell@linaro.org
18
---
9
---
19
target/arm/helper.h | 13 +++++++++++++
10
hw/arm/mps2-tz.c | 52 +++++++++++++++++++++++-------------------------
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
11
1 file changed, 25 insertions(+), 27 deletions(-)
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
12
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
15
--- a/hw/arm/mps2-tz.c
27
+++ b/target/arm/helper.h
16
+++ b/hw/arm/mps2-tz.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
17
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
18
const char *name, hwaddr size,
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
19
const int *irqs)
31
20
{
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
21
+ /* The irq[] array is tx, rx, combined, in that order */
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
22
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
23
CMSDKAPBUART *uart = opaque;
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
24
int i = uart - &mms->uart[0];
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
25
- int rxirqno = i * 2 + 32;
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
26
- int txirqno = i * 2 + 33;
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
27
- int combirqno = i + 42;
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
28
SysBusDevice *s;
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
29
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
30
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
31
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
32
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
44
+
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
34
s = SYS_BUS_DEVICE(uart);
46
35
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
36
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
37
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
49
index XXXXXXX..XXXXXXX 100644
38
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
50
--- a/target/arm/vfp_helper.c
39
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
51
+++ b/target/arm/vfp_helper.c
40
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
41
- sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
53
return float64_to_float32(x, &env->vfp.fp_status);
42
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
43
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
54
}
44
}
55
45
56
-/* VFP3 fixed point conversion. */
46
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
57
+/*
47
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
48
s = SYS_BUS_DEVICE(mms->lan9118);
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
49
sysbus_realize_and_unref(s, &error_fatal);
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
50
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
62
+ * must round-to-zero.
52
return sysbus_mmio_get_region(s, 0);
63
+ */
53
}
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
54
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
66
void *fpstp) \
56
const char *name, hwaddr size,
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
57
const int *irqs)
68
58
{
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
59
+ /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
60
PL080State *dma = opaque;
71
+ uint32_t shift, \
61
int i = dma - &mms->dma[0];
72
+ void *fpstp) \
62
SysBusDevice *s;
73
+ { \
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
74
+ ftype ret; \
64
75
+ float_status *fpst = fpstp; \
65
s = SYS_BUS_DEVICE(dma);
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
66
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
67
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
68
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
79
+ fpst->float_rounding_mode = oldmode; \
69
- sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
80
+ return ret; \
70
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
81
+ }
71
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
82
+
72
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
73
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
74
g_free(mscname);
85
void *fpst) \
75
return sysbus_mmio_get_region(s, 0);
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
76
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
87
77
* lines are set via the "MISC" register in the MPS2 FPGAIO device.
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
78
*/
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
79
PL022State *spi = opaque;
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
80
- int i = spi - &mms->spi[0];
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
81
SysBusDevice *s;
92
float_round_to_zero, _round_to_zero) \
82
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
83
object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
84
sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
95
index XXXXXXX..XXXXXXX 100644
85
s = SYS_BUS_DEVICE(spi);
96
--- a/target/arm/translate-vfp.c.inc
86
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
97
+++ b/target/arm/translate-vfp.c.inc
87
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
88
return sysbus_mmio_get_region(s, 0);
99
/* Switch on op:U:sx bits */
89
}
100
switch (a->opc) {
90
101
case 0:
91
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
92
}, {
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
93
.name = "apb_ppcexp1",
104
break;
94
.ports = {
105
case 1:
95
- { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
96
- { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
97
- { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
108
break;
98
- { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
109
case 2:
99
- { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
100
- { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
101
- { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
112
break;
102
- { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
113
case 3:
103
- { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
104
- { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
105
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
116
break;
106
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
117
case 4:
107
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
108
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
109
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
120
/* Switch on op:U:sx bits */
110
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
121
switch (a->opc) {
111
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
122
case 0:
112
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
113
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
114
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
125
break;
115
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
126
case 1:
116
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
117
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
118
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
129
break;
119
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
130
case 2:
120
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
121
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
122
- { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
133
break;
123
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
134
case 3:
124
},
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
125
}, {
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
126
.name = "ahb_ppcexp1",
137
break;
127
.ports = {
138
case 4:
128
- { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
129
- { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
130
- { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
141
/* Switch on op:U:sx bits */
131
- { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
142
switch (a->opc) {
132
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
143
case 0:
133
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
134
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
135
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
146
break;
136
},
147
case 1:
137
},
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
138
};
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
161
--
139
--
162
2.20.1
140
2.20.1
163
141
164
142
diff view generated by jsdifflib
1
The SMLAD instruction is supposed to:
1
We create an OR gate to wire together the overflow IRQs for all the
2
* signed multiply Rn[15:0] * Rm[15:0]
2
UARTs on the board; this has to have twice the number of inputs as
3
* signed multiply Rn[31:16] * Rm[31:16]
3
there are UARTs, since each UART feeds it a TX overflow and an RX
4
* perform a signed addition of the products and Ra
4
overflow interrupt line. Replace the hardcoded '10' with a
5
* set Rd to the low 32 bits of the theoretical
5
calculation based on the size of the uart[] array in the
6
infinite-precision result
6
MPS2TZMachineState. (We rely on OR gate inputs that are never wired
7
* set the Q flag if the sign-extension of Rd
7
up or asserted being treated as always-zero.)
8
would differ from the infinite-precision result
9
(ie on overflow)
10
11
Our current implementation doesn't quite do this, though: it performs
12
an addition of the products setting Q on overflow, and then it adds
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
14
the architecturally mandated only-check-for-overflow-once algorithm
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
20
The products are both 0x4000_0000, so when added together as 32-bit
21
signed numbers they overflow (and QEMU sets Q), but because the
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
23
there is no overflow for the complete operation and setting Q is
24
incorrect.
25
26
Fix this edge case by resorting to 64-bit arithmetic for the
27
case where we need to add three values together.
28
8
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
11
Message-id: 20210215115138.20465-15-peter.maydell@linaro.org
32
---
12
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
13
hw/arm/mps2-tz.c | 11 ++++++++---
34
1 file changed, 48 insertions(+), 10 deletions(-)
14
1 file changed, 8 insertions(+), 3 deletions(-)
35
15
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
37
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
18
--- a/hw/arm/mps2-tz.c
39
+++ b/target/arm/translate.c
19
+++ b/hw/arm/mps2-tz.c
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
20
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
41
gen_smul_dual(t1, t2);
21
*/
42
22
memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
43
if (sub) {
23
44
- /* This subtraction cannot overflow. */
24
- /* The overflow IRQs for all UARTs are ORed together.
45
+ /*
25
+ /*
46
+ * This subtraction cannot overflow, so we can do a simple
26
+ * The overflow IRQs for all UARTs are ORed together.
47
+ * 32-bit subtraction and then a possible 32-bit saturating
27
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
48
+ * addition of Ra.
28
- * Create the OR gate for this.
49
+ */
29
+ * Create the OR gate for this: it has one input for the TX overflow
50
tcg_gen_sub_i32(t1, t1, t2);
30
+ * and one for the RX overflow for each UART we might have.
51
+ tcg_temp_free_i32(t2);
31
+ * (If the board has fewer than the maximum possible number of UARTs
52
+
32
+ * those inputs are never wired up and are treated as always-zero.)
53
+ if (a->ra != 15) {
33
*/
54
+ t2 = load_reg(s, a->ra);
34
object_initialize_child(OBJECT(mms), "uart-irq-orgate",
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
35
&mms->uart_irq_orgate, TYPE_OR_IRQ);
56
+ tcg_temp_free_i32(t2);
36
- object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10,
57
+ }
37
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
58
+ } else if (a->ra == 15) {
38
+ 2 * ARRAY_SIZE(mms->uart),
59
+ /* Single saturation-checking addition */
39
&error_fatal);
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
40
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
61
+ tcg_temp_free_i32(t2);
41
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
62
} else {
63
/*
64
- * This addition cannot overflow 32 bits; however it may
65
- * overflow considered as a signed operation, in which case
66
- * we must set the Q flag.
67
+ * We need to add the products and Ra together and then
68
+ * determine whether the final result overflowed. Doing
69
+ * this as two separate add-and-check-overflow steps incorrectly
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
72
*/
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
74
- }
75
- tcg_temp_free_i32(t2);
76
+ TCGv_i64 p64, q64;
77
+ TCGv_i32 t3, qf, one;
78
79
- if (a->ra != 15) {
80
- t2 = load_reg(s, a->ra);
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
82
+ p64 = tcg_temp_new_i64();
83
+ q64 = tcg_temp_new_i64();
84
+ tcg_gen_ext_i32_i64(p64, t1);
85
+ tcg_gen_ext_i32_i64(q64, t2);
86
+ tcg_gen_add_i64(p64, p64, q64);
87
+ load_reg_var(s, t2, a->ra);
88
+ tcg_gen_ext_i32_i64(q64, t2);
89
+ tcg_gen_add_i64(p64, p64, q64);
90
+ tcg_temp_free_i64(q64);
91
+
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
42
--
111
2.20.1
43
2.20.1
112
44
113
45
diff view generated by jsdifflib
1
v8.1M brings four new insns to M-profile:
1
The AN505 and AN521 have the same device layout, but the AN524 is
2
* CSEL : Rd = cond ? Rn : Rm
2
somewhat different. Allow for more than one PPCInfo array, which can
3
* CSINC : Rd = cond ? Rn : Rm+1
3
be selected based on the board type.
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
6
4
7
Implement these.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-16-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 16 ++++++++++++++--
10
1 file changed, 14 insertions(+), 2 deletions(-)
8
11
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
13
target/arm/t32.decode | 3 +++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
16
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
14
--- a/hw/arm/mps2-tz.c
20
+++ b/target/arm/t32.decode
15
+++ b/hw/arm/mps2-tz.c
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
16
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
22
}
17
MemoryRegion *system_memory = get_system_memory();
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
18
DeviceState *iotkitdev;
24
19
DeviceState *dev_splitter;
25
+# v8.1M CSEL and friends
20
+ const PPCInfo *ppcs;
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
21
+ int num_ppcs;
27
+
22
int i;
28
# Data-processing (register-shifted register)
23
29
24
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
26
* + wire up the PPC's control lines to the IoTKit object
32
index XXXXXXX..XXXXXXX 100644
27
*/
33
--- a/target/arm/translate.c
28
34
+++ b/target/arm/translate.c
29
- const PPCInfo ppcs[] = { {
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
30
+ const PPCInfo an505_ppcs[] = { {
36
return true;
31
.name = "apb_ppcexp0",
37
}
32
.ports = {
38
33
{ "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
35
},
41
+{
36
};
42
+ TCGv_i32 rn, rm, zero;
37
43
+ DisasCompare c;
38
- for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
44
+
39
+ switch (mmc->fpga_type) {
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
40
+ case FPGA_AN505:
46
+ return false;
41
+ case FPGA_AN521:
47
+ }
42
+ ppcs = an505_ppcs;
48
+
43
+ num_ppcs = ARRAY_SIZE(an505_ppcs);
49
+ if (a->rm == 13) {
50
+ /* SEE "Related encodings" (MVE shifts) */
51
+ return false;
52
+ }
53
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
56
+ return false;
57
+ }
58
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
60
+ if (a->rn == 15) {
61
+ rn = tcg_const_i32(0);
62
+ } else {
63
+ rn = load_reg(s, a->rn);
64
+ }
65
+ if (a->rm == 15) {
66
+ rm = tcg_const_i32(0);
67
+ } else {
68
+ rm = load_reg(s, a->rm);
69
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
44
+ break;
83
+ default:
45
+ default:
84
+ g_assert_not_reached();
46
+ g_assert_not_reached();
85
+ }
47
+ }
86
+
48
+
87
+ arm_test_cc(&c, a->fcond);
49
+ for (i = 0; i < num_ppcs; i++) {
88
+ zero = tcg_const_i32(0);
50
const PPCInfo *ppcinfo = &ppcs[i];
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
51
TZPPC *ppc = &mms->ppc[i];
90
+ arm_free_cc(&c);
52
DeviceState *ppcdev;
91
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
97
+}
98
+
99
/*
100
* Legacy decoder.
101
*/
102
--
53
--
103
2.20.1
54
2.20.1
104
55
105
56
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN505 and AN521 have the same layout of RAM; the AN524 does not.
2
2
Replace the current hard-coding of where the RAM is and which parts
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
3
of it are behind which MPCs with a data-driven approach.
4
the address are significant in the virtual address. We are
4
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
which means that we do not "clean" the top byte early in TCG.
7
8
This new interface allows us to flush all 256 possible aliases
9
for a given page, currently missed by tlb_flush_page*.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-17-peter.maydell@linaro.org
16
---
8
---
17
include/exec/exec-all.h | 36 ++++++
9
hw/arm/mps2-tz.c | 175 +++++++++++++++++++++++++++++++++++++----------
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
10
1 file changed, 138 insertions(+), 37 deletions(-)
19
2 files changed, 302 insertions(+), 9 deletions(-)
11
20
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
14
--- a/hw/arm/mps2-tz.c
24
+++ b/include/exec/exec-all.h
15
+++ b/hw/arm/mps2-tz.c
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
16
@@ -XXX,XX +XXX,XX @@
26
* depend on when the guests translation ends the TB.
17
#include "qom/object.h"
27
*/
18
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
19
#define MPS2TZ_NUMIRQ_MAX 92
29
+
20
+#define MPS2TZ_RAM_MAX 4
30
+/**
21
31
+ * tlb_flush_page_bits_by_mmuidx
22
typedef enum MPS2TZFPGAType {
32
+ * @cpu: CPU whose TLB should be flushed
23
FPGA_AN505,
33
+ * @addr: virtual address of page to be flushed
24
FPGA_AN521,
34
+ * @idxmap: bitmap of mmu indexes to flush
25
} MPS2TZFPGAType;
35
+ * @bits: number of significant bits in address
26
36
+ *
27
+/*
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
28
+ * Define the layout of RAM in a board, including which parts are
29
+ * behind which MPCs.
30
+ * mrindex specifies the index into mms->ram[] to use for the backing RAM;
31
+ * -1 means "use the system RAM".
38
+ */
32
+ */
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
33
+typedef struct RAMInfo {
40
+ uint16_t idxmap, unsigned bits);
34
+ const char *name;
41
+
35
+ uint32_t base;
42
+/* Similarly, with broadcast and syncing. */
36
+ uint32_t size;
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
37
+ int mpc; /* MPC number, -1 for "not behind an MPC" */
44
+ uint16_t idxmap, unsigned bits);
38
+ int mrindex;
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
39
+ int flags;
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
40
+} RAMInfo;
47
+
41
+
48
/**
42
+/*
49
* tlb_set_page_with_attrs:
43
+ * Flag values:
50
* @cpu: CPU to add this TLB entry for
44
+ * IS_ALIAS: this RAM area is an alias to the upstream end of the
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
45
+ * MPC specified by its .mpc value
52
uint16_t idxmap)
46
+ */
53
{
47
+#define IS_ALIAS 1
54
}
48
+
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
49
struct MPS2TZMachineClass {
56
+ target_ulong addr,
50
MachineClass parent;
57
+ uint16_t idxmap,
51
MPS2TZFPGAType fpga_type;
58
+ unsigned bits)
52
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
53
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
54
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
55
int numirq; /* Number of external interrupts */
56
+ const RAMInfo *raminfo;
57
const char *armsse_type;
58
};
59
60
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
61
MachineState parent;
62
63
ARMSSE iotkit;
64
- MemoryRegion ssram[3];
65
- MemoryRegion ssram1_m;
66
+ MemoryRegion ram[MPS2TZ_RAM_MAX];
67
MPS2SCC scc;
68
MPS2FPGAIO fpgaio;
69
TZPPC ppc[5];
70
- TZMPC ssram_mpc[3];
71
+ TZMPC mpc[3];
72
PL022State spi[5];
73
ArmSbconI2CState i2c[4];
74
UnimplementedDeviceState i2s_audio;
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
76
25000000,
77
};
78
79
+static const RAMInfo an505_raminfo[] = { {
80
+ .name = "ssram-0",
81
+ .base = 0x00000000,
82
+ .size = 0x00400000,
83
+ .mpc = 0,
84
+ .mrindex = 0,
85
+ }, {
86
+ .name = "ssram-1",
87
+ .base = 0x28000000,
88
+ .size = 0x00200000,
89
+ .mpc = 1,
90
+ .mrindex = 1,
91
+ }, {
92
+ .name = "ssram-2",
93
+ .base = 0x28200000,
94
+ .size = 0x00200000,
95
+ .mpc = 2,
96
+ .mrindex = 2,
97
+ }, {
98
+ .name = "ssram-0-alias",
99
+ .base = 0x00400000,
100
+ .size = 0x00400000,
101
+ .mpc = 0,
102
+ .mrindex = 3,
103
+ .flags = IS_ALIAS,
104
+ }, {
105
+ /* Use the largest bit of contiguous RAM as our "system memory" */
106
+ .name = "mps.ram",
107
+ .base = 0x80000000,
108
+ .size = 16 * MiB,
109
+ .mpc = -1,
110
+ .mrindex = -1,
111
+ }, {
112
+ .name = NULL,
113
+ },
114
+};
115
+
116
+static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
59
+{
117
+{
60
+}
118
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
119
+ const RAMInfo *p;
62
+ target_ulong addr,
120
+
63
+ uint16_t idxmap,
121
+ for (p = mmc->raminfo; p->name; p++) {
64
+ unsigned bits)
122
+ if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
65
+{
123
+ return p;
66
+}
67
+static inline void
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
69
+ uint16_t idxmap, unsigned bits)
70
+{
71
+}
72
#endif
73
/**
74
* probe_access:
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/accel/tcg/cputlb.c
78
+++ b/accel/tcg/cputlb.c
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
143
}
144
}
145
}
146
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
148
+ target_ulong page)
149
+{
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
151
+}
152
+
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
154
target_ulong page)
155
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
158
}
159
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
161
+ target_ulong page, unsigned bits)
162
+{
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
166
+
167
+ /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
169
+ * within the TLB; otherwise all addresses that match under @mask hit
170
+ * the same TLB entry.
171
+ *
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
173
+ * For now, just flush the entire TLB.
174
+ */
175
+ if (mask < f->mask) {
176
+ tlb_debug("forcing full flush midx %d ("
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
178
+ midx, page, mask);
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
180
+ return;
181
+ }
182
+
183
+ /* Check if we need to flush due to large pages. */
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
185
+ tlb_debug("forcing full flush midx %d ("
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
187
+ midx, d->large_page_addr, d->large_page_mask);
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
189
+ return;
190
+ }
191
+
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
193
+ tlb_n_used_entries_dec(env, midx);
194
+ }
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
196
+}
197
+
198
+typedef struct {
199
+ target_ulong addr;
200
+ uint16_t idxmap;
201
+ uint16_t bits;
202
+} TLBFlushPageBitsByMMUIdxData;
203
+
204
+static void
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
206
+ TLBFlushPageBitsByMMUIdxData d)
207
+{
208
+ CPUArchState *env = cpu->env_ptr;
209
+ int mmu_idx;
210
+
211
+ assert_cpu_is_self(cpu);
212
+
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
214
+ d.addr, d.bits, d.idxmap);
215
+
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
218
+ if ((d.idxmap >> mmu_idx) & 1) {
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
220
+ }
124
+ }
221
+ }
125
+ }
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
126
+ /* if raminfo array doesn't have an entry for each MPC this is a bug */
223
+
127
+ g_assert_not_reached();
224
+ tb_flush_jmp_cache(cpu, d.addr);
225
+}
128
+}
226
+
129
+
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
130
+static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
228
+ TLBFlushPageBitsByMMUIdxData d)
131
+ const RAMInfo *raminfo)
229
+{
132
+{
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
133
+ /* Return an initialized MemoryRegion for the RAMInfo. */
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
134
+ MemoryRegion *ram;
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
135
+
233
+ return true;
136
+ if (raminfo->mrindex < 0) {
137
+ /* Means this RAMInfo is for QEMU's "system memory" */
138
+ MachineState *machine = MACHINE(mms);
139
+ return machine->ram;
234
+ }
140
+ }
235
+ return false;
141
+
142
+ assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
143
+ ram = &mms->ram[raminfo->mrindex];
144
+
145
+ memory_region_init_ram(ram, NULL, raminfo->name,
146
+ raminfo->size, &error_fatal);
147
+ return ram;
236
+}
148
+}
237
+
149
+
238
+static TLBFlushPageBitsByMMUIdxData
150
/* Create an alias of an entire original MemoryRegion @orig
239
+decode_runon_to_pbm(run_on_cpu_data data)
151
* located at @base in the memory map.
152
*/
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
154
const int *irqs)
155
{
156
TZMPC *mpc = opaque;
157
- int i = mpc - &mms->ssram_mpc[0];
158
- MemoryRegion *ssram = &mms->ssram[i];
159
+ int i = mpc - &mms->mpc[0];
160
MemoryRegion *upstream;
161
- char *mpcname = g_strdup_printf("%s-mpc", name);
162
- static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
163
- static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
164
+ const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
165
+ MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
166
167
- memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
168
-
169
- object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC);
170
- object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram),
171
+ object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
172
+ object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
173
&error_fatal);
174
sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
175
/* Map the upstream end of the MPC into system memory */
176
upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
177
- memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
178
+ memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
179
/* and connect its interrupt to the IoTKit */
180
qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
181
qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
182
"mpcexp_status", i));
183
184
- /* The first SSRAM is a special case as it has an alias; accesses to
185
- * the alias region at 0x00400000 must also go to the MPC upstream.
186
- */
187
- if (i == 0) {
188
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
189
- }
190
-
191
- g_free(mpcname);
192
/* Return the register interface MR for our caller to map behind the PPC */
193
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
}
195
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
196
return sysbus_mmio_get_region(s, 0);
197
}
198
199
+static void create_non_mpc_ram(MPS2TZMachineState *mms)
240
+{
200
+{
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
201
+ /*
242
+ return (TLBFlushPageBitsByMMUIdxData){
202
+ * Handle the RAMs which are either not behind MPCs or which are
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
203
+ * aliases to another MPC.
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
204
+ */
245
+ .bits = addr_map_bits & 0x3f
205
+ const RAMInfo *p;
246
+ };
206
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
247
+}
207
+
248
+
208
+ for (p = mmc->raminfo; p->name; p++) {
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
209
+ if (p->flags & IS_ALIAS) {
250
+ run_on_cpu_data runon)
210
+ SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
251
+{
211
+ MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
212
+ make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
253
+}
213
+ } else if (p->mpc == -1) {
254
+
214
+ /* RAM not behind an MPC */
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
215
+ MemoryRegion *mr = mr_for_raminfo(mms, p);
256
+ run_on_cpu_data data)
216
+ memory_region_add_subregion(get_system_memory(), p->base, mr);
257
+{
217
+ }
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
218
+ }
298
+}
219
+}
299
+
220
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
221
static void mps2tz_common_init(MachineState *machine)
301
+ target_ulong addr,
222
{
302
+ uint16_t idxmap,
223
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
303
+ unsigned bits)
224
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
304
+{
225
qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
305
+ TLBFlushPageBitsByMMUIdxData d;
226
qdev_get_gpio_in(dev_splitter, 0));
306
+ run_on_cpu_data runon;
227
307
+
228
- /* The IoTKit sets up much of the memory layout, including
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
229
+ /*
309
+ if (bits >= TARGET_LONG_BITS) {
230
+ * The IoTKit sets up much of the memory layout, including
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
231
* the aliases between secure and non-secure regions in the
311
+ return;
232
- * address space. The FPGA itself contains:
312
+ }
233
- *
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
234
- * 0x00000000..0x003fffff SSRAM1
314
+ if (bits < TARGET_PAGE_BITS) {
235
- * 0x00400000..0x007fffff alias of SSRAM1
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
236
- * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
316
+ return;
237
- * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
317
+ }
238
- * 0x80000000..0x80ffffff 16MB PSRAM
318
+
239
- */
319
+ /* This should already be page aligned */
240
-
320
+ d.addr = addr & TARGET_PAGE_MASK;
241
- /* The FPGA images have an odd combination of different RAMs,
321
+ d.idxmap = idxmap;
242
+ * address space, and also most of the devices in the system.
322
+ d.bits = bits;
243
+ * The FPGA itself contains various RAMs and some additional devices.
323
+
244
+ * The FPGA images have an odd combination of different RAMs,
324
+ if (encode_pbm_to_runon(&runon, d)) {
245
* because in hardware they are different implementations and
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
246
* connected to different buses, giving varying performance/size
326
+ } else {
247
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
327
+ CPUState *dst_cpu;
248
- * call the 16MB our "system memory", as it's the largest lump.
328
+ TLBFlushPageBitsByMMUIdxData *p;
249
+ * call the largest lump our "system memory".
329
+
250
*/
330
+ /* Allocate a separate data block for each destination cpu. */
251
- memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
331
+ CPU_FOREACH(dst_cpu) {
252
332
+ if (dst_cpu != src_cpu) {
253
/*
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
254
* The overflow IRQs for all UARTs are ORed together.
334
+ *p = d;
255
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
335
+ async_run_on_cpu(dst_cpu,
256
const PPCInfo an505_ppcs[] = { {
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
257
.name = "apb_ppcexp0",
337
+ RUN_ON_CPU_HOST_PTR(p));
258
.ports = {
338
+ }
259
- { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
339
+ }
260
- { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
340
+ }
261
- { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
341
+
262
+ { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
263
+ { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
343
+}
264
+ { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
344
+
265
},
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
266
}, {
346
+ target_ulong addr,
267
.name = "apb_ppcexp1",
347
+ uint16_t idxmap,
268
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
348
+ unsigned bits)
269
349
+{
270
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
350
+ TLBFlushPageBitsByMMUIdxData d;
271
351
+ run_on_cpu_data runon;
272
+ create_non_mpc_ram(mms);
352
+
273
+
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
274
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
354
+ if (bits >= TARGET_LONG_BITS) {
275
}
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
276
356
+ return;
277
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
357
+ }
278
mmc->fpgaio_num_leds = 2;
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
279
mmc->fpgaio_has_switches = false;
359
+ if (bits < TARGET_PAGE_BITS) {
280
mmc->numirq = 92;
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
281
+ mmc->raminfo = an505_raminfo;
361
+ return;
282
mmc->armsse_type = TYPE_IOTKIT;
362
+ }
283
}
363
+
284
364
+ /* This should already be page aligned */
285
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
365
+ d.addr = addr & TARGET_PAGE_MASK;
286
mmc->fpgaio_num_leds = 2;
366
+ d.idxmap = idxmap;
287
mmc->fpgaio_has_switches = false;
367
+ d.bits = bits;
288
mmc->numirq = 92;
368
+
289
+ mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
369
+ if (encode_pbm_to_runon(&runon, d)) {
290
mmc->armsse_type = TYPE_SSE200;
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
291
}
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
292
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
385
+ }
386
+
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
388
+ *p = d;
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
390
+ RUN_ON_CPU_HOST_PTR(p));
391
+ }
392
+}
393
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
395
can be detected */
396
void tlb_protect_code(ram_addr_t ram_addr)
397
--
293
--
398
2.20.1
294
2.20.1
399
295
400
296
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Instead of hardcoding the MachineClass default_ram_size and
2
default_ram_id fields, set them on class creation by finding the
3
entry in the RAMInfo array which is marked as being the QEMU system
4
RAM.
2
5
3
When TBI is enabled in a given regime, 56 bits of the address
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
are significant and we need to clear out any other matching
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
virtual addresses with differing tags.
8
Message-id: 20210215115138.20465-18-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 24 ++++++++++++++++++++++--
11
1 file changed, 22 insertions(+), 2 deletions(-)
6
12
7
The other uses of tlb_flush_page (without mmuidx) in this file
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
8
are only used by aarch32 mode.
9
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
19
1 file changed, 39 insertions(+), 7 deletions(-)
20
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
15
--- a/hw/arm/mps2-tz.c
24
+++ b/target/arm/helper.c
16
+++ b/hw/arm/mps2-tz.c
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
17
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
26
#endif
18
27
19
mc->init = mps2tz_common_init;
28
static void switch_mode(CPUARMState *env, int mode);
20
iic->check = mps2_tz_idau_check;
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
21
- mc->default_ram_size = 16 * MiB;
30
22
- mc->default_ram_id = "mps.ram";
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
32
{
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
34
}
35
}
36
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
39
+ uint64_t addr)
40
+{
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
43
+ int select = extract64(addr, 55, 1);
44
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
46
+}
23
+}
47
+
24
+
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
25
+static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
49
+{
26
+{
50
+ ARMMMUIdx mmu_idx;
27
+ /*
28
+ * Set mc->default_ram_size and default_ram_id from the
29
+ * information in mmc->raminfo.
30
+ */
31
+ MachineClass *mc = MACHINE_CLASS(mmc);
32
+ const RAMInfo *p;
51
+
33
+
52
+ /* Only the regime of the mmu_idx below is significant. */
34
+ for (p = mmc->raminfo; p->name; p++) {
53
+ if (arm_is_secure_below_el3(env)) {
35
+ if (p->mrindex < 0) {
54
+ mmu_idx = ARMMMUIdx_SE10_0;
36
+ /* Found the entry for "system memory" */
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
37
+ mc->default_ram_size = p->size;
56
+ == (HCR_E2H | HCR_TGE)) {
38
+ mc->default_ram_id = p->name;
57
+ mmu_idx = ARMMMUIdx_E20_0;
39
+ return;
58
+ } else {
40
+ }
59
+ mmu_idx = ARMMMUIdx_E10_0;
60
+ }
41
+ }
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
42
+ g_assert_not_reached();
62
+}
63
+
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
uint64_t value)
66
{
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
CPUState *cs = env_cpu(env);
69
int mask = vae1_tlbmask(env);
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
71
+ int bits = vae1_tlbbits(env, pageaddr);
72
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
75
}
43
}
76
44
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
45
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
46
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
CPUState *cs = env_cpu(env);
47
mmc->numirq = 92;
80
int mask = vae1_tlbmask(env);
48
mmc->raminfo = an505_raminfo;
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
49
mmc->armsse_type = TYPE_IOTKIT;
82
+ int bits = vae1_tlbbits(env, pageaddr);
50
+ mps2tz_set_default_ram_info(mmc);
83
84
if (tlb_force_broadcast(env)) {
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
87
} else {
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
90
}
91
}
51
}
92
52
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
53
static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
94
{
54
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
95
CPUState *cs = env_cpu(env);
55
mmc->numirq = 92;
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
56
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
57
mmc->armsse_type = TYPE_SSE200;
98
58
+ mps2tz_set_default_ram_info(mmc);
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
102
+ ARMMMUIdxBit_E2, bits);
103
}
59
}
104
60
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
61
static const TypeInfo mps2tz_info = {
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
{
108
CPUState *cs = env_cpu(env);
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
111
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
62
--
120
2.20.1
63
2.20.1
121
64
122
65
diff view generated by jsdifflib
1
The t32 decode has a group which represents a set of insns
1
The AN505 and AN521 don't have any read-only memory, but the AN524
2
which overlap with B_cond_thumb because they have [25:23]=111
2
does; add a flag to ROMInfo to mark a region as ROM.
3
(which is an invalid condition code field for the branch insn).
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
7
3
8
For this to be valid syntactically, CPS must move into the same
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
overlapping-group as the hint insns (CPS vs hints was the
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
only actual use of the overlap facility for the group).
6
Message-id: 20210215115138.20465-19-peter.maydell@linaro.org
7
---
8
hw/arm/mps2-tz.c | 6 ++++++
9
1 file changed, 6 insertions(+)
11
10
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
13
--- a/hw/arm/mps2-tz.c
26
+++ b/target/arm/t32.decode
14
+++ b/hw/arm/mps2-tz.c
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
15
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
28
{
16
* Flag values:
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
17
* IS_ALIAS: this RAM area is an alias to the upstream end of the
30
# or unconditional, which would be illegal for the branch.
18
* MPC specified by its .mpc value
31
- {
19
+ * IS_ROM: this RAM area is read-only
32
- # Hints
20
*/
33
+ [
21
#define IS_ALIAS 1
34
+ # Hints, and CPS
22
+#define IS_ROM 2
35
{
23
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
24
struct MPS2TZMachineClass {
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
25
MachineClass parent;
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
26
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
39
# The canonical nop ends in 0000 0000, but the whole rest
27
if (raminfo->mrindex < 0) {
40
# of the space is "reserved hint, behaves as nop".
28
/* Means this RAMInfo is for QEMU's "system memory" */
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
29
MachineState *machine = MACHINE(mms);
42
+
30
+ assert(!(raminfo->flags & IS_ROM));
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
31
return machine->ram;
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
32
}
47
33
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
35
50
- &cps
36
memory_region_init_ram(ram, NULL, raminfo->name,
51
-
37
raminfo->size, &error_fatal);
52
# Miscellaneous control
38
+ if (raminfo->flags & IS_ROM) {
53
- [
39
+ memory_region_set_readonly(ram, true);
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
40
+ }
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
41
return ram;
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
75
}
42
}
76
43
77
--
44
--
78
2.20.1
45
2.20.1
79
46
80
47
diff view generated by jsdifflib
1
v8.1M's "low-overhead-loop" extension has three instructions
1
The armv7m_load_kernel() function takes a mem_size argument which it
2
for looping:
2
expects to be the size of the memory region at guest address 0. (It
3
* DLS (start of a do-loop)
3
uses this argument only as a limit on how large a raw image file it
4
* WLS (start of a while-loop)
4
can load at address zero).
5
* LE (end of a loop)
6
5
7
The loop-start instructions are both simple operations to start a
6
Instead of hardcoding this value, find the RAMInfo corresponding to
8
loop whose iteration count (if any) is in LR. The loop-end
7
the 0 address and extract its size.
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
8
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
12
Message-id: 20210215115138.20465-20-peter.maydell@linaro.org
28
---
13
---
29
target/arm/t32.decode | 8 ++++
14
hw/arm/mps2-tz.c | 17 ++++++++++++++++-
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
15
1 file changed, 16 insertions(+), 1 deletion(-)
31
2 files changed, 99 insertions(+), 2 deletions(-)
32
16
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
19
--- a/hw/arm/mps2-tz.c
36
+++ b/target/arm/t32.decode
20
+++ b/hw/arm/mps2-tz.c
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
21
@@ -XXX,XX +XXX,XX @@ static void create_non_mpc_ram(MPS2TZMachineState *mms)
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
44
+
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate.c
53
+++ b/target/arm/translate.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
62
if (unlikely(is_singlestepping(s))) {
63
/* An indirect jump so that we still trigger the debug exception. */
64
gen_set_pc_im(s, dest);
65
s->base.is_jmp = DISAS_JUMP;
66
} else {
67
- gen_goto_tb(s, 0, dest);
68
+ gen_goto_tb(s, tbno, dest);
69
}
22
}
70
}
23
}
71
24
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
25
+static uint32_t boot_ram_size(MPS2TZMachineState *mms)
73
+{
26
+{
74
+ gen_jmp_tb(s, dest, 0);
27
+ /* Return the size of the RAM block at guest address zero */
28
+ const RAMInfo *p;
29
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
30
+
31
+ for (p = mmc->raminfo; p->name; p++) {
32
+ if (p->base == 0) {
33
+ return p->size;
34
+ }
35
+ }
36
+ g_assert_not_reached();
75
+}
37
+}
76
+
38
+
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
39
static void mps2tz_common_init(MachineState *machine)
78
{
40
{
79
if (x)
41
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
81
return true;
43
44
create_non_mpc_ram(mms);
45
46
- armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
47
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
48
+ boot_ram_size(mms));
82
}
49
}
83
50
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
51
static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
85
+{
86
+ /* M-profile low-overhead loop start */
87
+ TCGv_i32 tmp;
88
+
89
+ if (!dc_isar_feature(aa32_lob, s)) {
90
+ return false;
91
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
101
+}
102
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
104
+{
105
+ /* M-profile low-overhead while-loop start */
106
+ TCGv_i32 tmp;
107
+ TCGLabel *nextlabel;
108
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
110
+ return false;
111
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
136
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
138
+{
139
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
151
+ }
152
+
153
+ if (!a->f) {
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
169
TCGv_i32 addr, tmp;
170
--
52
--
171
2.20.1
53
2.20.1
172
54
173
55
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
Add support for the mps3-an524 board; this is an SSE-200 based FPGA
2
set of instructions that request the CPU to perform a branch
2
image, like the existing mps2-an521. It has a usefully larger amount
3
"in the future", when it reaches a particular execution address.
3
of RAM, and a PL031 RTC, as well as some more minor differences.
4
In hardware, the expected implementation is that the information
4
5
about the branch location and destination is cached and then
5
In real hardware this image runs on a newer generation of the FPGA
6
acted upon when execution reaches the specified address.
6
board, the MPS3 rather than the older MPS2. Architecturally the two
7
However the architecture permits an implementation to discard
7
boards are similar, so we implement the MPS3 boards in the mps2-tz.c
8
this cached information at any point, and so guest code must
8
file as variations of the existing MPS2 boards.
9
always include a normal branch insn at the branch point as
9
10
a fallback. In particular, an implementation is specifically
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
permitted to treat all BF insns as NOPs (which is equivalent
12
to discarding the cached information immediately).
13
14
For QEMU, implementing this caching of branch information
15
would be complicated and would not improve the speed of
16
execution at all, so we make the IMPDEF choice to implement
17
all BF insns as NOPs.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20210215115138.20465-21-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
13
---
23
target/arm/cpu.h | 6 ++++++
14
hw/arm/mps2-tz.c | 139 +++++++++++++++++++++++++++++++++++++++++++++--
24
target/arm/t32.decode | 13 ++++++++++++-
15
1 file changed, 135 insertions(+), 4 deletions(-)
25
target/arm/translate.c | 20 ++++++++++++++++++++
16
26
3 files changed, 38 insertions(+), 1 deletion(-)
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
19
--- a/hw/arm/mps2-tz.c
31
+++ b/target/arm/cpu.h
20
+++ b/hw/arm/mps2-tz.c
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
21
@@ -XXX,XX +XXX,XX @@
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
22
* This source file covers the following FPGA images, for TrustZone cores:
23
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
24
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
25
+ * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
26
*
27
* Links to the TRM for the board itself and to the various Application
28
* Notes which document the FPGA images can be found here:
29
@@ -XXX,XX +XXX,XX @@
30
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
31
* Application Note AN521:
32
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
33
+ * Application Note AN524:
34
+ * https://developer.arm.com/documentation/dai0524/latest/
35
*
36
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
37
* (ARM ECM0601256) for the details of some of the device layout:
38
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
39
- * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
40
+ * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
41
* most of the device layout:
42
* http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
43
*
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/qdev-clock.h"
46
#include "qom/object.h"
47
48
-#define MPS2TZ_NUMIRQ_MAX 92
49
+#define MPS2TZ_NUMIRQ_MAX 95
50
#define MPS2TZ_RAM_MAX 4
51
52
typedef enum MPS2TZFPGAType {
53
FPGA_AN505,
54
FPGA_AN521,
55
+ FPGA_AN524,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
TZPPC ppc[5];
61
TZMPC mpc[3];
62
PL022State spi[5];
63
- ArmSbconI2CState i2c[4];
64
+ ArmSbconI2CState i2c[5];
65
UnimplementedDeviceState i2s_audio;
66
UnimplementedDeviceState gpio[4];
67
UnimplementedDeviceState gfx;
68
+ UnimplementedDeviceState cldc;
69
+ UnimplementedDeviceState rtc;
70
PL080State dma[4];
71
TZMSC msc[4];
72
- CMSDKAPBUART uart[5];
73
+ CMSDKAPBUART uart[6];
74
SplitIRQ sec_resp_splitter;
75
qemu_or_irq uart_irq_orgate;
76
DeviceState *lan9118;
77
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
78
#define TYPE_MPS2TZ_MACHINE "mps2tz"
79
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
80
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
81
+#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
82
83
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
84
85
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
86
25000000,
87
};
88
89
+static const uint32_t an524_oscclk[] = {
90
+ 24000000,
91
+ 32000000,
92
+ 50000000,
93
+ 50000000,
94
+ 24576000,
95
+ 23750000,
96
+};
97
+
98
static const RAMInfo an505_raminfo[] = { {
99
.name = "ssram-0",
100
.base = 0x00000000,
101
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
102
},
103
};
104
105
+static const RAMInfo an524_raminfo[] = { {
106
+ .name = "bram",
107
+ .base = 0x00000000,
108
+ .size = 512 * KiB,
109
+ .mpc = 0,
110
+ .mrindex = 0,
111
+ }, {
112
+ .name = "sram",
113
+ .base = 0x20000000,
114
+ .size = 32 * 4 * KiB,
115
+ .mpc = 1,
116
+ .mrindex = 1,
117
+ }, {
118
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
119
+ .name = "QSPI",
120
+ .base = 0x28000000,
121
+ .size = 8 * MiB,
122
+ .mpc = 1,
123
+ .mrindex = 2,
124
+ .flags = IS_ROM,
125
+ }, {
126
+ .name = "DDR",
127
+ .base = 0x60000000,
128
+ .size = 2 * GiB,
129
+ .mpc = 2,
130
+ .mrindex = -1,
131
+ }, {
132
+ .name = NULL,
133
+ },
134
+};
135
+
136
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
137
{
138
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
139
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
140
},
141
};
142
143
+ const PPCInfo an524_ppcs[] = { {
144
+ .name = "apb_ppcexp0",
145
+ .ports = {
146
+ { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
147
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
148
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
149
+ },
150
+ }, {
151
+ .name = "apb_ppcexp1",
152
+ .ports = {
153
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
154
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
155
+ { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
156
+ { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
157
+ { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
158
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
159
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
160
+ { /* port 7 reserved */ },
161
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
162
+ },
163
+ }, {
164
+ .name = "apb_ppcexp2",
165
+ .ports = {
166
+ { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
167
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
168
+ 0x41301000, 0x1000 },
169
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
170
+ { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
171
+ { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
172
+ { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
173
+ { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
174
+ { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
175
+ { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
176
+
177
+ { /* port 9 reserved */ },
178
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
179
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
180
+ },
181
+ }, {
182
+ .name = "ahb_ppcexp0",
183
+ .ports = {
184
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
185
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
186
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
187
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
188
+ { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
189
+ },
190
+ },
191
+ };
192
+
193
switch (mmc->fpga_type) {
194
case FPGA_AN505:
195
case FPGA_AN521:
196
ppcs = an505_ppcs;
197
num_ppcs = ARRAY_SIZE(an505_ppcs);
198
break;
199
+ case FPGA_AN524:
200
+ ppcs = an524_ppcs;
201
+ num_ppcs = ARRAY_SIZE(an524_ppcs);
202
+ break;
203
default:
204
g_assert_not_reached();
205
}
206
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
207
mps2tz_set_default_ram_info(mmc);
34
}
208
}
35
209
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
210
+static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
37
+{
211
+{
38
+ /* (M-profile) low-overhead loops and branch future */
212
+ MachineClass *mc = MACHINE_CLASS(oc);
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
213
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
214
+
215
+ mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
216
+ mc->default_cpus = 2;
217
+ mc->min_cpus = mc->default_cpus;
218
+ mc->max_cpus = mc->default_cpus;
219
+ mmc->fpga_type = FPGA_AN524;
220
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
221
+ mmc->scc_id = 0x41045240;
222
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
223
+ mmc->oscclk = an524_oscclk;
224
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
225
+ mmc->fpgaio_num_leds = 10;
226
+ mmc->fpgaio_has_switches = true;
227
+ mmc->numirq = 95;
228
+ mmc->raminfo = an524_raminfo;
229
+ mmc->armsse_type = TYPE_SSE200;
230
+ mps2tz_set_default_ram_info(mmc);
40
+}
231
+}
41
+
232
+
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
233
static const TypeInfo mps2tz_info = {
234
.name = TYPE_MPS2TZ_MACHINE,
235
.parent = TYPE_MACHINE,
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an521_info = {
237
.class_init = mps2tz_an521_class_init,
238
};
239
240
+static const TypeInfo mps3tz_an524_info = {
241
+ .name = TYPE_MPS3TZ_AN524_MACHINE,
242
+ .parent = TYPE_MPS2TZ_MACHINE,
243
+ .class_init = mps3tz_an524_class_init,
244
+};
245
+
246
static void mps2tz_machine_init(void)
43
{
247
{
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
248
type_register_static(&mps2tz_info);
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
249
type_register_static(&mps2tz_an505_info);
46
index XXXXXXX..XXXXXXX 100644
250
type_register_static(&mps2tz_an521_info);
47
--- a/target/arm/t32.decode
251
+ type_register_static(&mps3tz_an524_info);
48
+++ b/target/arm/t32.decode
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
50
51
B 1111 0. .......... 10.1 ............ @branch24
52
BL 1111 0. .......... 11.1 ............ @branch24
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
54
+{
55
+ # BLX_i is non-M-profile only
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
57
+ # M-profile only: loop and branch insns
58
+ [
59
+ # All these BF insns have boff != 0b0000; we NOP them all
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
64
+ ]
65
+}
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
71
return true;
72
}
252
}
73
253
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
254
type_init(mps2tz_machine_init);
75
+{
76
+ /*
77
+ * M-profile branch future insns. The architecture permits an
78
+ * implementation to implement these as NOPs (equivalent to
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
80
+ * take that IMPDEF option because for QEMU a "real" implementation
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
84
+ return false;
85
+ }
86
+ if (a->boff == 0) {
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
92
+}
93
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
95
{
96
TCGv_i32 addr, tmp;
97
--
255
--
98
2.20.1
256
2.20.1
99
257
100
258
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The AN524 has a USB controller (an ISP1763); we don't have a model of
2
it but we should provide a stub "unimplemented-device" for it. This
3
is slightly complicated because the USB controller shares a PPC port
4
with the ethernet controller.
2
5
3
We already have the full ARMMMUIdx as computed from the
6
Implement a make_* function which provides creates a container
4
function parameter.
7
MemoryRegion with both the ethernet controller and an
8
unimplemented-device stub for the USB controller.
5
9
6
For the purpose of regime_has_2_ranges, we can ignore any
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
difference between AccType_Normal and AccType_Unpriv, which
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
would be the only difference between the passed mmu_idx
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
and arm_mmu_idx_el.
13
Message-id: 20210215115138.20465-22-peter.maydell@linaro.org
14
---
15
hw/arm/mps2-tz.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
16
1 file changed, 47 insertions(+), 1 deletion(-)
10
17
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/mte_helper.c | 3 +--
19
1 file changed, 1 insertion(+), 2 deletions(-)
20
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
22
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
20
--- a/hw/arm/mps2-tz.c
24
+++ b/target/arm/mte_helper.c
21
+++ b/hw/arm/mps2-tz.c
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
22
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
23
27
case 2:
24
ARMSSE iotkit;
28
/* Tag check fail causes asynchronous flag set. */
25
MemoryRegion ram[MPS2TZ_RAM_MAX];
29
- mmu_idx = arm_mmu_idx_el(env, el);
26
+ MemoryRegion eth_usb_container;
30
- if (regime_has_2_ranges(mmu_idx)) {
27
+
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
28
MPS2SCC scc;
32
select = extract64(dirty_ptr, 55, 1);
29
MPS2FPGAIO fpgaio;
33
} else {
30
TZPPC ppc[5];
34
select = 0;
31
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
32
UnimplementedDeviceState gfx;
33
UnimplementedDeviceState cldc;
34
UnimplementedDeviceState rtc;
35
+ UnimplementedDeviceState usb;
36
PL080State dma[4];
37
TZMSC msc[4];
38
CMSDKAPBUART uart[6];
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
40
return sysbus_mmio_get_region(s, 0);
41
}
42
43
+static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
44
+ const char *name, hwaddr size,
45
+ const int *irqs)
46
+{
47
+ /*
48
+ * The AN524 makes the ethernet and USB share a PPC port.
49
+ * irqs[] is the ethernet IRQ.
50
+ */
51
+ SysBusDevice *s;
52
+ NICInfo *nd = &nd_table[0];
53
+
54
+ memory_region_init(&mms->eth_usb_container, OBJECT(mms),
55
+ "mps2-tz-eth-usb-container", 0x200000);
56
+
57
+ /*
58
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
59
+ * except that it doesn't support the checksum-offload feature.
60
+ */
61
+ qemu_check_nic_model(nd, "lan9118");
62
+ mms->lan9118 = qdev_new(TYPE_LAN9118);
63
+ qdev_set_nic_properties(mms->lan9118, nd);
64
+
65
+ s = SYS_BUS_DEVICE(mms->lan9118);
66
+ sysbus_realize_and_unref(s, &error_fatal);
67
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
68
+
69
+ memory_region_add_subregion(&mms->eth_usb_container,
70
+ 0, sysbus_mmio_get_region(s, 0));
71
+
72
+ /* The USB OTG controller is an ISP1763; we don't have a model of it. */
73
+ object_initialize_child(OBJECT(mms), "usb-otg",
74
+ &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
75
+ qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
76
+ qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
77
+ s = SYS_BUS_DEVICE(&mms->usb);
78
+ sysbus_realize(s, &error_fatal);
79
+
80
+ memory_region_add_subregion(&mms->eth_usb_container,
81
+ 0x100000, sysbus_mmio_get_region(s, 0));
82
+
83
+ return &mms->eth_usb_container;
84
+}
85
+
86
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
87
const char *name, hwaddr size,
88
const int *irqs)
89
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
90
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
91
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
92
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
93
- { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
94
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
95
},
96
},
97
};
35
--
98
--
36
2.20.1
99
2.20.1
37
100
38
101
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
The AN524 has a PL031 RTC, which we have a model of; provide it
2
rather than an unimplemented-device stub.
2
3
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-23-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 22 ++++++++++++++++++++--
10
1 file changed, 20 insertions(+), 2 deletions(-)
6
11
7
Restrict the APEI tables generation code to the single user: the virt
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
8
machine. If another machine wants to use it, it simply has to 'select
9
ACPI_APEI' in its Kconfig.
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
default-configs/devices/arm-softmmu.mak | 1 -
21
hw/arm/Kconfig | 1 +
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
25
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
14
--- a/hw/arm/mps2-tz.c
27
+++ b/default-configs/devices/arm-softmmu.mak
15
+++ b/hw/arm/mps2-tz.c
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
16
@@ -XXX,XX +XXX,XX @@
29
CONFIG_FSL_IMX6UL=y
17
#include "hw/misc/tz-msc.h"
30
CONFIG_SEMIHOSTING=y
18
#include "hw/arm/armsse.h"
31
CONFIG_ALLWINNER_H3=y
19
#include "hw/dma/pl080.h"
32
-CONFIG_ACPI_APEI=y
20
+#include "hw/rtc/pl031.h"
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
21
#include "hw/ssi/pl022.h"
34
index XXXXXXX..XXXXXXX 100644
22
#include "hw/i2c/arm_sbcon_i2c.h"
35
--- a/hw/arm/Kconfig
23
#include "hw/net/lan9118.h"
36
+++ b/hw/arm/Kconfig
24
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
25
UnimplementedDeviceState gpio[4];
38
select ACPI_MEMORY_HOTPLUG
26
UnimplementedDeviceState gfx;
39
select ACPI_HW_REDUCED
27
UnimplementedDeviceState cldc;
40
select ACPI_NVDIMM
28
- UnimplementedDeviceState rtc;
41
+ select ACPI_APEI
29
UnimplementedDeviceState usb;
42
30
+ PL031State rtc;
43
config CHEETAH
31
PL080State dma[4];
44
bool
32
TZMSC msc[4];
33
CMSDKAPBUART uart[6];
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(s, 0);
36
}
37
38
+static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
39
+ const char *name, hwaddr size,
40
+ const int *irqs)
41
+{
42
+ PL031State *pl031 = opaque;
43
+ SysBusDevice *s;
44
+
45
+ object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
46
+ s = SYS_BUS_DEVICE(pl031);
47
+ sysbus_realize(s, &error_fatal);
48
+ /*
49
+ * The board docs don't give an IRQ number for the PL031, so
50
+ * presumably it is not connected.
51
+ */
52
+ return sysbus_mmio_get_region(s, 0);
53
+}
54
+
55
static void create_non_mpc_ram(MPS2TZMachineState *mms)
56
{
57
/*
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
60
{ /* port 9 reserved */ },
61
{ "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
62
- { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
63
+ { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
64
},
65
}, {
66
.name = "ahb_ppcexp0",
45
--
67
--
46
2.20.1
68
2.20.1
47
69
48
70
diff view generated by jsdifflib
1
The BLX immediate insn in the Thumb encoding always performs
1
Add brief documentation of the new mps3-an524 board.
2
a switch from Thumb to Arm state. This would be totally useless
3
in M-profile which has no Arm decoder, and so the instruction
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
2
6
(This part of the encoding space is used for the branch-future
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
and low-overhead-loop insns in v8.1M.)
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-24-peter.maydell@linaro.org
7
---
8
docs/system/arm/mps2.rst | 24 ++++++++++++++++++------
9
1 file changed, 18 insertions(+), 6 deletions(-)
8
10
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 8 insertions(+)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
13
--- a/docs/system/arm/mps2.rst
19
+++ b/target/arm/translate.c
14
+++ b/docs/system/arm/mps2.rst
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
15
@@ -XXX,XX +XXX,XX @@
21
{
16
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
22
TCGv_i32 tmp;
17
-================================================================================================================
23
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
24
+ /*
19
+=========================================================================================================================================
25
+ * BLX <imm> would be useless on M-profile; the encoding space
20
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
21
These board models all use Arm M-profile CPUs.
27
+ */
22
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
23
-The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
29
+ return false;
24
-FPGA but is otherwise the same as the 2). Since the CPU itself
30
+ }
25
-and most of the devices are in the FPGA, the details of the board
26
-as seen by the guest depend significantly on the FPGA image.
27
+The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
28
+bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
29
+FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
31
+
30
+
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
31
+Since the CPU itself and most of the devices are in the FPGA, the
33
if (s->thumb && (a->imm & 2)) {
32
+details of the board as seen by the guest depend significantly on the
34
return false;
33
+FPGA image.
34
35
QEMU models the following FPGA images:
36
37
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
38
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
39
``mps2-an521``
40
Dual Cortex-M33 as documented in Arm Application Note AN521
41
+``mps3-an524``
42
+ Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
43
44
Differences between QEMU and real hardware:
45
46
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
47
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
48
if zbt_boot_ctrl is always zero)
49
+- AN524 remapping of low memory to either BRAM or to QSPI flash is
50
+ unimplemented (QEMU always maps this to BRAM, ignoring the
51
+ SCC CFG_REG0 memory-remap bit)
52
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
53
visible difference is that the LAN9118 doesn't support checksum
54
offloading
55
+- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
56
+ flash, but only as simple ROM, so attempting to rewrite the flash
57
+ from the guest will fail
58
+- QEMU does not model the USB controller in MPS3 boards
35
--
59
--
36
2.20.1
60
2.20.1
37
61
38
62
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
1
Update old infocenter.arm.com URLs to the equivalent developer.arm.com
2
2
ones (the old URLs should redirect, but we might as well avoid the
3
Current documentation is not too clear on the GETPC usage.
3
redirection notice, and the new URLs are pleasantly shorter).
4
In particular, when used outside the top level helper function
4
5
it causes unexpected behavior.
5
This commit covers the links to the MPS2 board TRM, the various
6
6
Application Notes, the IoTKit and SSE-200 documents.
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
7
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
9
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>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-25-peter.maydell@linaro.org
11
---
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
12
include/hw/arm/armsse.h | 4 ++--
13
1 file changed, 7 insertions(+), 1 deletion(-)
13
include/hw/misc/armsse-cpuid.h | 2 +-
14
14
include/hw/misc/armsse-mhu.h | 2 +-
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
15
include/hw/misc/iotkit-secctl.h | 2 +-
16
index XXXXXXX..XXXXXXX 100644
16
include/hw/misc/iotkit-sysctl.h | 2 +-
17
--- a/docs/devel/loads-stores.rst
17
include/hw/misc/iotkit-sysinfo.h | 2 +-
18
+++ b/docs/devel/loads-stores.rst
18
include/hw/misc/mps2-fpgaio.h | 2 +-
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
19
hw/arm/mps2-tz.c | 11 +++++------
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
20
hw/misc/armsse-cpuid.c | 2 +-
21
to indicate that the guest CPU state is already synchronized, or
21
hw/misc/armsse-mhu.c | 2 +-
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
22
hw/misc/iotkit-sysctl.c | 2 +-
23
-function, which is a return address into the generated code.
23
hw/misc/iotkit-sysinfo.c | 2 +-
24
+function, which is a return address into the generated code [#gpc]_.
24
hw/misc/mps2-fpgaio.c | 2 +-
25
+
25
hw/misc/mps2-scc.c | 2 +-
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
26
14 files changed, 19 insertions(+), 20 deletions(-)
27
+ it in other functions that are *not* the top level
27
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
28
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
29
+ value of ``GETPC()`` should be read from the helper and passed
29
index XXXXXXX..XXXXXXX 100644
30
+ if needed to the functions that the helper calls.
30
--- a/include/hw/arm/armsse.h
31
31
+++ b/include/hw/arm/armsse.h
32
Function names follow the pattern:
32
@@ -XXX,XX +XXX,XX @@
33
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
34
* SSE-200. Currently we model:
35
* - the Arm IoT Kit which is documented in
36
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
37
+ * https://developer.arm.com/documentation/ecm0601256/latest
38
* - the SSE-200 which is documented in
39
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
40
+ * https://developer.arm.com/documentation/101104/latest/
41
*
42
* The IoTKit contains:
43
* a Cortex-M33
44
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/misc/armsse-cpuid.h
47
+++ b/include/hw/misc/armsse-cpuid.h
48
@@ -XXX,XX +XXX,XX @@
49
/*
50
* This is a model of the "CPU_IDENTITY" register block which is part of the
51
* Arm SSE-200 and documented in
52
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
53
+ * https://developer.arm.com/documentation/101104/latest/
54
*
55
* QEMU interface:
56
* + QOM property "CPUID": the value to use for the CPUID register
57
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/misc/armsse-mhu.h
60
+++ b/include/hw/misc/armsse-mhu.h
61
@@ -XXX,XX +XXX,XX @@
62
/*
63
* This is a model of the Message Handling Unit (MHU) which is part of the
64
* Arm SSE-200 and documented in
65
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
66
+ * https://developer.arm.com/documentation/101104/latest/
67
*
68
* QEMU interface:
69
* + sysbus MMIO region 0: the system information register bank
70
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/misc/iotkit-secctl.h
73
+++ b/include/hw/misc/iotkit-secctl.h
74
@@ -XXX,XX +XXX,XX @@
75
76
/* This is a model of the security controller which is part of the
77
* Arm IoT Kit and documented in
78
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
79
+ * https://developer.arm.com/documentation/ecm0601256/latest
80
*
81
* QEMU interface:
82
* + sysbus MMIO region 0 is the "secure privilege control block" registers
83
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/misc/iotkit-sysctl.h
86
+++ b/include/hw/misc/iotkit-sysctl.h
87
@@ -XXX,XX +XXX,XX @@
88
/*
89
* This is a model of the "system control element" which is part of the
90
* Arm IoTKit and documented in
91
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
92
+ * https://developer.arm.com/documentation/ecm0601256/latest
93
* Specifically, it implements the "system information block" and
94
* "system control register" blocks.
95
*
96
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/include/hw/misc/iotkit-sysinfo.h
99
+++ b/include/hw/misc/iotkit-sysinfo.h
100
@@ -XXX,XX +XXX,XX @@
101
/*
102
* This is a model of the "system information block" which is part of the
103
* Arm IoTKit and documented in
104
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
105
+ * https://developer.arm.com/documentation/ecm0601256/latest
106
* QEMU interface:
107
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
108
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
109
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
110
index XXXXXXX..XXXXXXX 100644
111
--- a/include/hw/misc/mps2-fpgaio.h
112
+++ b/include/hw/misc/mps2-fpgaio.h
113
@@ -XXX,XX +XXX,XX @@
114
/* This is a model of the FPGAIO register block in the AN505
115
* FPGA image for the MPS2 dev board; it is documented in the
116
* application note:
117
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
118
+ * https://developer.arm.com/documentation/dai0505/latest/
119
*
120
* QEMU interface:
121
* + sysbus MMIO region 0: the register bank
122
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/mps2-tz.c
125
+++ b/hw/arm/mps2-tz.c
126
@@ -XXX,XX +XXX,XX @@
127
* https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
128
*
129
* Board TRM:
130
- * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
131
+ * https://developer.arm.com/documentation/100112/latest/
132
* Application Note AN505:
133
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
134
+ * https://developer.arm.com/documentation/dai0505/latest/
135
* Application Note AN521:
136
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
137
+ * https://developer.arm.com/documentation/dai0521/latest/
138
* Application Note AN524:
139
* https://developer.arm.com/documentation/dai0524/latest/
140
*
141
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
142
* (ARM ECM0601256) for the details of some of the device layout:
143
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
144
+ * https://developer.arm.com/documentation/ecm0601256/latest
145
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
146
* most of the device layout:
147
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
148
- *
149
+ * https://developer.arm.com/documentation/101104/latest/
150
*/
151
152
#include "qemu/osdep.h"
153
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/misc/armsse-cpuid.c
156
+++ b/hw/misc/armsse-cpuid.c
157
@@ -XXX,XX +XXX,XX @@
158
/*
159
* This is a model of the "CPU_IDENTITY" register block which is part of the
160
* Arm SSE-200 and documented in
161
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
162
+ * https://developer.arm.com/documentation/101104/latest/
163
*
164
* It consists of one read-only CPUID register (set by QOM property), plus the
165
* usual ID registers.
166
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/misc/armsse-mhu.c
169
+++ b/hw/misc/armsse-mhu.c
170
@@ -XXX,XX +XXX,XX @@
171
/*
172
* This is a model of the Message Handling Unit (MHU) which is part of the
173
* Arm SSE-200 and documented in
174
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
175
+ * https://developer.arm.com/documentation/101104/latest/
176
*/
177
178
#include "qemu/osdep.h"
179
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/misc/iotkit-sysctl.c
182
+++ b/hw/misc/iotkit-sysctl.c
183
@@ -XXX,XX +XXX,XX @@
184
/*
185
* This is a model of the "system control element" which is part of the
186
* Arm IoTKit and documented in
187
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
188
+ * https://developer.arm.com/documentation/ecm0601256/latest
189
* Specifically, it implements the "system control register" blocks.
190
*/
191
192
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/hw/misc/iotkit-sysinfo.c
195
+++ b/hw/misc/iotkit-sysinfo.c
196
@@ -XXX,XX +XXX,XX @@
197
/*
198
* This is a model of the "system information block" which is part of the
199
* Arm IoTKit and documented in
200
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
201
+ * https://developer.arm.com/documentation/ecm0601256/latest
202
* It consists of 2 read-only version/config registers, plus the
203
* usual ID registers.
204
*/
205
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/misc/mps2-fpgaio.c
208
+++ b/hw/misc/mps2-fpgaio.c
209
@@ -XXX,XX +XXX,XX @@
210
/* This is a model of the "FPGA system control and I/O" block found
211
* in the AN505 FPGA image for the MPS2 devboard.
212
* It is documented in AN505:
213
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
214
+ * https://developer.arm.com/documentation/dai0505/latest/
215
*/
216
217
#include "qemu/osdep.h"
218
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/misc/mps2-scc.c
221
+++ b/hw/misc/mps2-scc.c
222
@@ -XXX,XX +XXX,XX @@
223
* found in the FPGA images of MPS2 development boards.
224
*
225
* Documentation of it can be found in the MPS2 TRM:
226
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
227
+ * https://developer.arm.com/documentation/100112/latest/
228
* and also in the Application Notes documenting individual FPGA images.
229
*/
33
230
34
--
231
--
35
2.20.1
232
2.20.1
36
233
37
234
diff view generated by jsdifflib