1 | Small pile of bug fixes for rc1. I've included my patches to get | 1 | The following changes since commit 64ada298b98a51eb2512607f6e6180cb330c47b1: |
---|---|---|---|
2 | our docs building with Sphinx 3, just for convenience... | ||
3 | 2 | ||
4 | -- PMM | 3 | Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220302' into staging (2022-03-02 12:38:46 +0000) |
5 | |||
6 | The following changes since commit b149dea55cce97cb226683d06af61984a1c11e96: | ||
7 | |||
8 | Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20201102' into staging (2020-11-02 10:57:48 +0000) | ||
9 | 4 | ||
10 | are available in the Git repository at: | 5 | are available in the Git repository at: |
11 | 6 | ||
12 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201102 | 7 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220302 |
13 | 8 | ||
14 | for you to fetch changes up to ffb4fbf90a2f63c9cb33e4bb9f854c79bf04ca4a: | 9 | for you to fetch changes up to 268c11984e67867c22f53beb3c7f8b98900d66b2: |
15 | 10 | ||
16 | tests/qtest/npcm7xx_rng-test: Disable randomness tests (2020-11-02 16:52:18 +0000) | 11 | ui/cocoa.m: Remove unnecessary NSAutoreleasePools (2022-03-02 19:27:37 +0000) |
17 | 12 | ||
18 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
19 | target-arm queue: | 14 | target-arm queue: |
20 | * target/arm: Fix Neon emulation bugs on big-endian hosts | 15 | * mps3-an547: Add missing user ahb interfaces |
21 | * target/arm: fix handling of HCR.FB | 16 | * hw/arm/mps2-tz.c: Update AN547 documentation URL |
22 | * target/arm: fix LORID_EL1 access check | 17 | * hw/input/tsc210x: Don't abort on bad SPI word widths |
23 | * disas/capstone: Fix monitor disassembly of >32 bytes | 18 | * hw/i2c: flatten pca954x mux device |
24 | * hw/arm/smmuv3: Fix potential integer overflow (CID 1432363) | 19 | * target/arm: Support PSCI 1.1 and SMCCC 1.0 |
25 | * hw/arm/boot: fix SVE for EL3 direct kernel boot | 20 | * target/arm: Fix early free of TCG temp in handle_simd_shift_fpint_conv() |
26 | * hw/display/omap_lcdc: Fix potential NULL pointer dereference | 21 | * tests/qtest: add qtests for npcm7xx sdhci |
27 | * hw/display/exynos4210_fimd: Fix potential NULL pointer dereference | 22 | * Implement FEAT_LVA |
28 | * target/arm: Get correct MMU index for other-security-state | 23 | * Implement FEAT_LPA |
29 | * configure: Test that gio libs from pkg-config work | 24 | * Implement FEAT_LPA2 (but do not enable it yet) |
30 | * hw/intc/arm_gicv3_cpuif: Make GIC maintenance interrupts work | 25 | * Report KVM's actual PSCI version to guest in dtb |
31 | * docs: Fix building with Sphinx 3 | 26 | * ui/cocoa.m: Fix updateUIInfo threading issues |
32 | * tests/qtest/npcm7xx_rng-test: Disable randomness tests | 27 | * ui/cocoa.m: Remove unnecessary NSAutoreleasePools |
33 | 28 | ||
34 | ---------------------------------------------------------------- | 29 | ---------------------------------------------------------------- |
35 | AlexChen (2): | 30 | Akihiko Odaki (1): |
36 | hw/display/omap_lcdc: Fix potential NULL pointer dereference | 31 | target/arm: Support PSCI 1.1 and SMCCC 1.0 |
37 | hw/display/exynos4210_fimd: Fix potential NULL pointer dereference | ||
38 | 32 | ||
39 | Peter Maydell (9): | 33 | Jimmy Brisson (1): |
40 | target/arm: Fix float16 pairwise Neon ops on big-endian hosts | 34 | mps3-an547: Add missing user ahb interfaces |
41 | target/arm: Fix VUDOT/VSDOT (scalar) on big-endian hosts | ||
42 | disas/capstone: Fix monitor disassembly of >32 bytes | ||
43 | target/arm: Get correct MMU index for other-security-state | ||
44 | configure: Test that gio libs from pkg-config work | ||
45 | hw/intc/arm_gicv3_cpuif: Make GIC maintenance interrupts work | ||
46 | scripts/kerneldoc: For Sphinx 3 use c:macro for macros with arguments | ||
47 | qemu-option-trace.rst.inc: Don't use option:: markup | ||
48 | tests/qtest/npcm7xx_rng-test: Disable randomness tests | ||
49 | 35 | ||
50 | Philippe Mathieu-Daudé (1): | 36 | Patrick Venture (1): |
51 | hw/arm/smmuv3: Fix potential integer overflow (CID 1432363) | 37 | hw/i2c: flatten pca954x mux device |
52 | 38 | ||
53 | Richard Henderson (11): | 39 | Peter Maydell (5): |
54 | target/arm: Introduce neon_full_reg_offset | 40 | hw/arm/mps2-tz.c: Update AN547 documentation URL |
55 | target/arm: Move neon_element_offset to translate.c | 41 | hw/input/tsc210x: Don't abort on bad SPI word widths |
56 | target/arm: Use neon_element_offset in neon_load/store_reg | 42 | target/arm: Report KVM's actual PSCI version to guest in dtb |
57 | target/arm: Use neon_element_offset in vfp_reg_offset | 43 | ui/cocoa.m: Fix updateUIInfo threading issues |
58 | target/arm: Add read/write_neon_element32 | 44 | ui/cocoa.m: Remove unnecessary NSAutoreleasePools |
59 | target/arm: Expand read/write_neon_element32 to all MemOp | ||
60 | target/arm: Rename neon_load_reg32 to vfp_load_reg32 | ||
61 | target/arm: Add read/write_neon_element64 | ||
62 | target/arm: Rename neon_load_reg64 to vfp_load_reg64 | ||
63 | target/arm: Simplify do_long_3d and do_2scalar_long | ||
64 | target/arm: Improve do_prewiden_3d | ||
65 | 45 | ||
66 | Rémi Denis-Courmont (3): | 46 | Richard Henderson (16): |
67 | target/arm: fix handling of HCR.FB | 47 | hw/registerfields: Add FIELD_SEX<N> and FIELD_SDP<N> |
68 | target/arm: fix LORID_EL1 access check | 48 | target/arm: Set TCR_EL1.TSZ for user-only |
69 | hw/arm/boot: fix SVE for EL3 direct kernel boot | 49 | target/arm: Fault on invalid TCR_ELx.TxSZ |
50 | target/arm: Move arm_pamax out of line | ||
51 | target/arm: Pass outputsize down to check_s2_mmu_setup | ||
52 | target/arm: Use MAKE_64BIT_MASK to compute indexmask | ||
53 | target/arm: Honor TCR_ELx.{I}PS | ||
54 | target/arm: Prepare DBGBVR and DBGWVR for FEAT_LVA | ||
55 | target/arm: Implement FEAT_LVA | ||
56 | target/arm: Implement FEAT_LPA | ||
57 | target/arm: Extend arm_fi_to_lfsc to level -1 | ||
58 | target/arm: Introduce tlbi_aa64_get_range | ||
59 | target/arm: Fix TLBIRange.base for 16k and 64k pages | ||
60 | target/arm: Validate tlbi TG matches translation granule in use | ||
61 | target/arm: Advertise all page sizes for -cpu max | ||
62 | target/arm: Implement FEAT_LPA2 | ||
70 | 63 | ||
71 | docs/qemu-option-trace.rst.inc | 6 +- | 64 | Shengtan Mao (1): |
72 | configure | 10 +- | 65 | tests/qtest: add qtests for npcm7xx sdhci |
73 | include/hw/intc/arm_gicv3_common.h | 1 - | ||
74 | disas/capstone.c | 2 +- | ||
75 | hw/arm/boot.c | 3 + | ||
76 | hw/arm/smmuv3.c | 3 +- | ||
77 | hw/display/exynos4210_fimd.c | 4 +- | ||
78 | hw/display/omap_lcdc.c | 10 +- | ||
79 | hw/intc/arm_gicv3_cpuif.c | 5 +- | ||
80 | target/arm/helper.c | 24 +- | ||
81 | target/arm/m_helper.c | 3 +- | ||
82 | target/arm/translate.c | 153 +++++++++--- | ||
83 | target/arm/vec_helper.c | 12 +- | ||
84 | tests/qtest/npcm7xx_rng-test.c | 14 +- | ||
85 | scripts/kernel-doc | 18 +- | ||
86 | target/arm/translate-neon.c.inc | 472 ++++++++++++++++++++----------------- | ||
87 | target/arm/translate-vfp.c.inc | 341 +++++++++++---------------- | ||
88 | 17 files changed, 588 insertions(+), 493 deletions(-) | ||
89 | 66 | ||
67 | Wentao_Liang (1): | ||
68 | target/arm: Fix early free of TCG temp in handle_simd_shift_fpint_conv() | ||
69 | |||
70 | docs/system/arm/emulation.rst | 3 + | ||
71 | include/hw/registerfields.h | 48 +++++- | ||
72 | target/arm/cpu-param.h | 4 +- | ||
73 | target/arm/cpu.h | 27 ++++ | ||
74 | target/arm/internals.h | 58 ++++--- | ||
75 | target/arm/kvm-consts.h | 14 +- | ||
76 | hw/arm/boot.c | 11 +- | ||
77 | hw/arm/mps2-tz.c | 6 +- | ||
78 | hw/i2c/i2c_mux_pca954x.c | 77 ++------- | ||
79 | hw/input/tsc210x.c | 8 +- | ||
80 | target/arm/cpu.c | 8 +- | ||
81 | target/arm/cpu64.c | 7 +- | ||
82 | target/arm/helper.c | 332 ++++++++++++++++++++++++++++++--------- | ||
83 | target/arm/hvf/hvf.c | 27 +++- | ||
84 | target/arm/kvm64.c | 14 +- | ||
85 | target/arm/psci.c | 35 ++++- | ||
86 | target/arm/translate-a64.c | 2 +- | ||
87 | tests/qtest/npcm7xx_sdhci-test.c | 215 +++++++++++++++++++++++++ | ||
88 | tests/qtest/meson.build | 1 + | ||
89 | ui/cocoa.m | 31 ++-- | ||
90 | 20 files changed, 736 insertions(+), 192 deletions(-) | ||
91 | create mode 100644 tests/qtest/npcm7xx_sdhci-test.c | diff view generated by jsdifflib |
1 | Sphinx 3.2 is pickier than earlier versions about the option:: markup, | 1 | From: Jimmy Brisson <jimmy.brisson@linaro.org> |
---|---|---|---|
2 | and complains about our usage in qemu-option-trace.rst: | ||
3 | 2 | ||
4 | ../../docs/qemu-option-trace.rst.inc:4:Malformed option description | 3 | With these interfaces missing, TFM would delegate peripherals 0, 1, |
5 | '[enable=]PATTERN', should look like "opt", "-opt args", "--opt args", | 4 | 2, 3 and 8, and qemu would ignore the delegation of interface 8, as |
6 | "/opt args" or "+opt args" | 5 | it thought interface 4 was eth & USB. |
7 | 6 | ||
8 | In this file, we're really trying to document the different parts of | 7 | This patch corrects this behavior and allows TFM to delegate the |
9 | the top-level --trace option, which qemu-nbd.rst and qemu-img.rst | 8 | eth & USB peripheral to NS mode. |
10 | have already introduced with an option:: markup. So it's not right | ||
11 | to use option:: here anyway. Switch to a different markup | ||
12 | (definition lists) which gives about the same formatted output. | ||
13 | 9 | ||
14 | (Unlike option::, this markup doesn't produce index entries; but | 10 | (The old QEMU behaviour was based on revision B of the AN547 |
15 | at the moment we don't do anything much with indexes anyway, and | 11 | appnote; revision C corrects this error in the documentation, |
16 | in any case I think it doesn't make much sense to have individual | 12 | and this commit brings QEMU in to line with how the FPGA |
17 | index entries for the sub-parts of the --trace option.) | 13 | image really behaves.) |
18 | 14 | ||
15 | Signed-off-by: Jimmy Brisson <jimmy.brisson@linaro.org> | ||
16 | Message-id: 20220210210227.3203883-1-jimmy.brisson@linaro.org | ||
17 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | [PMM: added commit message note clarifying that the old behaviour | ||
19 | was a docs issue, not because there were two different versions | ||
20 | of the FPGA image] | ||
19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
20 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
21 | Tested-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
22 | Message-id: 20201030174700.7204-3-peter.maydell@linaro.org | ||
23 | --- | 22 | --- |
24 | docs/qemu-option-trace.rst.inc | 6 +++--- | 23 | hw/arm/mps2-tz.c | 4 ++++ |
25 | 1 file changed, 3 insertions(+), 3 deletions(-) | 24 | 1 file changed, 4 insertions(+) |
26 | 25 | ||
27 | diff --git a/docs/qemu-option-trace.rst.inc b/docs/qemu-option-trace.rst.inc | 26 | diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c |
28 | index XXXXXXX..XXXXXXX 100644 | 27 | index XXXXXXX..XXXXXXX 100644 |
29 | --- a/docs/qemu-option-trace.rst.inc | 28 | --- a/hw/arm/mps2-tz.c |
30 | +++ b/docs/qemu-option-trace.rst.inc | 29 | +++ b/hw/arm/mps2-tz.c |
31 | @@ -XXX,XX +XXX,XX @@ | 30 | @@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine) |
32 | 31 | { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 }, | |
33 | Specify tracing options. | 32 | { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 }, |
34 | 33 | { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 }, | |
35 | -.. option:: [enable=]PATTERN | 34 | + { /* port 4 USER AHB interface 0 */ }, |
36 | +``[enable=]PATTERN`` | 35 | + { /* port 5 USER AHB interface 1 */ }, |
37 | 36 | + { /* port 6 USER AHB interface 2 */ }, | |
38 | Immediately enable events matching *PATTERN* | 37 | + { /* port 7 USER AHB interface 3 */ }, |
39 | (either event name or a globbing pattern). This option is only | 38 | { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } }, |
40 | @@ -XXX,XX +XXX,XX @@ Specify tracing options. | 39 | }, |
41 | 40 | }, | |
42 | Use :option:`-trace help` to print a list of names of trace points. | ||
43 | |||
44 | -.. option:: events=FILE | ||
45 | +``events=FILE`` | ||
46 | |||
47 | Immediately enable events listed in *FILE*. | ||
48 | The file must contain one event name (as listed in the ``trace-events-all`` | ||
49 | @@ -XXX,XX +XXX,XX @@ Specify tracing options. | ||
50 | available if QEMU has been compiled with the ``simple``, ``log`` or | ||
51 | ``ftrace`` tracing backend. | ||
52 | |||
53 | -.. option:: file=FILE | ||
54 | +``file=FILE`` | ||
55 | |||
56 | Log output traces to *FILE*. | ||
57 | This option is only available if QEMU has been compiled with | ||
58 | -- | 41 | -- |
59 | 2.20.1 | 42 | 2.25.1 |
60 | |||
61 | diff view generated by jsdifflib |
1 | If we're using the capstone disassembler, disassembly of a run of | 1 | The AN547 application note URL has changed: update our comment |
---|---|---|---|
2 | instructions more than 32 bytes long disassembles the wrong data for | 2 | accordingly. (Rev B is still downloadable from the old URL, |
3 | instructions beyond the 32 byte mark: | 3 | but there is a new Rev C of the document now.) |
4 | 4 | ||
5 | (qemu) xp /16x 0x100 | ||
6 | 0000000000000100: 0x00000005 0x54410001 0x00000001 0x00001000 | ||
7 | 0000000000000110: 0x00000000 0x00000004 0x54410002 0x3c000000 | ||
8 | 0000000000000120: 0x00000000 0x00000004 0x54410009 0x74736574 | ||
9 | 0000000000000130: 0x00000000 0x00000000 0x00000000 0x00000000 | ||
10 | (qemu) xp /16i 0x100 | ||
11 | 0x00000100: 00000005 andeq r0, r0, r5 | ||
12 | 0x00000104: 54410001 strbpl r0, [r1], #-1 | ||
13 | 0x00000108: 00000001 andeq r0, r0, r1 | ||
14 | 0x0000010c: 00001000 andeq r1, r0, r0 | ||
15 | 0x00000110: 00000000 andeq r0, r0, r0 | ||
16 | 0x00000114: 00000004 andeq r0, r0, r4 | ||
17 | 0x00000118: 54410002 strbpl r0, [r1], #-2 | ||
18 | 0x0000011c: 3c000000 .byte 0x00, 0x00, 0x00, 0x3c | ||
19 | 0x00000120: 54410001 strbpl r0, [r1], #-1 | ||
20 | 0x00000124: 00000001 andeq r0, r0, r1 | ||
21 | 0x00000128: 00001000 andeq r1, r0, r0 | ||
22 | 0x0000012c: 00000000 andeq r0, r0, r0 | ||
23 | 0x00000130: 00000004 andeq r0, r0, r4 | ||
24 | 0x00000134: 54410002 strbpl r0, [r1], #-2 | ||
25 | 0x00000138: 3c000000 .byte 0x00, 0x00, 0x00, 0x3c | ||
26 | 0x0000013c: 00000000 andeq r0, r0, r0 | ||
27 | |||
28 | Here the disassembly of 0x120..0x13f is using the data that is in | ||
29 | 0x104..0x123. | ||
30 | |||
31 | This is caused by passing the wrong value to the read_memory_func(). | ||
32 | The intention is that at this point in the loop the 'cap_buf' buffer | ||
33 | already contains 'csize' bytes of data for the instruction at guest | ||
34 | addr 'pc', and we want to read in an extra 'tsize' bytes. Those | ||
35 | extra bytes are therefore at 'pc + csize', not 'pc'. On the first | ||
36 | time through the loop 'csize' happens to be zero, so the initial read | ||
37 | of 32 bytes into cap_buf is correct and as long as the disassembly | ||
38 | never needs to read more data we return the correct information. | ||
39 | |||
40 | Use the correct guest address in the call to read_memory_func(). | ||
41 | |||
42 | Cc: qemu-stable@nongnu.org | ||
43 | Fixes: https://bugs.launchpad.net/qemu/+bug/1900779 | ||
44 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
45 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
46 | Message-id: 20201022132445.25039-1-peter.maydell@linaro.org | 7 | Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
8 | Message-id: 20220221094144.426191-1-peter.maydell@linaro.org | ||
47 | --- | 9 | --- |
48 | disas/capstone.c | 2 +- | 10 | hw/arm/mps2-tz.c | 2 +- |
49 | 1 file changed, 1 insertion(+), 1 deletion(-) | 11 | 1 file changed, 1 insertion(+), 1 deletion(-) |
50 | 12 | ||
51 | diff --git a/disas/capstone.c b/disas/capstone.c | 13 | diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c |
52 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
53 | --- a/disas/capstone.c | 15 | --- a/hw/arm/mps2-tz.c |
54 | +++ b/disas/capstone.c | 16 | +++ b/hw/arm/mps2-tz.c |
55 | @@ -XXX,XX +XXX,XX @@ bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) | 17 | @@ -XXX,XX +XXX,XX @@ |
56 | 18 | * Application Note AN524: | |
57 | /* Make certain that we can make progress. */ | 19 | * https://developer.arm.com/documentation/dai0524/latest/ |
58 | assert(tsize != 0); | 20 | * Application Note AN547: |
59 | - info->read_memory_func(pc, cap_buf + csize, tsize, info); | 21 | - * https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/DAI0547B_SSE300_PLUS_U55_FPGA_for_mps3.pdf |
60 | + info->read_memory_func(pc + csize, cap_buf + csize, tsize, info); | 22 | + * https://developer.arm.com/documentation/dai0547/latest/ |
61 | csize += tsize; | 23 | * |
62 | 24 | * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide | |
63 | if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { | 25 | * (ARM ECM0601256) for the details of some of the device layout: |
64 | -- | 26 | -- |
65 | 2.20.1 | 27 | 2.25.1 |
66 | 28 | ||
67 | 29 | diff view generated by jsdifflib |
1 | The randomness tests in the NPCM7xx RNG test fail intermittently | 1 | The tsc210x doesn't support anything other than 16-bit reads on the |
---|---|---|---|
2 | but fairly frequently. On my machine running the test in a loop: | 2 | SPI bus, but the guest can program the SPI controller to attempt |
3 | while QTEST_QEMU_BINARY=./qemu-system-aarch64 ./tests/qtest/npcm7xx_rng-test; do true; done | 3 | them anyway. If this happens, don't abort QEMU, just log this as |
4 | a guest error. | ||
4 | 5 | ||
5 | will fail in less than a minute with an error like: | 6 | This fixes our machine_arm_n8x0.py:N8x0Machine.test_n800 |
6 | ERROR:../../tests/qtest/npcm7xx_rng-test.c:256:test_first_byte_runs: | 7 | acceptance test, which hits this assertion. |
7 | assertion failed (calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE) > 0.01): (0.00286205989 > 0.01) | ||
8 | 8 | ||
9 | (Failures have been observed on all 4 of the randomness tests, | 9 | The reason we hit the assertion is because the guest kernel thinks |
10 | not just first_byte_runs.) | 10 | there is a TSC2005 on this SPI bus address, not a TSC210x. (The n810 |
11 | *does* have a TSC2005 at this address.) The TSC2005 supports the | ||
12 | 24-bit accesses which the guest driver makes, and the TSC210x does | ||
13 | not (that is, our TSC210x emulation is not missing support for a word | ||
14 | width the hardware can handle). It's not clear whether the problem | ||
15 | here is that the guest kernel incorrectly thinks the n800 has the | ||
16 | same device at this SPI bus address as the n810, or that QEMU's n810 | ||
17 | board model doesn't get the SPI devices right. At this late date | ||
18 | there no longer appears to be any reliable information on the web | ||
19 | about the hardware behaviour, but I am inclined to think this is a | ||
20 | guest kernel bug. In any case, we prefer not to abort QEMU for | ||
21 | guest-triggerable conditions, so logging the error is the right thing | ||
22 | to do. | ||
11 | 23 | ||
12 | It's not clear why these tests are failing like this, but intermittent | 24 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/736 |
13 | failures make CI and merge testing awkward, so disable running them | 25 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | unless a developer specifically sets QEMU_TEST_FLAKY_RNG_TESTS when | 26 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
15 | running the test suite, until we work out the cause. | 27 | Message-id: 20220221140750.514557-1-peter.maydell@linaro.org |
28 | --- | ||
29 | hw/input/tsc210x.c | 8 ++++++-- | ||
30 | 1 file changed, 6 insertions(+), 2 deletions(-) | ||
16 | 31 | ||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 32 | diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c |
18 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
19 | Message-id: 20201102152454.8287-1-peter.maydell@linaro.org | ||
20 | Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com> | ||
21 | --- | ||
22 | tests/qtest/npcm7xx_rng-test.c | 14 ++++++++++---- | ||
23 | 1 file changed, 10 insertions(+), 4 deletions(-) | ||
24 | |||
25 | diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | 33 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/tests/qtest/npcm7xx_rng-test.c | 34 | --- a/hw/input/tsc210x.c |
28 | +++ b/tests/qtest/npcm7xx_rng-test.c | 35 | +++ b/hw/input/tsc210x.c |
29 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) | 36 | @@ -XXX,XX +XXX,XX @@ |
30 | 37 | #include "hw/hw.h" | |
31 | qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable); | 38 | #include "audio/audio.h" |
32 | qtest_add_func("npcm7xx_rng/rosel", test_rosel); | 39 | #include "qemu/timer.h" |
33 | - qtest_add_func("npcm7xx_rng/continuous/monobit", test_continuous_monobit); | 40 | +#include "qemu/log.h" |
34 | - qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs); | 41 | #include "sysemu/reset.h" |
35 | - qtest_add_func("npcm7xx_rng/first_byte/monobit", test_first_byte_monobit); | 42 | #include "ui/console.h" |
36 | - qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs); | 43 | #include "hw/arm/omap.h" /* For I2SCodec */ |
37 | + /* | 44 | @@ -XXX,XX +XXX,XX @@ uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len) |
38 | + * These tests fail intermittently; only run them on explicit | 45 | TSC210xState *s = opaque; |
39 | + * request until we figure out why. | 46 | uint32_t ret = 0; |
40 | + */ | 47 | |
41 | + if (getenv("QEMU_TEST_FLAKY_RNG_TESTS")) { | 48 | - if (len != 16) |
42 | + qtest_add_func("npcm7xx_rng/continuous/monobit", test_continuous_monobit); | 49 | - hw_error("%s: FIXME: bad SPI word width %i\n", __func__, len); |
43 | + qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs); | 50 | + if (len != 16) { |
44 | + qtest_add_func("npcm7xx_rng/first_byte/monobit", test_first_byte_monobit); | 51 | + qemu_log_mask(LOG_GUEST_ERROR, |
45 | + qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs); | 52 | + "%s: bad SPI word width %i\n", __func__, len); |
53 | + return 0; | ||
46 | + } | 54 | + } |
47 | 55 | ||
48 | qtest_start("-machine npcm750-evb"); | 56 | /* TODO: sequential reads etc - how do we make sure the host doesn't |
49 | ret = g_test_run(); | 57 | * unintentionally read out a conversion result from a register while |
50 | -- | 58 | -- |
51 | 2.20.1 | 59 | 2.25.1 |
52 | 60 | ||
53 | 61 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Patrick Venture <venture@google.com> |
---|---|---|---|
2 | 2 | ||
3 | We can then use this to improve VMOV (scalar to gp) and | 3 | Previously this device created N subdevices which each owned an i2c bus. |
4 | VMOV (gp to scalar) so that we simply perform the memory | 4 | Now this device simply owns the N i2c busses directly. |
5 | operation that we wanted, rather than inserting or | ||
6 | extracting from a 32-bit quantity. | ||
7 | 5 | ||
8 | These were the last uses of neon_load/store_reg, so remove them. | 6 | Tested: Verified devices behind mux are still accessible via qmp and i2c |
7 | from within an arm32 SoC. | ||
9 | 8 | ||
10 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Reviewed-by: Hao Wu <wuhaotsh@google.com> |
11 | Message-id: 20201030022618.785675-7-richard.henderson@linaro.org | 10 | Signed-off-by: Patrick Venture <venture@google.com> |
12 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
12 | Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
13 | Message-id: 20220202164533.1283668-1-venture@google.com | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | --- | 15 | --- |
15 | target/arm/translate.c | 50 +++++++++++++----------- | 16 | hw/i2c/i2c_mux_pca954x.c | 77 +++++++--------------------------------- |
16 | target/arm/translate-vfp.c.inc | 71 +++++----------------------------- | 17 | 1 file changed, 13 insertions(+), 64 deletions(-) |
17 | 2 files changed, 37 insertions(+), 84 deletions(-) | ||
18 | 18 | ||
19 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 19 | diff --git a/hw/i2c/i2c_mux_pca954x.c b/hw/i2c/i2c_mux_pca954x.c |
20 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/translate.c | 21 | --- a/hw/i2c/i2c_mux_pca954x.c |
22 | +++ b/target/arm/translate.c | 22 | +++ b/hw/i2c/i2c_mux_pca954x.c |
23 | @@ -XXX,XX +XXX,XX @@ static long neon_full_reg_offset(unsigned reg) | 23 | @@ -XXX,XX +XXX,XX @@ |
24 | * Return the offset of a 2**SIZE piece of a NEON register, at index ELE, | 24 | #define PCA9548_CHANNEL_COUNT 8 |
25 | * where 0 is the least significant end of the register. | 25 | #define PCA9546_CHANNEL_COUNT 4 |
26 | */ | 26 | |
27 | -static long neon_element_offset(int reg, int element, MemOp size) | 27 | -/* |
28 | +static long neon_element_offset(int reg, int element, MemOp memop) | 28 | - * struct Pca954xChannel - The i2c mux device will have N of these states |
29 | { | 29 | - * that own the i2c channel bus. |
30 | - int element_size = 1 << size; | 30 | - * @bus: The owned channel bus. |
31 | + int element_size = 1 << (memop & MO_SIZE); | 31 | - * @enabled: Is this channel active? |
32 | int ofs = element * element_size; | 32 | - */ |
33 | #ifdef HOST_WORDS_BIGENDIAN | 33 | -typedef struct Pca954xChannel { |
34 | /* | 34 | - SysBusDevice parent; |
35 | @@ -XXX,XX +XXX,XX @@ static long vfp_reg_offset(bool dp, unsigned reg) | 35 | - |
36 | - I2CBus *bus; | ||
37 | - | ||
38 | - bool enabled; | ||
39 | -} Pca954xChannel; | ||
40 | - | ||
41 | -#define TYPE_PCA954X_CHANNEL "pca954x-channel" | ||
42 | -#define PCA954X_CHANNEL(obj) \ | ||
43 | - OBJECT_CHECK(Pca954xChannel, (obj), TYPE_PCA954X_CHANNEL) | ||
44 | - | ||
45 | /* | ||
46 | * struct Pca954xState - The pca954x state object. | ||
47 | * @control: The value written to the mux control. | ||
48 | @@ -XXX,XX +XXX,XX @@ typedef struct Pca954xState { | ||
49 | |||
50 | uint8_t control; | ||
51 | |||
52 | - /* The channel i2c buses. */ | ||
53 | - Pca954xChannel channel[PCA9548_CHANNEL_COUNT]; | ||
54 | + bool enabled[PCA9548_CHANNEL_COUNT]; | ||
55 | + I2CBus *bus[PCA9548_CHANNEL_COUNT]; | ||
56 | } Pca954xState; | ||
57 | |||
58 | /* | ||
59 | @@ -XXX,XX +XXX,XX @@ static bool pca954x_match(I2CSlave *candidate, uint8_t address, | ||
60 | } | ||
61 | |||
62 | for (i = 0; i < mc->nchans; i++) { | ||
63 | - if (!mux->channel[i].enabled) { | ||
64 | + if (!mux->enabled[i]) { | ||
65 | continue; | ||
66 | } | ||
67 | |||
68 | - if (i2c_scan_bus(mux->channel[i].bus, address, broadcast, | ||
69 | + if (i2c_scan_bus(mux->bus[i], address, broadcast, | ||
70 | current_devs)) { | ||
71 | if (!broadcast) { | ||
72 | return true; | ||
73 | @@ -XXX,XX +XXX,XX @@ static void pca954x_enable_channel(Pca954xState *s, uint8_t enable_mask) | ||
74 | */ | ||
75 | for (i = 0; i < mc->nchans; i++) { | ||
76 | if (enable_mask & (1 << i)) { | ||
77 | - s->channel[i].enabled = true; | ||
78 | + s->enabled[i] = true; | ||
79 | } else { | ||
80 | - s->channel[i].enabled = false; | ||
81 | + s->enabled[i] = false; | ||
82 | } | ||
36 | } | 83 | } |
37 | } | 84 | } |
38 | 85 | @@ -XXX,XX +XXX,XX @@ I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel) | |
39 | -static TCGv_i32 neon_load_reg(int reg, int pass) | 86 | Pca954xState *pca954x = PCA954X(mux); |
40 | -{ | 87 | |
41 | - TCGv_i32 tmp = tcg_temp_new_i32(); | 88 | g_assert(channel < pc->nchans); |
42 | - tcg_gen_ld_i32(tmp, cpu_env, neon_element_offset(reg, pass, MO_32)); | 89 | - return I2C_BUS(qdev_get_child_bus(DEVICE(&pca954x->channel[channel]), |
43 | - return tmp; | 90 | - "i2c-bus")); |
44 | -} | 91 | -} |
45 | - | 92 | - |
46 | -static void neon_store_reg(int reg, int pass, TCGv_i32 var) | 93 | -static void pca954x_channel_init(Object *obj) |
47 | -{ | 94 | -{ |
48 | - tcg_gen_st_i32(var, cpu_env, neon_element_offset(reg, pass, MO_32)); | 95 | - Pca954xChannel *s = PCA954X_CHANNEL(obj); |
49 | - tcg_temp_free_i32(var); | 96 | - s->bus = i2c_init_bus(DEVICE(s), "i2c-bus"); |
97 | - | ||
98 | - /* Start all channels as disabled. */ | ||
99 | - s->enabled = false; | ||
50 | -} | 100 | -} |
51 | - | 101 | - |
52 | static inline void neon_load_reg64(TCGv_i64 var, int reg) | 102 | -static void pca954x_channel_class_init(ObjectClass *klass, void *data) |
103 | -{ | ||
104 | - DeviceClass *dc = DEVICE_CLASS(klass); | ||
105 | - dc->desc = "Pca954x Channel"; | ||
106 | + return pca954x->bus[channel]; | ||
107 | } | ||
108 | |||
109 | static void pca9546_class_init(ObjectClass *klass, void *data) | ||
110 | @@ -XXX,XX +XXX,XX @@ static void pca9548_class_init(ObjectClass *klass, void *data) | ||
111 | s->nchans = PCA9548_CHANNEL_COUNT; | ||
112 | } | ||
113 | |||
114 | -static void pca954x_realize(DeviceState *dev, Error **errp) | ||
115 | -{ | ||
116 | - Pca954xState *s = PCA954X(dev); | ||
117 | - Pca954xClass *c = PCA954X_GET_CLASS(s); | ||
118 | - int i; | ||
119 | - | ||
120 | - /* SMBus modules. Cannot fail. */ | ||
121 | - for (i = 0; i < c->nchans; i++) { | ||
122 | - sysbus_realize(SYS_BUS_DEVICE(&s->channel[i]), &error_abort); | ||
123 | - } | ||
124 | -} | ||
125 | - | ||
126 | static void pca954x_init(Object *obj) | ||
53 | { | 127 | { |
54 | tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); | 128 | Pca954xState *s = PCA954X(obj); |
55 | @@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg32(TCGv_i32 var, int reg) | 129 | Pca954xClass *c = PCA954X_GET_CLASS(obj); |
56 | tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 130 | int i; |
57 | } | 131 | |
58 | 132 | - /* Only initialize the children we expect. */ | |
59 | -static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp size) | 133 | + /* SMBus modules. Cannot fail. */ |
60 | +static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | 134 | for (i = 0; i < c->nchans; i++) { |
61 | { | 135 | - object_initialize_child(obj, "channel[*]", &s->channel[i], |
62 | - long off = neon_element_offset(reg, ele, size); | 136 | - TYPE_PCA954X_CHANNEL); |
63 | + long off = neon_element_offset(reg, ele, memop); | 137 | + g_autofree gchar *bus_name = g_strdup_printf("i2c.%d", i); |
64 | 138 | + | |
65 | - switch (size) { | 139 | + /* start all channels as disabled. */ |
66 | - case MO_32: | 140 | + s->enabled[i] = false; |
67 | + switch (memop) { | 141 | + s->bus[i] = i2c_init_bus(DEVICE(s), bus_name); |
68 | + case MO_SB: | ||
69 | + tcg_gen_ld8s_i32(dest, cpu_env, off); | ||
70 | + break; | ||
71 | + case MO_UB: | ||
72 | + tcg_gen_ld8u_i32(dest, cpu_env, off); | ||
73 | + break; | ||
74 | + case MO_SW: | ||
75 | + tcg_gen_ld16s_i32(dest, cpu_env, off); | ||
76 | + break; | ||
77 | + case MO_UW: | ||
78 | + tcg_gen_ld16u_i32(dest, cpu_env, off); | ||
79 | + break; | ||
80 | + case MO_UL: | ||
81 | + case MO_SL: | ||
82 | tcg_gen_ld_i32(dest, cpu_env, off); | ||
83 | break; | ||
84 | default: | ||
85 | @@ -XXX,XX +XXX,XX @@ static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp size) | ||
86 | } | 142 | } |
87 | } | 143 | } |
88 | 144 | ||
89 | -static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp size) | 145 | @@ -XXX,XX +XXX,XX @@ static void pca954x_class_init(ObjectClass *klass, void *data) |
90 | +static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | 146 | rc->phases.enter = pca954x_enter_reset; |
91 | { | 147 | |
92 | - long off = neon_element_offset(reg, ele, size); | 148 | dc->desc = "Pca954x i2c-mux"; |
93 | + long off = neon_element_offset(reg, ele, memop); | 149 | - dc->realize = pca954x_realize; |
94 | 150 | ||
95 | - switch (size) { | 151 | k->write_data = pca954x_write_data; |
96 | + switch (memop) { | 152 | k->receive_byte = pca954x_read_byte; |
97 | + case MO_8: | 153 | @@ -XXX,XX +XXX,XX @@ static const TypeInfo pca954x_info[] = { |
98 | + tcg_gen_st8_i32(src, cpu_env, off); | 154 | .parent = TYPE_PCA954X, |
99 | + break; | 155 | .class_init = pca9548_class_init, |
100 | + case MO_16: | 156 | }, |
101 | + tcg_gen_st16_i32(src, cpu_env, off); | 157 | - { |
102 | + break; | 158 | - .name = TYPE_PCA954X_CHANNEL, |
103 | case MO_32: | 159 | - .parent = TYPE_SYS_BUS_DEVICE, |
104 | tcg_gen_st_i32(src, cpu_env, off); | 160 | - .class_init = pca954x_channel_class_init, |
105 | break; | 161 | - .instance_size = sizeof(Pca954xChannel), |
106 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | 162 | - .instance_init = pca954x_channel_init, |
107 | index XXXXXXX..XXXXXXX 100644 | ||
108 | --- a/target/arm/translate-vfp.c.inc | ||
109 | +++ b/target/arm/translate-vfp.c.inc | ||
110 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) | ||
111 | { | ||
112 | /* VMOV scalar to general purpose register */ | ||
113 | TCGv_i32 tmp; | ||
114 | - int pass; | ||
115 | - uint32_t offset; | ||
116 | |||
117 | - /* SIZE == 2 is a VFP instruction; otherwise NEON. */ | ||
118 | - if (a->size == 2 | ||
119 | + /* SIZE == MO_32 is a VFP instruction; otherwise NEON. */ | ||
120 | + if (a->size == MO_32 | ||
121 | ? !dc_isar_feature(aa32_fpsp_v2, s) | ||
122 | : !arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
123 | return false; | ||
124 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | - offset = a->index << a->size; | ||
129 | - pass = extract32(offset, 2, 1); | ||
130 | - offset = extract32(offset, 0, 2) * 8; | ||
131 | - | ||
132 | if (!vfp_access_check(s)) { | ||
133 | return true; | ||
134 | } | ||
135 | |||
136 | - tmp = neon_load_reg(a->vn, pass); | ||
137 | - switch (a->size) { | ||
138 | - case 0: | ||
139 | - if (offset) { | ||
140 | - tcg_gen_shri_i32(tmp, tmp, offset); | ||
141 | - } | ||
142 | - if (a->u) { | ||
143 | - gen_uxtb(tmp); | ||
144 | - } else { | ||
145 | - gen_sxtb(tmp); | ||
146 | - } | ||
147 | - break; | ||
148 | - case 1: | ||
149 | - if (a->u) { | ||
150 | - if (offset) { | ||
151 | - tcg_gen_shri_i32(tmp, tmp, 16); | ||
152 | - } else { | ||
153 | - gen_uxth(tmp); | ||
154 | - } | ||
155 | - } else { | ||
156 | - if (offset) { | ||
157 | - tcg_gen_sari_i32(tmp, tmp, 16); | ||
158 | - } else { | ||
159 | - gen_sxth(tmp); | ||
160 | - } | ||
161 | - } | ||
162 | - break; | ||
163 | - case 2: | ||
164 | - break; | ||
165 | - } | 163 | - } |
166 | + tmp = tcg_temp_new_i32(); | 164 | }; |
167 | + read_neon_element32(tmp, a->vn, a->index, a->size | (a->u ? 0 : MO_SIGN)); | 165 | |
168 | store_reg(s, a->rt, tmp); | 166 | DEFINE_TYPES(pca954x_info) |
169 | |||
170 | return true; | ||
171 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a) | ||
172 | static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) | ||
173 | { | ||
174 | /* VMOV general purpose register to scalar */ | ||
175 | - TCGv_i32 tmp, tmp2; | ||
176 | - int pass; | ||
177 | - uint32_t offset; | ||
178 | + TCGv_i32 tmp; | ||
179 | |||
180 | - /* SIZE == 2 is a VFP instruction; otherwise NEON. */ | ||
181 | - if (a->size == 2 | ||
182 | + /* SIZE == MO_32 is a VFP instruction; otherwise NEON. */ | ||
183 | + if (a->size == MO_32 | ||
184 | ? !dc_isar_feature(aa32_fpsp_v2, s) | ||
185 | : !arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
186 | return false; | ||
187 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a) | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | - offset = a->index << a->size; | ||
192 | - pass = extract32(offset, 2, 1); | ||
193 | - offset = extract32(offset, 0, 2) * 8; | ||
194 | - | ||
195 | if (!vfp_access_check(s)) { | ||
196 | return true; | ||
197 | } | ||
198 | |||
199 | tmp = load_reg(s, a->rt); | ||
200 | - switch (a->size) { | ||
201 | - case 0: | ||
202 | - tmp2 = neon_load_reg(a->vn, pass); | ||
203 | - tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8); | ||
204 | - tcg_temp_free_i32(tmp2); | ||
205 | - break; | ||
206 | - case 1: | ||
207 | - tmp2 = neon_load_reg(a->vn, pass); | ||
208 | - tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16); | ||
209 | - tcg_temp_free_i32(tmp2); | ||
210 | - break; | ||
211 | - case 2: | ||
212 | - break; | ||
213 | - } | ||
214 | - neon_store_reg(a->vn, pass, tmp); | ||
215 | + write_neon_element32(tmp, a->vn, a->index, a->size); | ||
216 | + tcg_temp_free_i32(tmp); | ||
217 | |||
218 | return true; | ||
219 | } | ||
220 | -- | 167 | -- |
221 | 2.20.1 | 168 | 2.25.1 |
222 | 169 | ||
223 | 170 | diff view generated by jsdifflib |
1 | From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | 1 | From: Akihiko Odaki <akihiko.odaki@gmail.com> |
---|---|---|---|
2 | 2 | ||
3 | When booting a CPU with EL3 using the -kernel flag, set up CPTR_EL3 so | 3 | Support the latest PSCI on TCG and HVF. A 64-bit function called from |
4 | that SVE will not trap to EL3. | 4 | AArch32 now returns NOT_SUPPORTED, which is necessary to adhere to SMC |
5 | Calling Convention 1.0. It is still not compliant with SMCCC 1.3 since | ||
6 | they do not implement mandatory functions. | ||
5 | 7 | ||
6 | Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | 8 | Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> |
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Message-id: 20220213035753.34577-1-akihiko.odaki@gmail.com |
8 | Message-id: 20201030151541.11976-1-remi@remlab.net | 10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
11 | [PMM: update MISMATCH_CHECK checks on PSCI_VERSION macros to match] | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 13 | --- |
11 | hw/arm/boot.c | 3 +++ | 14 | target/arm/kvm-consts.h | 13 +++++++++---- |
12 | 1 file changed, 3 insertions(+) | 15 | hw/arm/boot.c | 12 +++++++++--- |
16 | target/arm/cpu.c | 5 +++-- | ||
17 | target/arm/hvf/hvf.c | 27 ++++++++++++++++++++++++++- | ||
18 | target/arm/kvm64.c | 2 +- | ||
19 | target/arm/psci.c | 35 ++++++++++++++++++++++++++++++++--- | ||
20 | 6 files changed, 80 insertions(+), 14 deletions(-) | ||
13 | 21 | ||
22 | diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/target/arm/kvm-consts.h | ||
25 | +++ b/target/arm/kvm-consts.h | ||
26 | @@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_0_1_FN_MIGRATE, KVM_PSCI_FN_MIGRATE); | ||
27 | #define QEMU_PSCI_0_2_FN64_AFFINITY_INFO QEMU_PSCI_0_2_FN64(4) | ||
28 | #define QEMU_PSCI_0_2_FN64_MIGRATE QEMU_PSCI_0_2_FN64(5) | ||
29 | |||
30 | +#define QEMU_PSCI_1_0_FN_PSCI_FEATURES QEMU_PSCI_0_2_FN(10) | ||
31 | + | ||
32 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_SUSPEND, PSCI_0_2_FN_CPU_SUSPEND); | ||
33 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_OFF, PSCI_0_2_FN_CPU_OFF); | ||
34 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_ON, PSCI_0_2_FN_CPU_ON); | ||
35 | @@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_0_2_FN_MIGRATE, PSCI_0_2_FN_MIGRATE); | ||
36 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_SUSPEND, PSCI_0_2_FN64_CPU_SUSPEND); | ||
37 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_ON, PSCI_0_2_FN64_CPU_ON); | ||
38 | MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_MIGRATE, PSCI_0_2_FN64_MIGRATE); | ||
39 | +MISMATCH_CHECK(QEMU_PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_PSCI_FEATURES); | ||
40 | |||
41 | /* PSCI v0.2 return values used by TCG emulation of PSCI */ | ||
42 | |||
43 | /* No Trusted OS migration to worry about when offlining CPUs */ | ||
44 | #define QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED 2 | ||
45 | |||
46 | -/* We implement version 0.2 only */ | ||
47 | -#define QEMU_PSCI_0_2_RET_VERSION_0_2 2 | ||
48 | +#define QEMU_PSCI_VERSION_0_1 0x00001 | ||
49 | +#define QEMU_PSCI_VERSION_0_2 0x00002 | ||
50 | +#define QEMU_PSCI_VERSION_1_1 0x10001 | ||
51 | |||
52 | MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP); | ||
53 | -MISMATCH_CHECK(QEMU_PSCI_0_2_RET_VERSION_0_2, | ||
54 | - (PSCI_VERSION_MAJOR(0) | PSCI_VERSION_MINOR(2))); | ||
55 | +/* We don't bother to check every possible version value */ | ||
56 | +MISMATCH_CHECK(QEMU_PSCI_VERSION_0_2, PSCI_VERSION(0, 2)); | ||
57 | +MISMATCH_CHECK(QEMU_PSCI_VERSION_1_1, PSCI_VERSION(1, 1)); | ||
58 | |||
59 | /* PSCI return values (inclusive of all PSCI versions) */ | ||
60 | #define QEMU_PSCI_RET_SUCCESS 0 | ||
14 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c | 61 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c |
15 | index XXXXXXX..XXXXXXX 100644 | 62 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/arm/boot.c | 63 | --- a/hw/arm/boot.c |
17 | +++ b/hw/arm/boot.c | 64 | +++ b/hw/arm/boot.c |
18 | @@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque) | 65 | @@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt) |
19 | if (cpu_isar_feature(aa64_mte, cpu)) { | 66 | } |
20 | env->cp15.scr_el3 |= SCR_ATA; | 67 | |
21 | } | 68 | qemu_fdt_add_subnode(fdt, "/psci"); |
22 | + if (cpu_isar_feature(aa64_sve, cpu)) { | 69 | - if (armcpu->psci_version == 2) { |
23 | + env->cp15.cptr_el[3] |= CPTR_EZ; | 70 | - const char comp[] = "arm,psci-0.2\0arm,psci"; |
24 | + } | 71 | - qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); |
25 | /* AArch64 kernels never boot in secure mode */ | 72 | + if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2 || |
26 | assert(!info->secure_boot); | 73 | + armcpu->psci_version == QEMU_PSCI_VERSION_1_1) { |
27 | /* This hook is only supported for AArch32 currently: | 74 | + if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2) { |
75 | + const char comp[] = "arm,psci-0.2\0arm,psci"; | ||
76 | + qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); | ||
77 | + } else { | ||
78 | + const char comp[] = "arm,psci-1.0\0arm,psci-0.2\0arm,psci"; | ||
79 | + qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); | ||
80 | + } | ||
81 | |||
82 | cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF; | ||
83 | if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) { | ||
84 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c | ||
85 | index XXXXXXX..XXXXXXX 100644 | ||
86 | --- a/target/arm/cpu.c | ||
87 | +++ b/target/arm/cpu.c | ||
88 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj) | ||
89 | * picky DTB consumer will also provide a helpful error message. | ||
90 | */ | ||
91 | cpu->dtb_compatible = "qemu,unknown"; | ||
92 | - cpu->psci_version = 1; /* By default assume PSCI v0.1 */ | ||
93 | + cpu->psci_version = QEMU_PSCI_VERSION_0_1; /* By default assume PSCI v0.1 */ | ||
94 | cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; | ||
95 | |||
96 | if (tcg_enabled() || hvf_enabled()) { | ||
97 | - cpu->psci_version = 2; /* TCG and HVF implement PSCI 0.2 */ | ||
98 | + /* TCG and HVF implement PSCI 1.1 */ | ||
99 | + cpu->psci_version = QEMU_PSCI_VERSION_1_1; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c | ||
104 | index XXXXXXX..XXXXXXX 100644 | ||
105 | --- a/target/arm/hvf/hvf.c | ||
106 | +++ b/target/arm/hvf/hvf.c | ||
107 | @@ -XXX,XX +XXX,XX @@ static bool hvf_handle_psci_call(CPUState *cpu) | ||
108 | |||
109 | switch (param[0]) { | ||
110 | case QEMU_PSCI_0_2_FN_PSCI_VERSION: | ||
111 | - ret = QEMU_PSCI_0_2_RET_VERSION_0_2; | ||
112 | + ret = QEMU_PSCI_VERSION_1_1; | ||
113 | break; | ||
114 | case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: | ||
115 | ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ | ||
116 | @@ -XXX,XX +XXX,XX @@ static bool hvf_handle_psci_call(CPUState *cpu) | ||
117 | case QEMU_PSCI_0_2_FN_MIGRATE: | ||
118 | ret = QEMU_PSCI_RET_NOT_SUPPORTED; | ||
119 | break; | ||
120 | + case QEMU_PSCI_1_0_FN_PSCI_FEATURES: | ||
121 | + switch (param[1]) { | ||
122 | + case QEMU_PSCI_0_2_FN_PSCI_VERSION: | ||
123 | + case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: | ||
124 | + case QEMU_PSCI_0_2_FN_AFFINITY_INFO: | ||
125 | + case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: | ||
126 | + case QEMU_PSCI_0_2_FN_SYSTEM_RESET: | ||
127 | + case QEMU_PSCI_0_2_FN_SYSTEM_OFF: | ||
128 | + case QEMU_PSCI_0_1_FN_CPU_ON: | ||
129 | + case QEMU_PSCI_0_2_FN_CPU_ON: | ||
130 | + case QEMU_PSCI_0_2_FN64_CPU_ON: | ||
131 | + case QEMU_PSCI_0_1_FN_CPU_OFF: | ||
132 | + case QEMU_PSCI_0_2_FN_CPU_OFF: | ||
133 | + case QEMU_PSCI_0_1_FN_CPU_SUSPEND: | ||
134 | + case QEMU_PSCI_0_2_FN_CPU_SUSPEND: | ||
135 | + case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: | ||
136 | + case QEMU_PSCI_1_0_FN_PSCI_FEATURES: | ||
137 | + ret = 0; | ||
138 | + break; | ||
139 | + case QEMU_PSCI_0_1_FN_MIGRATE: | ||
140 | + case QEMU_PSCI_0_2_FN_MIGRATE: | ||
141 | + default: | ||
142 | + ret = QEMU_PSCI_RET_NOT_SUPPORTED; | ||
143 | + } | ||
144 | + break; | ||
145 | default: | ||
146 | return false; | ||
147 | } | ||
148 | diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c | ||
149 | index XXXXXXX..XXXXXXX 100644 | ||
150 | --- a/target/arm/kvm64.c | ||
151 | +++ b/target/arm/kvm64.c | ||
152 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs) | ||
153 | cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF; | ||
154 | } | ||
155 | if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) { | ||
156 | - cpu->psci_version = 2; | ||
157 | + cpu->psci_version = QEMU_PSCI_VERSION_0_2; | ||
158 | cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2; | ||
159 | } | ||
160 | if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { | ||
161 | diff --git a/target/arm/psci.c b/target/arm/psci.c | ||
162 | index XXXXXXX..XXXXXXX 100644 | ||
163 | --- a/target/arm/psci.c | ||
164 | +++ b/target/arm/psci.c | ||
165 | @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) | ||
166 | { | ||
167 | /* | ||
168 | * This function partially implements the logic for dispatching Power State | ||
169 | - * Coordination Interface (PSCI) calls (as described in ARM DEN 0022B.b), | ||
170 | + * Coordination Interface (PSCI) calls (as described in ARM DEN 0022D.b), | ||
171 | * to the extent required for bringing up and taking down secondary cores, | ||
172 | * and for handling reset and poweroff requests. | ||
173 | * Additional information about the calling convention used is available in | ||
174 | @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) | ||
175 | } | ||
176 | |||
177 | if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) { | ||
178 | - ret = QEMU_PSCI_RET_INVALID_PARAMS; | ||
179 | + ret = QEMU_PSCI_RET_NOT_SUPPORTED; | ||
180 | goto err; | ||
181 | } | ||
182 | |||
183 | @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) | ||
184 | ARMCPU *target_cpu; | ||
185 | |||
186 | case QEMU_PSCI_0_2_FN_PSCI_VERSION: | ||
187 | - ret = QEMU_PSCI_0_2_RET_VERSION_0_2; | ||
188 | + ret = QEMU_PSCI_VERSION_1_1; | ||
189 | break; | ||
190 | case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: | ||
191 | ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ | ||
192 | @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) | ||
193 | } | ||
194 | helper_wfi(env, 4); | ||
195 | break; | ||
196 | + case QEMU_PSCI_1_0_FN_PSCI_FEATURES: | ||
197 | + switch (param[1]) { | ||
198 | + case QEMU_PSCI_0_2_FN_PSCI_VERSION: | ||
199 | + case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: | ||
200 | + case QEMU_PSCI_0_2_FN_AFFINITY_INFO: | ||
201 | + case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: | ||
202 | + case QEMU_PSCI_0_2_FN_SYSTEM_RESET: | ||
203 | + case QEMU_PSCI_0_2_FN_SYSTEM_OFF: | ||
204 | + case QEMU_PSCI_0_1_FN_CPU_ON: | ||
205 | + case QEMU_PSCI_0_2_FN_CPU_ON: | ||
206 | + case QEMU_PSCI_0_2_FN64_CPU_ON: | ||
207 | + case QEMU_PSCI_0_1_FN_CPU_OFF: | ||
208 | + case QEMU_PSCI_0_2_FN_CPU_OFF: | ||
209 | + case QEMU_PSCI_0_1_FN_CPU_SUSPEND: | ||
210 | + case QEMU_PSCI_0_2_FN_CPU_SUSPEND: | ||
211 | + case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: | ||
212 | + case QEMU_PSCI_1_0_FN_PSCI_FEATURES: | ||
213 | + if (!(param[1] & QEMU_PSCI_0_2_64BIT) || is_a64(env)) { | ||
214 | + ret = 0; | ||
215 | + break; | ||
216 | + } | ||
217 | + /* fallthrough */ | ||
218 | + case QEMU_PSCI_0_1_FN_MIGRATE: | ||
219 | + case QEMU_PSCI_0_2_FN_MIGRATE: | ||
220 | + default: | ||
221 | + ret = QEMU_PSCI_RET_NOT_SUPPORTED; | ||
222 | + break; | ||
223 | + } | ||
224 | + break; | ||
225 | case QEMU_PSCI_0_1_FN_MIGRATE: | ||
226 | case QEMU_PSCI_0_2_FN_MIGRATE: | ||
227 | default: | ||
28 | -- | 228 | -- |
29 | 2.20.1 | 229 | 2.25.1 |
30 | |||
31 | diff view generated by jsdifflib |
1 | From: AlexChen <alex.chen@huawei.com> | 1 | From: Wentao_Liang <Wentao_Liang_g@163.com> |
---|---|---|---|
2 | 2 | ||
3 | In exynos4210_fimd_update(), the pointer s is dereferinced before | 3 | handle_simd_shift_fpint_conv() was accidentally freeing the TCG |
4 | being check if it is valid, which may lead to NULL pointer dereference. | 4 | temporary tcg_fpstatus too early, before the last use of it. Move |
5 | So move the assignment to global_width after checking that the s is valid. | 5 | the free down to where it belongs. |
6 | 6 | ||
7 | Reported-by: Euler Robot <euler.robot@huawei.com> | 7 | Signed-off-by: Wentao_Liang <Wentao_Liang_g@163.com> |
8 | Signed-off-by: Alex Chen <alex.chen@huawei.com> | 8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
9 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | 9 | [PMM: cleaned up commit message] |
10 | Message-id: 5F9F8D88.9030102@huawei.com | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
12 | --- | 11 | --- |
13 | hw/display/exynos4210_fimd.c | 4 +++- | 12 | target/arm/translate-a64.c | 2 +- |
14 | 1 file changed, 3 insertions(+), 1 deletion(-) | 13 | 1 file changed, 1 insertion(+), 1 deletion(-) |
15 | 14 | ||
16 | diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c | 15 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c |
17 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/hw/display/exynos4210_fimd.c | 17 | --- a/target/arm/translate-a64.c |
19 | +++ b/hw/display/exynos4210_fimd.c | 18 | +++ b/target/arm/translate-a64.c |
20 | @@ -XXX,XX +XXX,XX @@ static void exynos4210_fimd_update(void *opaque) | 19 | @@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar, |
21 | bool blend = false; | 20 | } |
22 | uint8_t *host_fb_addr; | ||
23 | bool is_dirty = false; | ||
24 | - const int global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; | ||
25 | + int global_width; | ||
26 | |||
27 | if (!s || !s->console || !s->enabled || | ||
28 | surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { | ||
29 | return; | ||
30 | } | 21 | } |
31 | + | 22 | |
32 | + global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; | 23 | - tcg_temp_free_ptr(tcg_fpstatus); |
33 | exynos4210_update_resolution(s); | 24 | tcg_temp_free_i32(tcg_shift); |
34 | surface = qemu_console_surface(s->console); | 25 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus); |
26 | + tcg_temp_free_ptr(tcg_fpstatus); | ||
27 | tcg_temp_free_i32(tcg_rmode); | ||
28 | } | ||
35 | 29 | ||
36 | -- | 30 | -- |
37 | 2.20.1 | 31 | 2.25.1 |
38 | |||
39 | diff view generated by jsdifflib |
1 | The kerneldoc script currently emits Sphinx markup for a macro with | 1 | From: Shengtan Mao <stmao@google.com> |
---|---|---|---|
2 | arguments that uses the c:function directive. This is correct for | ||
3 | Sphinx versions earlier than Sphinx 3, where c:macro doesn't allow | ||
4 | documentation of macros with arguments and c:function is not picky | ||
5 | about the syntax of what it is passed. However, in Sphinx 3 the | ||
6 | c:macro directive was enhanced to support macros with arguments, | ||
7 | and c:function was made more picky about what syntax it accepted. | ||
8 | 2 | ||
9 | When kerneldoc is told that it needs to produce output for Sphinx | 3 | Reviewed-by: Hao Wu <wuhaotsh@google.com> |
10 | 3 or later, make it emit c:function only for functions and c:macro | 4 | Reviewed-by: Chris Rauer <crauer@google.com> |
11 | for macros with arguments. We assume that anything with a return | 5 | Signed-off-by: Shengtan Mao <stmao@google.com> |
12 | type is a function and anything without is a macro. | 6 | Signed-off-by: Patrick Venture <venture@google.com> |
7 | Message-id: 20220225174451.192304-1-wuhaotsh@google.com | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | --- | ||
10 | tests/qtest/npcm7xx_sdhci-test.c | 215 +++++++++++++++++++++++++++++++ | ||
11 | tests/qtest/meson.build | 1 + | ||
12 | 2 files changed, 216 insertions(+) | ||
13 | create mode 100644 tests/qtest/npcm7xx_sdhci-test.c | ||
13 | 14 | ||
14 | This fixes the Sphinx error: | 15 | diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c |
15 | 16 | new file mode 100644 | |
16 | /home/petmay01/linaro/qemu-from-laptop/qemu/docs/../include/qom/object.h:155:Error in declarator | 17 | index XXXXXXX..XXXXXXX |
17 | If declarator-id with parameters (e.g., 'void f(int arg)'): | 18 | --- /dev/null |
18 | Invalid C declaration: Expected identifier in nested name. [error at 25] | 19 | +++ b/tests/qtest/npcm7xx_sdhci-test.c |
19 | DECLARE_INSTANCE_CHECKER ( InstanceType, OBJ_NAME, TYPENAME) | 20 | @@ -XXX,XX +XXX,XX @@ |
20 | -------------------------^ | 21 | +/* |
21 | If parenthesis in noptr-declarator (e.g., 'void (*f(int arg))(double)'): | 22 | + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller |
22 | Error in declarator or parameters | 23 | + * |
23 | Invalid C declaration: Expecting "(" in parameters. [error at 39] | 24 | + * Copyright (c) 2022 Google LLC |
24 | DECLARE_INSTANCE_CHECKER ( InstanceType, OBJ_NAME, TYPENAME) | 25 | + * |
25 | ---------------------------------------^ | 26 | + * This program is free software; you can redistribute it and/or modify it |
26 | 27 | + * under the terms of the GNU General Public License as published by the | |
27 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 28 | + * Free Software Foundation; either version 2 of the License, or |
28 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | 29 | + * (at your option) any later version. |
29 | Tested-by: Stefan Hajnoczi <stefanha@redhat.com> | 30 | + * |
30 | Message-id: 20201030174700.7204-2-peter.maydell@linaro.org | 31 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
31 | --- | 32 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
32 | scripts/kernel-doc | 18 +++++++++++++++++- | 33 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
33 | 1 file changed, 17 insertions(+), 1 deletion(-) | 34 | + * for more details. |
34 | 35 | + */ | |
35 | diff --git a/scripts/kernel-doc b/scripts/kernel-doc | 36 | + |
36 | index XXXXXXX..XXXXXXX 100755 | 37 | +#include "qemu/osdep.h" |
37 | --- a/scripts/kernel-doc | 38 | +#include "hw/sd/npcm7xx_sdhci.h" |
38 | +++ b/scripts/kernel-doc | 39 | + |
39 | @@ -XXX,XX +XXX,XX @@ sub output_function_rst(%) { | 40 | +#include "libqos/libqtest.h" |
40 | output_highlight_rst($args{'purpose'}); | 41 | +#include "libqtest-single.h" |
41 | $start = "\n\n**Syntax**\n\n ``"; | 42 | +#include "libqos/sdhci-cmd.h" |
42 | } else { | 43 | + |
43 | - print ".. c:function:: "; | 44 | +#define NPCM7XX_REG_SIZE 0x100 |
44 | + if ((split(/\./, $sphinx_version))[0] >= 3) { | 45 | +#define NPCM7XX_MMC_BA 0xF0842000 |
45 | + # Sphinx 3 and later distinguish macros and functions and | 46 | +#define NPCM7XX_BLK_SIZE 512 |
46 | + # complain if you use c:function with something that's not | 47 | +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) |
47 | + # syntactically valid as a function declaration. | 48 | + |
48 | + # We assume that anything with a return type is a function | 49 | +char *sd_path; |
49 | + # and anything without is a macro. | 50 | + |
50 | + if ($args{'functiontype'} ne "") { | 51 | +static QTestState *setup_sd_card(void) |
51 | + print ".. c:function:: "; | 52 | +{ |
52 | + } else { | 53 | + QTestState *qts = qtest_initf( |
53 | + print ".. c:macro:: "; | 54 | + "-machine kudo-bmc " |
55 | + "-device sd-card,drive=drive0 " | ||
56 | + "-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", | ||
57 | + sd_path); | ||
58 | + | ||
59 | + qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); | ||
60 | + qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, | ||
61 | + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | | ||
62 | + SDHC_CLOCK_INT_EN); | ||
63 | + sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); | ||
64 | + sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x41200000, 0, (41 << 8)); | ||
65 | + sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); | ||
66 | + sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); | ||
67 | + sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x45670000, 0, | ||
68 | + SDHC_SELECT_DESELECT_CARD); | ||
69 | + | ||
70 | + return qts; | ||
71 | +} | ||
72 | + | ||
73 | +static void write_sdread(QTestState *qts, const char *msg) | ||
74 | +{ | ||
75 | + int fd, ret; | ||
76 | + size_t len = strlen(msg); | ||
77 | + char *rmsg = g_malloc(len); | ||
78 | + | ||
79 | + /* write message to sd */ | ||
80 | + fd = open(sd_path, O_WRONLY); | ||
81 | + g_assert(fd >= 0); | ||
82 | + ret = write(fd, msg, len); | ||
83 | + close(fd); | ||
84 | + g_assert(ret == len); | ||
85 | + | ||
86 | + /* read message using sdhci */ | ||
87 | + ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); | ||
88 | + g_assert(ret == len); | ||
89 | + g_assert(!memcmp(rmsg, msg, len)); | ||
90 | + | ||
91 | + g_free(rmsg); | ||
92 | +} | ||
93 | + | ||
94 | +/* Check MMC can read values from sd */ | ||
95 | +static void test_read_sd(void) | ||
96 | +{ | ||
97 | + QTestState *qts = setup_sd_card(); | ||
98 | + | ||
99 | + write_sdread(qts, "hello world"); | ||
100 | + write_sdread(qts, "goodbye"); | ||
101 | + | ||
102 | + qtest_quit(qts); | ||
103 | +} | ||
104 | + | ||
105 | +static void sdwrite_read(QTestState *qts, const char *msg) | ||
106 | +{ | ||
107 | + int fd, ret; | ||
108 | + size_t len = strlen(msg); | ||
109 | + char *rmsg = g_malloc(len); | ||
110 | + | ||
111 | + /* write message using sdhci */ | ||
112 | + sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE); | ||
113 | + | ||
114 | + /* read message from sd */ | ||
115 | + fd = open(sd_path, O_RDONLY); | ||
116 | + g_assert(fd >= 0); | ||
117 | + ret = read(fd, rmsg, len); | ||
118 | + close(fd); | ||
119 | + g_assert(ret == len); | ||
120 | + | ||
121 | + g_assert(!memcmp(rmsg, msg, len)); | ||
122 | + | ||
123 | + g_free(rmsg); | ||
124 | +} | ||
125 | + | ||
126 | +/* Check MMC can write values to sd */ | ||
127 | +static void test_write_sd(void) | ||
128 | +{ | ||
129 | + QTestState *qts = setup_sd_card(); | ||
130 | + | ||
131 | + sdwrite_read(qts, "hello world"); | ||
132 | + sdwrite_read(qts, "goodbye"); | ||
133 | + | ||
134 | + qtest_quit(qts); | ||
135 | +} | ||
136 | + | ||
137 | +/* Check SDHCI has correct default values. */ | ||
138 | +static void test_reset(void) | ||
139 | +{ | ||
140 | + QTestState *qts = qtest_init("-machine kudo-bmc"); | ||
141 | + uint64_t addr = NPCM7XX_MMC_BA; | ||
142 | + uint64_t end_addr = addr + NPCM7XX_REG_SIZE; | ||
143 | + uint16_t prstvals_resets[] = {NPCM7XX_PRSTVALS_0_RESET, | ||
144 | + NPCM7XX_PRSTVALS_1_RESET, | ||
145 | + 0, | ||
146 | + NPCM7XX_PRSTVALS_3_RESET, | ||
147 | + 0, | ||
148 | + 0}; | ||
149 | + int i; | ||
150 | + uint32_t mask; | ||
151 | + | ||
152 | + while (addr < end_addr) { | ||
153 | + switch (addr - NPCM7XX_MMC_BA) { | ||
154 | + case SDHC_PRNSTS: | ||
155 | + /* | ||
156 | + * ignores bits 20 to 24: they are changed when reading registers | ||
157 | + */ | ||
158 | + mask = 0x1f00000; | ||
159 | + g_assert_cmphex(qtest_readl(qts, addr) | mask, ==, | ||
160 | + NPCM7XX_PRSNTS_RESET | mask); | ||
161 | + addr += 4; | ||
162 | + break; | ||
163 | + case SDHC_BLKGAP: | ||
164 | + g_assert_cmphex(qtest_readb(qts, addr), ==, NPCM7XX_BLKGAP_RESET); | ||
165 | + addr += 1; | ||
166 | + break; | ||
167 | + case SDHC_CAPAB: | ||
168 | + g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_CAPAB_RESET); | ||
169 | + addr += 8; | ||
170 | + break; | ||
171 | + case SDHC_MAXCURR: | ||
172 | + g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_MAXCURR_RESET); | ||
173 | + addr += 8; | ||
174 | + break; | ||
175 | + case SDHC_HCVER: | ||
176 | + g_assert_cmphex(qtest_readw(qts, addr), ==, NPCM7XX_HCVER_RESET); | ||
177 | + addr += 2; | ||
178 | + break; | ||
179 | + case NPCM7XX_PRSTVALS: | ||
180 | + for (i = 0; i < NPCM7XX_PRSTVALS_SIZE; ++i) { | ||
181 | + g_assert_cmphex(qtest_readw(qts, addr + 2 * i), ==, | ||
182 | + prstvals_resets[i]); | ||
54 | + } | 183 | + } |
55 | + } else { | 184 | + addr += NPCM7XX_PRSTVALS_SIZE * 2; |
56 | + # Older Sphinx don't support documenting macros that take | 185 | + break; |
57 | + # arguments with c:macro, and don't complain about the use | 186 | + default: |
58 | + # of c:function for this. | 187 | + g_assert_cmphex(qtest_readb(qts, addr), ==, 0); |
59 | + print ".. c:function:: "; | 188 | + addr += 1; |
60 | + } | 189 | + } |
61 | } | 190 | + } |
62 | if ($args{'functiontype'} ne "") { | 191 | + |
63 | $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; | 192 | + qtest_quit(qts); |
193 | +} | ||
194 | + | ||
195 | +static void drive_destroy(void) | ||
196 | +{ | ||
197 | + unlink(sd_path); | ||
198 | + g_free(sd_path); | ||
199 | +} | ||
200 | + | ||
201 | +static void drive_create(void) | ||
202 | +{ | ||
203 | + int fd, ret; | ||
204 | + GError *error = NULL; | ||
205 | + | ||
206 | + /* Create a temporary raw image */ | ||
207 | + fd = g_file_open_tmp("sdhci_XXXXXX", &sd_path, &error); | ||
208 | + if (fd == -1) { | ||
209 | + fprintf(stderr, "unable to create sdhci file: %s\n", error->message); | ||
210 | + g_error_free(error); | ||
211 | + } | ||
212 | + g_assert(sd_path != NULL); | ||
213 | + | ||
214 | + ret = ftruncate(fd, NPCM7XX_TEST_IMAGE_SIZE); | ||
215 | + g_assert_cmpint(ret, ==, 0); | ||
216 | + g_message("%s", sd_path); | ||
217 | + close(fd); | ||
218 | +} | ||
219 | + | ||
220 | +int main(int argc, char **argv) | ||
221 | +{ | ||
222 | + int ret; | ||
223 | + | ||
224 | + drive_create(); | ||
225 | + | ||
226 | + g_test_init(&argc, &argv, NULL); | ||
227 | + | ||
228 | + qtest_add_func("npcm7xx_sdhci/reset", test_reset); | ||
229 | + qtest_add_func("npcm7xx_sdhci/write_sd", test_write_sd); | ||
230 | + qtest_add_func("npcm7xx_sdhci/read_sd", test_read_sd); | ||
231 | + | ||
232 | + ret = g_test_run(); | ||
233 | + drive_destroy(); | ||
234 | + return ret; | ||
235 | +} | ||
236 | diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build | ||
237 | index XXXXXXX..XXXXXXX 100644 | ||
238 | --- a/tests/qtest/meson.build | ||
239 | +++ b/tests/qtest/meson.build | ||
240 | @@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \ | ||
241 | 'npcm7xx_gpio-test', | ||
242 | 'npcm7xx_pwm-test', | ||
243 | 'npcm7xx_rng-test', | ||
244 | + 'npcm7xx_sdhci-test', | ||
245 | 'npcm7xx_smbus-test', | ||
246 | 'npcm7xx_timer-test', | ||
247 | 'npcm7xx_watchdog_timer-test'] + \ | ||
64 | -- | 248 | -- |
65 | 2.20.1 | 249 | 2.25.1 |
66 | |||
67 | diff view generated by jsdifflib |
1 | On some hosts (eg Ubuntu Bionic) pkg-config returns a set of | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | libraries for gio-2.0 which don't actually work when compiling | ||
3 | statically. (Specifically, the returned library string includes | ||
4 | -lmount, but not -lblkid which -lmount depends upon, so linking | ||
5 | fails due to missing symbols.) | ||
6 | 2 | ||
7 | Check that the libraries work, and don't enable gio if they don't, | 3 | Add new macros to manipulate signed fields within the register. |
8 | in the same way we do for gnutls. | ||
9 | 4 | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20220301215958.157011-2-richard.henderson@linaro.org | ||
8 | Suggested-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Message-id: 20200928160402.7961-1-peter.maydell@linaro.org | ||
14 | --- | 11 | --- |
15 | configure | 10 +++++++++- | 12 | include/hw/registerfields.h | 48 ++++++++++++++++++++++++++++++++++++- |
16 | 1 file changed, 9 insertions(+), 1 deletion(-) | 13 | 1 file changed, 47 insertions(+), 1 deletion(-) |
17 | 14 | ||
18 | diff --git a/configure b/configure | 15 | diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h |
19 | index XXXXXXX..XXXXXXX 100755 | 16 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/configure | 17 | --- a/include/hw/registerfields.h |
21 | +++ b/configure | 18 | +++ b/include/hw/registerfields.h |
22 | @@ -XXX,XX +XXX,XX @@ if test "$static" = yes && test "$mingw32" = yes; then | 19 | @@ -XXX,XX +XXX,XX @@ |
23 | fi | 20 | extract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ |
24 | 21 | R_ ## reg ## _ ## field ## _LENGTH) | |
25 | if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then | 22 | |
26 | - gio=yes | 23 | +#define FIELD_SEX8(storage, reg, field) \ |
27 | gio_cflags=$($pkg_config --cflags gio-2.0) | 24 | + sextract8((storage), R_ ## reg ## _ ## field ## _SHIFT, \ |
28 | gio_libs=$($pkg_config --libs gio-2.0) | 25 | + R_ ## reg ## _ ## field ## _LENGTH) |
29 | gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0) | 26 | +#define FIELD_SEX16(storage, reg, field) \ |
30 | if [ ! -x "$gdbus_codegen" ]; then | 27 | + sextract16((storage), R_ ## reg ## _ ## field ## _SHIFT, \ |
31 | gdbus_codegen= | 28 | + R_ ## reg ## _ ## field ## _LENGTH) |
32 | fi | 29 | +#define FIELD_SEX32(storage, reg, field) \ |
33 | + # Check that the libraries actually work -- Ubuntu 18.04 ships | 30 | + sextract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ |
34 | + # with pkg-config --static --libs data for gio-2.0 that is missing | 31 | + R_ ## reg ## _ ## field ## _LENGTH) |
35 | + # -lblkid and will give a link error. | 32 | +#define FIELD_SEX64(storage, reg, field) \ |
36 | + write_c_skeleton | 33 | + sextract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ |
37 | + if compile_prog "" "gio_libs" ; then | 34 | + R_ ## reg ## _ ## field ## _LENGTH) |
38 | + gio=yes | 35 | + |
39 | + else | 36 | /* Extract a field from an array of registers */ |
40 | + gio=no | 37 | #define ARRAY_FIELD_EX32(regs, reg, field) \ |
41 | + fi | 38 | FIELD_EX32((regs)[R_ ## reg], reg, field) |
42 | else | 39 | @@ -XXX,XX +XXX,XX @@ |
43 | gio=no | 40 | _d; }) |
44 | fi | 41 | #define FIELD_DP64(storage, reg, field, val) ({ \ |
42 | struct { \ | ||
43 | - uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
44 | + uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
45 | + } _v = { .v = val }; \ | ||
46 | + uint64_t _d; \ | ||
47 | + _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ | ||
48 | + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ | ||
49 | + _d; }) | ||
50 | + | ||
51 | +#define FIELD_SDP8(storage, reg, field, val) ({ \ | ||
52 | + struct { \ | ||
53 | + signed int v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
54 | + } _v = { .v = val }; \ | ||
55 | + uint8_t _d; \ | ||
56 | + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ | ||
57 | + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ | ||
58 | + _d; }) | ||
59 | +#define FIELD_SDP16(storage, reg, field, val) ({ \ | ||
60 | + struct { \ | ||
61 | + signed int v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
62 | + } _v = { .v = val }; \ | ||
63 | + uint16_t _d; \ | ||
64 | + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ | ||
65 | + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ | ||
66 | + _d; }) | ||
67 | +#define FIELD_SDP32(storage, reg, field, val) ({ \ | ||
68 | + struct { \ | ||
69 | + signed int v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
70 | + } _v = { .v = val }; \ | ||
71 | + uint32_t _d; \ | ||
72 | + _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \ | ||
73 | + R_ ## reg ## _ ## field ## _LENGTH, _v.v); \ | ||
74 | + _d; }) | ||
75 | +#define FIELD_SDP64(storage, reg, field, val) ({ \ | ||
76 | + struct { \ | ||
77 | + int64_t v:R_ ## reg ## _ ## field ## _LENGTH; \ | ||
78 | } _v = { .v = val }; \ | ||
79 | uint64_t _d; \ | ||
80 | _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \ | ||
45 | -- | 81 | -- |
46 | 2.20.1 | 82 | 2.25.1 |
47 | 83 | ||
48 | 84 | diff view generated by jsdifflib |
1 | In arm_v7m_mmu_idx_for_secstate() we get the 'priv' level to pass to | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | armv7m_mmu_idx_for_secstate_and_priv() by calling arm_current_el(). | ||
3 | This is incorrect when the security state being queried is not the | ||
4 | current one, because arm_current_el() uses the current security state | ||
5 | to determine which of the banked CONTROL.nPRIV bits to look at. | ||
6 | The effect was that if (for instance) Secure state was in privileged | ||
7 | mode but Non-Secure was not then we would return the wrong MMU index. | ||
8 | 2 | ||
9 | The only places where we are using this function in a way that could | 3 | Set this as the kernel would, to 48 bits, to keep the computation |
10 | trigger this bug are for the stack loads during a v8M function-return | 4 | of the address space correct for PAuth. |
11 | and for the instruction fetch of a v8M SG insn. | ||
12 | 5 | ||
13 | Fix the bug by expanding out the M-profile version of the | 6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
14 | arm_current_el() logic inline so it can use the passed in secstate | 7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
15 | rather than env->v7m.secure. | 8 | Message-id: 20220301215958.157011-3-richard.henderson@linaro.org |
16 | |||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
18 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
19 | Message-id: 20201022164408.13214-1-peter.maydell@linaro.org | ||
20 | --- | 10 | --- |
21 | target/arm/m_helper.c | 3 ++- | 11 | target/arm/cpu.c | 3 ++- |
22 | 1 file changed, 2 insertions(+), 1 deletion(-) | 12 | 1 file changed, 2 insertions(+), 1 deletion(-) |
23 | 13 | ||
24 | diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c | 14 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c |
25 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/target/arm/m_helper.c | 16 | --- a/target/arm/cpu.c |
27 | +++ b/target/arm/m_helper.c | 17 | +++ b/target/arm/cpu.c |
28 | @@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env, | 18 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev) |
29 | /* Return the MMU index for a v7M CPU in the specified security state */ | 19 | aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1); |
30 | ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate) | 20 | } |
31 | { | 21 | /* |
32 | - bool priv = arm_current_el(env) != 0; | 22 | + * Enable 48-bit address space (TODO: take reserved_va into account). |
33 | + bool priv = arm_v7m_is_handler_mode(env) || | 23 | * Enable TBI0 but not TBI1. |
34 | + !(env->v7m.control[secstate] & 1); | 24 | * Note that this must match useronly_clean_ptr. |
35 | 25 | */ | |
36 | return arm_v7m_mmu_idx_for_secstate_and_priv(env, secstate, priv); | 26 | - env->cp15.tcr_el[1].raw_tcr = (1ULL << 37); |
37 | } | 27 | + env->cp15.tcr_el[1].raw_tcr = 5 | (1ULL << 37); |
28 | |||
29 | /* Enable MTE */ | ||
30 | if (cpu_isar_feature(aa64_mte, cpu)) { | ||
38 | -- | 31 | -- |
39 | 2.20.1 | 32 | 2.25.1 |
40 | |||
41 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | The only uses of this function are for loading VFP | 3 | Without FEAT_LVA, the behaviour of programming an invalid value |
4 | double-precision values, and nothing to do with NEON. | 4 | is IMPLEMENTATION DEFINED. With FEAT_LVA, programming an invalid |
5 | minimum value requires a Translation fault. | ||
5 | 6 | ||
7 | It is most self-consistent to choose to generate the fault always. | ||
8 | |||
9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 10 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | Message-id: 20201030022618.785675-10-richard.henderson@linaro.org | 11 | Message-id: 20220301215958.157011-4-richard.henderson@linaro.org |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 13 | --- |
11 | target/arm/translate.c | 8 ++-- | 14 | target/arm/internals.h | 1 + |
12 | target/arm/translate-vfp.c.inc | 84 +++++++++++++++++----------------- | 15 | target/arm/helper.c | 32 ++++++++++++++++++++++++++++---- |
13 | 2 files changed, 46 insertions(+), 46 deletions(-) | 16 | 2 files changed, 29 insertions(+), 4 deletions(-) |
14 | 17 | ||
15 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 18 | diff --git a/target/arm/internals.h b/target/arm/internals.h |
16 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/target/arm/translate.c | 20 | --- a/target/arm/internals.h |
18 | +++ b/target/arm/translate.c | 21 | +++ b/target/arm/internals.h |
19 | @@ -XXX,XX +XXX,XX @@ static long vfp_reg_offset(bool dp, unsigned reg) | 22 | @@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters { |
23 | bool hpd : 1; | ||
24 | bool using16k : 1; | ||
25 | bool using64k : 1; | ||
26 | + bool tsz_oob : 1; /* tsz has been clamped to legal range */ | ||
27 | } ARMVAParameters; | ||
28 | |||
29 | ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
30 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/target/arm/helper.c | ||
33 | +++ b/target/arm/helper.c | ||
34 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
35 | ARMMMUIdx mmu_idx, bool data) | ||
36 | { | ||
37 | uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; | ||
38 | - bool epd, hpd, using16k, using64k; | ||
39 | - int select, tsz, tbi, max_tsz; | ||
40 | + bool epd, hpd, using16k, using64k, tsz_oob; | ||
41 | + int select, tsz, tbi, max_tsz, min_tsz; | ||
42 | |||
43 | if (!regime_has_2_ranges(mmu_idx)) { | ||
44 | select = 0; | ||
45 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
46 | } else { | ||
47 | max_tsz = 39; | ||
20 | } | 48 | } |
49 | + min_tsz = 16; /* TODO: ARMv8.2-LVA */ | ||
50 | |||
51 | - tsz = MIN(tsz, max_tsz); | ||
52 | - tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */ | ||
53 | + if (tsz > max_tsz) { | ||
54 | + tsz = max_tsz; | ||
55 | + tsz_oob = true; | ||
56 | + } else if (tsz < min_tsz) { | ||
57 | + tsz = min_tsz; | ||
58 | + tsz_oob = true; | ||
59 | + } else { | ||
60 | + tsz_oob = false; | ||
61 | + } | ||
62 | |||
63 | /* Present TBI as a composite with TBID. */ | ||
64 | tbi = aa64_va_parameter_tbi(tcr, mmu_idx); | ||
65 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
66 | .hpd = hpd, | ||
67 | .using16k = using16k, | ||
68 | .using64k = using64k, | ||
69 | + .tsz_oob = tsz_oob, | ||
70 | }; | ||
21 | } | 71 | } |
22 | 72 | ||
23 | -static inline void neon_load_reg64(TCGv_i64 var, int reg) | 73 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
24 | +static inline void vfp_load_reg64(TCGv_i64 var, int reg) | 74 | param = aa64_va_parameters(env, address, mmu_idx, |
25 | { | 75 | access_type != MMU_INST_FETCH); |
26 | - tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); | 76 | level = 0; |
27 | + tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg)); | 77 | + |
28 | } | 78 | + /* |
29 | 79 | + * If TxSZ is programmed to a value larger than the maximum, | |
30 | -static inline void neon_store_reg64(TCGv_i64 var, int reg) | 80 | + * or smaller than the effective minimum, it is IMPLEMENTATION |
31 | +static inline void vfp_store_reg64(TCGv_i64 var, int reg) | 81 | + * DEFINED whether we behave as if the field were programmed |
32 | { | 82 | + * within bounds, or if a level 0 Translation fault is generated. |
33 | - tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); | 83 | + * |
34 | + tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg)); | 84 | + * With FEAT_LVA, fault on less than minimum becomes required, |
35 | } | 85 | + * so our choice is to always raise the fault. |
36 | 86 | + */ | |
37 | static inline void vfp_load_reg32(TCGv_i32 var, int reg) | 87 | + if (param.tsz_oob) { |
38 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | 88 | + fault_type = ARMFault_Translation; |
39 | index XXXXXXX..XXXXXXX 100644 | 89 | + goto do_fault; |
40 | --- a/target/arm/translate-vfp.c.inc | 90 | + } |
41 | +++ b/target/arm/translate-vfp.c.inc | 91 | + |
42 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) | 92 | addrsize = 64 - 8 * param.tbi; |
43 | tcg_gen_ext_i32_i64(nf, cpu_NF); | 93 | inputsize = 64 - param.tsz; |
44 | tcg_gen_ext_i32_i64(vf, cpu_VF); | ||
45 | |||
46 | - neon_load_reg64(frn, rn); | ||
47 | - neon_load_reg64(frm, rm); | ||
48 | + vfp_load_reg64(frn, rn); | ||
49 | + vfp_load_reg64(frm, rm); | ||
50 | switch (a->cc) { | ||
51 | case 0: /* eq: Z */ | ||
52 | tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, | ||
53 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) | ||
54 | tcg_temp_free_i64(tmp); | ||
55 | break; | ||
56 | } | ||
57 | - neon_store_reg64(dest, rd); | ||
58 | + vfp_store_reg64(dest, rd); | ||
59 | tcg_temp_free_i64(frn); | ||
60 | tcg_temp_free_i64(frm); | ||
61 | tcg_temp_free_i64(dest); | ||
62 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) | ||
63 | TCGv_i64 tcg_res; | ||
64 | tcg_op = tcg_temp_new_i64(); | ||
65 | tcg_res = tcg_temp_new_i64(); | ||
66 | - neon_load_reg64(tcg_op, rm); | ||
67 | + vfp_load_reg64(tcg_op, rm); | ||
68 | gen_helper_rintd(tcg_res, tcg_op, fpst); | ||
69 | - neon_store_reg64(tcg_res, rd); | ||
70 | + vfp_store_reg64(tcg_res, rd); | ||
71 | tcg_temp_free_i64(tcg_op); | ||
72 | tcg_temp_free_i64(tcg_res); | ||
73 | } else { | 94 | } else { |
74 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) | ||
75 | tcg_double = tcg_temp_new_i64(); | ||
76 | tcg_res = tcg_temp_new_i64(); | ||
77 | tcg_tmp = tcg_temp_new_i32(); | ||
78 | - neon_load_reg64(tcg_double, rm); | ||
79 | + vfp_load_reg64(tcg_double, rm); | ||
80 | if (is_signed) { | ||
81 | gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst); | ||
82 | } else { | ||
83 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a) | ||
84 | tmp = tcg_temp_new_i64(); | ||
85 | if (a->l) { | ||
86 | gen_aa32_ld64(s, tmp, addr, get_mem_index(s)); | ||
87 | - neon_store_reg64(tmp, a->vd); | ||
88 | + vfp_store_reg64(tmp, a->vd); | ||
89 | } else { | ||
90 | - neon_load_reg64(tmp, a->vd); | ||
91 | + vfp_load_reg64(tmp, a->vd); | ||
92 | gen_aa32_st64(s, tmp, addr, get_mem_index(s)); | ||
93 | } | ||
94 | tcg_temp_free_i64(tmp); | ||
95 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a) | ||
96 | if (a->l) { | ||
97 | /* load */ | ||
98 | gen_aa32_ld64(s, tmp, addr, get_mem_index(s)); | ||
99 | - neon_store_reg64(tmp, a->vd + i); | ||
100 | + vfp_store_reg64(tmp, a->vd + i); | ||
101 | } else { | ||
102 | /* store */ | ||
103 | - neon_load_reg64(tmp, a->vd + i); | ||
104 | + vfp_load_reg64(tmp, a->vd + i); | ||
105 | gen_aa32_st64(s, tmp, addr, get_mem_index(s)); | ||
106 | } | ||
107 | tcg_gen_addi_i32(addr, addr, offset); | ||
108 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, | ||
109 | fd = tcg_temp_new_i64(); | ||
110 | fpst = fpstatus_ptr(FPST_FPCR); | ||
111 | |||
112 | - neon_load_reg64(f0, vn); | ||
113 | - neon_load_reg64(f1, vm); | ||
114 | + vfp_load_reg64(f0, vn); | ||
115 | + vfp_load_reg64(f1, vm); | ||
116 | |||
117 | for (;;) { | ||
118 | if (reads_vd) { | ||
119 | - neon_load_reg64(fd, vd); | ||
120 | + vfp_load_reg64(fd, vd); | ||
121 | } | ||
122 | fn(fd, f0, f1, fpst); | ||
123 | - neon_store_reg64(fd, vd); | ||
124 | + vfp_store_reg64(fd, vd); | ||
125 | |||
126 | if (veclen == 0) { | ||
127 | break; | ||
128 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, | ||
129 | veclen--; | ||
130 | vd = vfp_advance_dreg(vd, delta_d); | ||
131 | vn = vfp_advance_dreg(vn, delta_d); | ||
132 | - neon_load_reg64(f0, vn); | ||
133 | + vfp_load_reg64(f0, vn); | ||
134 | if (delta_m) { | ||
135 | vm = vfp_advance_dreg(vm, delta_m); | ||
136 | - neon_load_reg64(f1, vm); | ||
137 | + vfp_load_reg64(f1, vm); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) | ||
142 | f0 = tcg_temp_new_i64(); | ||
143 | fd = tcg_temp_new_i64(); | ||
144 | |||
145 | - neon_load_reg64(f0, vm); | ||
146 | + vfp_load_reg64(f0, vm); | ||
147 | |||
148 | for (;;) { | ||
149 | fn(fd, f0); | ||
150 | - neon_store_reg64(fd, vd); | ||
151 | + vfp_store_reg64(fd, vd); | ||
152 | |||
153 | if (veclen == 0) { | ||
154 | break; | ||
155 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) | ||
156 | /* single source one-many */ | ||
157 | while (veclen--) { | ||
158 | vd = vfp_advance_dreg(vd, delta_d); | ||
159 | - neon_store_reg64(fd, vd); | ||
160 | + vfp_store_reg64(fd, vd); | ||
161 | } | ||
162 | break; | ||
163 | } | ||
164 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm) | ||
165 | veclen--; | ||
166 | vd = vfp_advance_dreg(vd, delta_d); | ||
167 | vd = vfp_advance_dreg(vm, delta_m); | ||
168 | - neon_load_reg64(f0, vm); | ||
169 | + vfp_load_reg64(f0, vm); | ||
170 | } | ||
171 | |||
172 | tcg_temp_free_i64(f0); | ||
173 | @@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) | ||
174 | vm = tcg_temp_new_i64(); | ||
175 | vd = tcg_temp_new_i64(); | ||
176 | |||
177 | - neon_load_reg64(vn, a->vn); | ||
178 | - neon_load_reg64(vm, a->vm); | ||
179 | + vfp_load_reg64(vn, a->vn); | ||
180 | + vfp_load_reg64(vm, a->vm); | ||
181 | if (neg_n) { | ||
182 | /* VFNMS, VFMS */ | ||
183 | gen_helper_vfp_negd(vn, vn); | ||
184 | } | ||
185 | - neon_load_reg64(vd, a->vd); | ||
186 | + vfp_load_reg64(vd, a->vd); | ||
187 | if (neg_d) { | ||
188 | /* VFNMA, VFNMS */ | ||
189 | gen_helper_vfp_negd(vd, vd); | ||
190 | } | ||
191 | fpst = fpstatus_ptr(FPST_FPCR); | ||
192 | gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst); | ||
193 | - neon_store_reg64(vd, a->vd); | ||
194 | + vfp_store_reg64(vd, a->vd); | ||
195 | |||
196 | tcg_temp_free_ptr(fpst); | ||
197 | tcg_temp_free_i64(vn); | ||
198 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a) | ||
199 | fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm)); | ||
200 | |||
201 | for (;;) { | ||
202 | - neon_store_reg64(fd, vd); | ||
203 | + vfp_store_reg64(fd, vd); | ||
204 | |||
205 | if (veclen == 0) { | ||
206 | break; | ||
207 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a) | ||
208 | vd = tcg_temp_new_i64(); | ||
209 | vm = tcg_temp_new_i64(); | ||
210 | |||
211 | - neon_load_reg64(vd, a->vd); | ||
212 | + vfp_load_reg64(vd, a->vd); | ||
213 | if (a->z) { | ||
214 | tcg_gen_movi_i64(vm, 0); | ||
215 | } else { | ||
216 | - neon_load_reg64(vm, a->vm); | ||
217 | + vfp_load_reg64(vm, a->vm); | ||
218 | } | ||
219 | |||
220 | if (a->e) { | ||
221 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a) | ||
222 | tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t)); | ||
223 | vd = tcg_temp_new_i64(); | ||
224 | gen_helper_vfp_fcvt_f16_to_f64(vd, tmp, fpst, ahp_mode); | ||
225 | - neon_store_reg64(vd, a->vd); | ||
226 | + vfp_store_reg64(vd, a->vd); | ||
227 | tcg_temp_free_i32(ahp_mode); | ||
228 | tcg_temp_free_ptr(fpst); | ||
229 | tcg_temp_free_i32(tmp); | ||
230 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a) | ||
231 | tmp = tcg_temp_new_i32(); | ||
232 | vm = tcg_temp_new_i64(); | ||
233 | |||
234 | - neon_load_reg64(vm, a->vm); | ||
235 | + vfp_load_reg64(vm, a->vm); | ||
236 | gen_helper_vfp_fcvt_f64_to_f16(tmp, vm, fpst, ahp_mode); | ||
237 | tcg_temp_free_i64(vm); | ||
238 | tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t)); | ||
239 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a) | ||
240 | } | ||
241 | |||
242 | tmp = tcg_temp_new_i64(); | ||
243 | - neon_load_reg64(tmp, a->vm); | ||
244 | + vfp_load_reg64(tmp, a->vm); | ||
245 | fpst = fpstatus_ptr(FPST_FPCR); | ||
246 | gen_helper_rintd(tmp, tmp, fpst); | ||
247 | - neon_store_reg64(tmp, a->vd); | ||
248 | + vfp_store_reg64(tmp, a->vd); | ||
249 | tcg_temp_free_ptr(fpst); | ||
250 | tcg_temp_free_i64(tmp); | ||
251 | return true; | ||
252 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a) | ||
253 | } | ||
254 | |||
255 | tmp = tcg_temp_new_i64(); | ||
256 | - neon_load_reg64(tmp, a->vm); | ||
257 | + vfp_load_reg64(tmp, a->vm); | ||
258 | fpst = fpstatus_ptr(FPST_FPCR); | ||
259 | tcg_rmode = tcg_const_i32(float_round_to_zero); | ||
260 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
261 | gen_helper_rintd(tmp, tmp, fpst); | ||
262 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
263 | - neon_store_reg64(tmp, a->vd); | ||
264 | + vfp_store_reg64(tmp, a->vd); | ||
265 | tcg_temp_free_ptr(fpst); | ||
266 | tcg_temp_free_i64(tmp); | ||
267 | tcg_temp_free_i32(tcg_rmode); | ||
268 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a) | ||
269 | } | ||
270 | |||
271 | tmp = tcg_temp_new_i64(); | ||
272 | - neon_load_reg64(tmp, a->vm); | ||
273 | + vfp_load_reg64(tmp, a->vm); | ||
274 | fpst = fpstatus_ptr(FPST_FPCR); | ||
275 | gen_helper_rintd_exact(tmp, tmp, fpst); | ||
276 | - neon_store_reg64(tmp, a->vd); | ||
277 | + vfp_store_reg64(tmp, a->vd); | ||
278 | tcg_temp_free_ptr(fpst); | ||
279 | tcg_temp_free_i64(tmp); | ||
280 | return true; | ||
281 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a) | ||
282 | vd = tcg_temp_new_i64(); | ||
283 | vfp_load_reg32(vm, a->vm); | ||
284 | gen_helper_vfp_fcvtds(vd, vm, cpu_env); | ||
285 | - neon_store_reg64(vd, a->vd); | ||
286 | + vfp_store_reg64(vd, a->vd); | ||
287 | tcg_temp_free_i32(vm); | ||
288 | tcg_temp_free_i64(vd); | ||
289 | return true; | ||
290 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a) | ||
291 | |||
292 | vd = tcg_temp_new_i32(); | ||
293 | vm = tcg_temp_new_i64(); | ||
294 | - neon_load_reg64(vm, a->vm); | ||
295 | + vfp_load_reg64(vm, a->vm); | ||
296 | gen_helper_vfp_fcvtsd(vd, vm, cpu_env); | ||
297 | vfp_store_reg32(vd, a->vd); | ||
298 | tcg_temp_free_i32(vd); | ||
299 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a) | ||
300 | /* u32 -> f64 */ | ||
301 | gen_helper_vfp_uitod(vd, vm, fpst); | ||
302 | } | ||
303 | - neon_store_reg64(vd, a->vd); | ||
304 | + vfp_store_reg64(vd, a->vd); | ||
305 | tcg_temp_free_i32(vm); | ||
306 | tcg_temp_free_i64(vd); | ||
307 | tcg_temp_free_ptr(fpst); | ||
308 | @@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a) | ||
309 | |||
310 | vm = tcg_temp_new_i64(); | ||
311 | vd = tcg_temp_new_i32(); | ||
312 | - neon_load_reg64(vm, a->vm); | ||
313 | + vfp_load_reg64(vm, a->vm); | ||
314 | gen_helper_vjcvt(vd, vm, cpu_env); | ||
315 | vfp_store_reg32(vd, a->vd); | ||
316 | tcg_temp_free_i64(vm); | ||
317 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) | ||
318 | frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); | ||
319 | |||
320 | vd = tcg_temp_new_i64(); | ||
321 | - neon_load_reg64(vd, a->vd); | ||
322 | + vfp_load_reg64(vd, a->vd); | ||
323 | |||
324 | fpst = fpstatus_ptr(FPST_FPCR); | ||
325 | shift = tcg_const_i32(frac_bits); | ||
326 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) | ||
327 | g_assert_not_reached(); | ||
328 | } | ||
329 | |||
330 | - neon_store_reg64(vd, a->vd); | ||
331 | + vfp_store_reg64(vd, a->vd); | ||
332 | tcg_temp_free_i64(vd); | ||
333 | tcg_temp_free_i32(shift); | ||
334 | tcg_temp_free_ptr(fpst); | ||
335 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) | ||
336 | fpst = fpstatus_ptr(FPST_FPCR); | ||
337 | vm = tcg_temp_new_i64(); | ||
338 | vd = tcg_temp_new_i32(); | ||
339 | - neon_load_reg64(vm, a->vm); | ||
340 | + vfp_load_reg64(vm, a->vm); | ||
341 | |||
342 | if (a->s) { | ||
343 | if (a->rz) { | ||
344 | -- | 95 | -- |
345 | 2.20.1 | 96 | 2.25.1 |
346 | |||
347 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Replace all uses of neon_load/store_reg64 within translate-neon.c.inc. | 3 | We will shortly share parts of this function with other portions |
4 | of address translation. | ||
4 | 5 | ||
6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | Message-id: 20201030022618.785675-9-richard.henderson@linaro.org | 10 | Message-id: 20220301215958.157011-5-richard.henderson@linaro.org |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 12 | --- |
10 | target/arm/translate.c | 26 +++++++++ | 13 | target/arm/internals.h | 19 +------------------ |
11 | target/arm/translate-neon.c.inc | 94 ++++++++++++++++----------------- | 14 | target/arm/helper.c | 22 ++++++++++++++++++++++ |
12 | 2 files changed, 73 insertions(+), 47 deletions(-) | 15 | 2 files changed, 23 insertions(+), 18 deletions(-) |
13 | 16 | ||
14 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 17 | diff --git a/target/arm/internals.h b/target/arm/internals.h |
15 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/translate.c | 19 | --- a/target/arm/internals.h |
17 | +++ b/target/arm/translate.c | 20 | +++ b/target/arm/internals.h |
18 | @@ -XXX,XX +XXX,XX @@ static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | 21 | @@ -XXX,XX +XXX,XX @@ static inline void update_spsel(CPUARMState *env, uint32_t imm) |
19 | } | 22 | * Returns the implementation defined bit-width of physical addresses. |
23 | * The ARMv8 reference manuals refer to this as PAMax(). | ||
24 | */ | ||
25 | -static inline unsigned int arm_pamax(ARMCPU *cpu) | ||
26 | -{ | ||
27 | - static const unsigned int pamax_map[] = { | ||
28 | - [0] = 32, | ||
29 | - [1] = 36, | ||
30 | - [2] = 40, | ||
31 | - [3] = 42, | ||
32 | - [4] = 44, | ||
33 | - [5] = 48, | ||
34 | - }; | ||
35 | - unsigned int parange = | ||
36 | - FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); | ||
37 | - | ||
38 | - /* id_aa64mmfr0 is a read-only register so values outside of the | ||
39 | - * supported mappings can be considered an implementation error. */ | ||
40 | - assert(parange < ARRAY_SIZE(pamax_map)); | ||
41 | - return pamax_map[parange]; | ||
42 | -} | ||
43 | +unsigned int arm_pamax(ARMCPU *cpu); | ||
44 | |||
45 | /* Return true if extended addresses are enabled. | ||
46 | * This is always the case if our translation regime is 64 bit, | ||
47 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
48 | index XXXXXXX..XXXXXXX 100644 | ||
49 | --- a/target/arm/helper.c | ||
50 | +++ b/target/arm/helper.c | ||
51 | @@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs) | ||
20 | } | 52 | } |
21 | 53 | #endif /* !CONFIG_USER_ONLY */ | |
22 | +static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) | 54 | |
55 | +/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */ | ||
56 | +unsigned int arm_pamax(ARMCPU *cpu) | ||
23 | +{ | 57 | +{ |
24 | + long off = neon_element_offset(reg, ele, memop); | 58 | + static const unsigned int pamax_map[] = { |
59 | + [0] = 32, | ||
60 | + [1] = 36, | ||
61 | + [2] = 40, | ||
62 | + [3] = 42, | ||
63 | + [4] = 44, | ||
64 | + [5] = 48, | ||
65 | + }; | ||
66 | + unsigned int parange = | ||
67 | + FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); | ||
25 | + | 68 | + |
26 | + switch (memop) { | 69 | + /* |
27 | + case MO_Q: | 70 | + * id_aa64mmfr0 is a read-only register so values outside of the |
28 | + tcg_gen_ld_i64(dest, cpu_env, off); | 71 | + * supported mappings can be considered an implementation error. |
29 | + break; | 72 | + */ |
30 | + default: | 73 | + assert(parange < ARRAY_SIZE(pamax_map)); |
31 | + g_assert_not_reached(); | 74 | + return pamax_map[parange]; |
32 | + } | ||
33 | +} | 75 | +} |
34 | + | 76 | + |
35 | static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | 77 | static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx) |
36 | { | 78 | { |
37 | long off = neon_element_offset(reg, ele, memop); | 79 | if (regime_has_2_ranges(mmu_idx)) { |
38 | @@ -XXX,XX +XXX,XX @@ static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | ||
39 | } | ||
40 | } | ||
41 | |||
42 | +static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) | ||
43 | +{ | ||
44 | + long off = neon_element_offset(reg, ele, memop); | ||
45 | + | ||
46 | + switch (memop) { | ||
47 | + case MO_64: | ||
48 | + tcg_gen_st_i64(src, cpu_env, off); | ||
49 | + break; | ||
50 | + default: | ||
51 | + g_assert_not_reached(); | ||
52 | + } | ||
53 | +} | ||
54 | + | ||
55 | static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
56 | { | ||
57 | TCGv_ptr ret = tcg_temp_new_ptr(); | ||
58 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | ||
59 | index XXXXXXX..XXXXXXX 100644 | ||
60 | --- a/target/arm/translate-neon.c.inc | ||
61 | +++ b/target/arm/translate-neon.c.inc | ||
62 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a, | ||
63 | for (pass = 0; pass < a->q + 1; pass++) { | ||
64 | TCGv_i64 tmp = tcg_temp_new_i64(); | ||
65 | |||
66 | - neon_load_reg64(tmp, a->vm + pass); | ||
67 | + read_neon_element64(tmp, a->vm, pass, MO_64); | ||
68 | fn(tmp, cpu_env, tmp, constimm); | ||
69 | - neon_store_reg64(tmp, a->vd + pass); | ||
70 | + write_neon_element64(tmp, a->vd, pass, MO_64); | ||
71 | tcg_temp_free_i64(tmp); | ||
72 | } | ||
73 | tcg_temp_free_i64(constimm); | ||
74 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, | ||
75 | rd = tcg_temp_new_i32(); | ||
76 | |||
77 | /* Load both inputs first to avoid potential overwrite if rm == rd */ | ||
78 | - neon_load_reg64(rm1, a->vm); | ||
79 | - neon_load_reg64(rm2, a->vm + 1); | ||
80 | + read_neon_element64(rm1, a->vm, 0, MO_64); | ||
81 | + read_neon_element64(rm2, a->vm, 1, MO_64); | ||
82 | |||
83 | shiftfn(rm1, rm1, constimm); | ||
84 | narrowfn(rd, cpu_env, rm1); | ||
85 | @@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a, | ||
86 | tcg_gen_shli_i64(tmp, tmp, a->shift); | ||
87 | tcg_gen_andi_i64(tmp, tmp, ~widen_mask); | ||
88 | } | ||
89 | - neon_store_reg64(tmp, a->vd); | ||
90 | + write_neon_element64(tmp, a->vd, 0, MO_64); | ||
91 | |||
92 | widenfn(tmp, rm1); | ||
93 | tcg_temp_free_i32(rm1); | ||
94 | @@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a, | ||
95 | tcg_gen_shli_i64(tmp, tmp, a->shift); | ||
96 | tcg_gen_andi_i64(tmp, tmp, ~widen_mask); | ||
97 | } | ||
98 | - neon_store_reg64(tmp, a->vd + 1); | ||
99 | + write_neon_element64(tmp, a->vd, 1, MO_64); | ||
100 | tcg_temp_free_i64(tmp); | ||
101 | return true; | ||
102 | } | ||
103 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
104 | rm_64 = tcg_temp_new_i64(); | ||
105 | |||
106 | if (src1_wide) { | ||
107 | - neon_load_reg64(rn0_64, a->vn); | ||
108 | + read_neon_element64(rn0_64, a->vn, 0, MO_64); | ||
109 | } else { | ||
110 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
111 | read_neon_element32(tmp, a->vn, 0, MO_32); | ||
112 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
113 | * avoid incorrect results if a narrow input overlaps with the result. | ||
114 | */ | ||
115 | if (src1_wide) { | ||
116 | - neon_load_reg64(rn1_64, a->vn + 1); | ||
117 | + read_neon_element64(rn1_64, a->vn, 1, MO_64); | ||
118 | } else { | ||
119 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
120 | read_neon_element32(tmp, a->vn, 1, MO_32); | ||
121 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
122 | rm = tcg_temp_new_i32(); | ||
123 | read_neon_element32(rm, a->vm, 1, MO_32); | ||
124 | |||
125 | - neon_store_reg64(rn0_64, a->vd); | ||
126 | + write_neon_element64(rn0_64, a->vd, 0, MO_64); | ||
127 | |||
128 | widenfn(rm_64, rm); | ||
129 | tcg_temp_free_i32(rm); | ||
130 | opfn(rn1_64, rn1_64, rm_64); | ||
131 | - neon_store_reg64(rn1_64, a->vd + 1); | ||
132 | + write_neon_element64(rn1_64, a->vd, 1, MO_64); | ||
133 | |||
134 | tcg_temp_free_i64(rn0_64); | ||
135 | tcg_temp_free_i64(rn1_64); | ||
136 | @@ -XXX,XX +XXX,XX @@ static bool do_narrow_3d(DisasContext *s, arg_3diff *a, | ||
137 | rd0 = tcg_temp_new_i32(); | ||
138 | rd1 = tcg_temp_new_i32(); | ||
139 | |||
140 | - neon_load_reg64(rn_64, a->vn); | ||
141 | - neon_load_reg64(rm_64, a->vm); | ||
142 | + read_neon_element64(rn_64, a->vn, 0, MO_64); | ||
143 | + read_neon_element64(rm_64, a->vm, 0, MO_64); | ||
144 | |||
145 | opfn(rn_64, rn_64, rm_64); | ||
146 | |||
147 | narrowfn(rd0, rn_64); | ||
148 | |||
149 | - neon_load_reg64(rn_64, a->vn + 1); | ||
150 | - neon_load_reg64(rm_64, a->vm + 1); | ||
151 | + read_neon_element64(rn_64, a->vn, 1, MO_64); | ||
152 | + read_neon_element64(rm_64, a->vm, 1, MO_64); | ||
153 | |||
154 | opfn(rn_64, rn_64, rm_64); | ||
155 | |||
156 | @@ -XXX,XX +XXX,XX @@ static bool do_long_3d(DisasContext *s, arg_3diff *a, | ||
157 | /* Don't store results until after all loads: they might overlap */ | ||
158 | if (accfn) { | ||
159 | tmp = tcg_temp_new_i64(); | ||
160 | - neon_load_reg64(tmp, a->vd); | ||
161 | + read_neon_element64(tmp, a->vd, 0, MO_64); | ||
162 | accfn(tmp, tmp, rd0); | ||
163 | - neon_store_reg64(tmp, a->vd); | ||
164 | - neon_load_reg64(tmp, a->vd + 1); | ||
165 | + write_neon_element64(tmp, a->vd, 0, MO_64); | ||
166 | + read_neon_element64(tmp, a->vd, 1, MO_64); | ||
167 | accfn(tmp, tmp, rd1); | ||
168 | - neon_store_reg64(tmp, a->vd + 1); | ||
169 | + write_neon_element64(tmp, a->vd, 1, MO_64); | ||
170 | tcg_temp_free_i64(tmp); | ||
171 | } else { | ||
172 | - neon_store_reg64(rd0, a->vd); | ||
173 | - neon_store_reg64(rd1, a->vd + 1); | ||
174 | + write_neon_element64(rd0, a->vd, 0, MO_64); | ||
175 | + write_neon_element64(rd1, a->vd, 1, MO_64); | ||
176 | } | ||
177 | |||
178 | tcg_temp_free_i64(rd0); | ||
179 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar_long(DisasContext *s, arg_2scalar *a, | ||
180 | |||
181 | if (accfn) { | ||
182 | TCGv_i64 t64 = tcg_temp_new_i64(); | ||
183 | - neon_load_reg64(t64, a->vd); | ||
184 | + read_neon_element64(t64, a->vd, 0, MO_64); | ||
185 | accfn(t64, t64, rn0_64); | ||
186 | - neon_store_reg64(t64, a->vd); | ||
187 | - neon_load_reg64(t64, a->vd + 1); | ||
188 | + write_neon_element64(t64, a->vd, 0, MO_64); | ||
189 | + read_neon_element64(t64, a->vd, 1, MO_64); | ||
190 | accfn(t64, t64, rn1_64); | ||
191 | - neon_store_reg64(t64, a->vd + 1); | ||
192 | + write_neon_element64(t64, a->vd, 1, MO_64); | ||
193 | tcg_temp_free_i64(t64); | ||
194 | } else { | ||
195 | - neon_store_reg64(rn0_64, a->vd); | ||
196 | - neon_store_reg64(rn1_64, a->vd + 1); | ||
197 | + write_neon_element64(rn0_64, a->vd, 0, MO_64); | ||
198 | + write_neon_element64(rn1_64, a->vd, 1, MO_64); | ||
199 | } | ||
200 | tcg_temp_free_i64(rn0_64); | ||
201 | tcg_temp_free_i64(rn1_64); | ||
202 | @@ -XXX,XX +XXX,XX @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a) | ||
203 | right = tcg_temp_new_i64(); | ||
204 | dest = tcg_temp_new_i64(); | ||
205 | |||
206 | - neon_load_reg64(right, a->vn); | ||
207 | - neon_load_reg64(left, a->vm); | ||
208 | + read_neon_element64(right, a->vn, 0, MO_64); | ||
209 | + read_neon_element64(left, a->vm, 0, MO_64); | ||
210 | tcg_gen_extract2_i64(dest, right, left, a->imm * 8); | ||
211 | - neon_store_reg64(dest, a->vd); | ||
212 | + write_neon_element64(dest, a->vd, 0, MO_64); | ||
213 | |||
214 | tcg_temp_free_i64(left); | ||
215 | tcg_temp_free_i64(right); | ||
216 | @@ -XXX,XX +XXX,XX @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a) | ||
217 | destright = tcg_temp_new_i64(); | ||
218 | |||
219 | if (a->imm < 8) { | ||
220 | - neon_load_reg64(right, a->vn); | ||
221 | - neon_load_reg64(middle, a->vn + 1); | ||
222 | + read_neon_element64(right, a->vn, 0, MO_64); | ||
223 | + read_neon_element64(middle, a->vn, 1, MO_64); | ||
224 | tcg_gen_extract2_i64(destright, right, middle, a->imm * 8); | ||
225 | - neon_load_reg64(left, a->vm); | ||
226 | + read_neon_element64(left, a->vm, 0, MO_64); | ||
227 | tcg_gen_extract2_i64(destleft, middle, left, a->imm * 8); | ||
228 | } else { | ||
229 | - neon_load_reg64(right, a->vn + 1); | ||
230 | - neon_load_reg64(middle, a->vm); | ||
231 | + read_neon_element64(right, a->vn, 1, MO_64); | ||
232 | + read_neon_element64(middle, a->vm, 0, MO_64); | ||
233 | tcg_gen_extract2_i64(destright, right, middle, (a->imm - 8) * 8); | ||
234 | - neon_load_reg64(left, a->vm + 1); | ||
235 | + read_neon_element64(left, a->vm, 1, MO_64); | ||
236 | tcg_gen_extract2_i64(destleft, middle, left, (a->imm - 8) * 8); | ||
237 | } | ||
238 | |||
239 | - neon_store_reg64(destright, a->vd); | ||
240 | - neon_store_reg64(destleft, a->vd + 1); | ||
241 | + write_neon_element64(destright, a->vd, 0, MO_64); | ||
242 | + write_neon_element64(destleft, a->vd, 1, MO_64); | ||
243 | |||
244 | tcg_temp_free_i64(destright); | ||
245 | tcg_temp_free_i64(destleft); | ||
246 | @@ -XXX,XX +XXX,XX @@ static bool do_2misc_pairwise(DisasContext *s, arg_2misc *a, | ||
247 | |||
248 | if (accfn) { | ||
249 | TCGv_i64 tmp64 = tcg_temp_new_i64(); | ||
250 | - neon_load_reg64(tmp64, a->vd + pass); | ||
251 | + read_neon_element64(tmp64, a->vd, pass, MO_64); | ||
252 | accfn(rd_64, tmp64, rd_64); | ||
253 | tcg_temp_free_i64(tmp64); | ||
254 | } | ||
255 | - neon_store_reg64(rd_64, a->vd + pass); | ||
256 | + write_neon_element64(rd_64, a->vd, pass, MO_64); | ||
257 | tcg_temp_free_i64(rd_64); | ||
258 | } | ||
259 | return true; | ||
260 | @@ -XXX,XX +XXX,XX @@ static bool do_vmovn(DisasContext *s, arg_2misc *a, | ||
261 | rd0 = tcg_temp_new_i32(); | ||
262 | rd1 = tcg_temp_new_i32(); | ||
263 | |||
264 | - neon_load_reg64(rm, a->vm); | ||
265 | + read_neon_element64(rm, a->vm, 0, MO_64); | ||
266 | narrowfn(rd0, cpu_env, rm); | ||
267 | - neon_load_reg64(rm, a->vm + 1); | ||
268 | + read_neon_element64(rm, a->vm, 1, MO_64); | ||
269 | narrowfn(rd1, cpu_env, rm); | ||
270 | write_neon_element32(rd0, a->vd, 0, MO_32); | ||
271 | write_neon_element32(rd1, a->vd, 1, MO_32); | ||
272 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL(DisasContext *s, arg_2misc *a) | ||
273 | |||
274 | widenfn(rd, rm0); | ||
275 | tcg_gen_shli_i64(rd, rd, 8 << a->size); | ||
276 | - neon_store_reg64(rd, a->vd); | ||
277 | + write_neon_element64(rd, a->vd, 0, MO_64); | ||
278 | widenfn(rd, rm1); | ||
279 | tcg_gen_shli_i64(rd, rd, 8 << a->size); | ||
280 | - neon_store_reg64(rd, a->vd + 1); | ||
281 | + write_neon_element64(rd, a->vd, 1, MO_64); | ||
282 | |||
283 | tcg_temp_free_i64(rd); | ||
284 | tcg_temp_free_i32(rm0); | ||
285 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSWP(DisasContext *s, arg_2misc *a) | ||
286 | rm = tcg_temp_new_i64(); | ||
287 | rd = tcg_temp_new_i64(); | ||
288 | for (pass = 0; pass < (a->q ? 2 : 1); pass++) { | ||
289 | - neon_load_reg64(rm, a->vm + pass); | ||
290 | - neon_load_reg64(rd, a->vd + pass); | ||
291 | - neon_store_reg64(rm, a->vd + pass); | ||
292 | - neon_store_reg64(rd, a->vm + pass); | ||
293 | + read_neon_element64(rm, a->vm, pass, MO_64); | ||
294 | + read_neon_element64(rd, a->vd, pass, MO_64); | ||
295 | + write_neon_element64(rm, a->vd, pass, MO_64); | ||
296 | + write_neon_element64(rd, a->vm, pass, MO_64); | ||
297 | } | ||
298 | tcg_temp_free_i64(rm); | ||
299 | tcg_temp_free_i64(rd); | ||
300 | -- | 80 | -- |
301 | 2.20.1 | 81 | 2.25.1 |
302 | 82 | ||
303 | 83 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | The only uses of this function are for loading VFP | 3 | Pass down the width of the output address from translation. |
4 | single-precision values, and nothing to do with NEON. | 4 | For now this is still just PAMax, but a subsequent patch will |
5 | compute the correct value from TCR_ELx.{I}PS. | ||
5 | 6 | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | Message-id: 20201030022618.785675-8-richard.henderson@linaro.org | 9 | Message-id: 20220301215958.157011-6-richard.henderson@linaro.org |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 11 | --- |
11 | target/arm/translate.c | 4 +- | 12 | target/arm/helper.c | 21 ++++++++++----------- |
12 | target/arm/translate-vfp.c.inc | 184 ++++++++++++++++----------------- | 13 | 1 file changed, 10 insertions(+), 11 deletions(-) |
13 | 2 files changed, 94 insertions(+), 94 deletions(-) | ||
14 | 14 | ||
15 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 15 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
16 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/target/arm/translate.c | 17 | --- a/target/arm/helper.c |
18 | +++ b/target/arm/translate.c | 18 | +++ b/target/arm/helper.c |
19 | @@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg64(TCGv_i64 var, int reg) | 19 | @@ -XXX,XX +XXX,XX @@ do_fault: |
20 | tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); | 20 | * false otherwise. |
21 | } | 21 | */ |
22 | 22 | static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, | |
23 | -static inline void neon_load_reg32(TCGv_i32 var, int reg) | 23 | - int inputsize, int stride) |
24 | +static inline void vfp_load_reg32(TCGv_i32 var, int reg) | 24 | + int inputsize, int stride, int outputsize) |
25 | { | 25 | { |
26 | tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 26 | const int grainsize = stride + 3; |
27 | } | 27 | int startsizecheck; |
28 | 28 | @@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, | |
29 | -static inline void neon_store_reg32(TCGv_i32 var, int reg) | ||
30 | +static inline void vfp_store_reg32(TCGv_i32 var, int reg) | ||
31 | { | ||
32 | tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | ||
33 | } | ||
34 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/target/arm/translate-vfp.c.inc | ||
37 | +++ b/target/arm/translate-vfp.c.inc | ||
38 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) | ||
39 | frn = tcg_temp_new_i32(); | ||
40 | frm = tcg_temp_new_i32(); | ||
41 | dest = tcg_temp_new_i32(); | ||
42 | - neon_load_reg32(frn, rn); | ||
43 | - neon_load_reg32(frm, rm); | ||
44 | + vfp_load_reg32(frn, rn); | ||
45 | + vfp_load_reg32(frm, rm); | ||
46 | switch (a->cc) { | ||
47 | case 0: /* eq: Z */ | ||
48 | tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, | ||
49 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) | ||
50 | if (sz == 1) { | ||
51 | tcg_gen_andi_i32(dest, dest, 0xffff); | ||
52 | } | ||
53 | - neon_store_reg32(dest, rd); | ||
54 | + vfp_store_reg32(dest, rd); | ||
55 | tcg_temp_free_i32(frn); | ||
56 | tcg_temp_free_i32(frm); | ||
57 | tcg_temp_free_i32(dest); | ||
58 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) | ||
59 | TCGv_i32 tcg_res; | ||
60 | tcg_op = tcg_temp_new_i32(); | ||
61 | tcg_res = tcg_temp_new_i32(); | ||
62 | - neon_load_reg32(tcg_op, rm); | ||
63 | + vfp_load_reg32(tcg_op, rm); | ||
64 | if (sz == 1) { | ||
65 | gen_helper_rinth(tcg_res, tcg_op, fpst); | ||
66 | } else { | ||
67 | gen_helper_rints(tcg_res, tcg_op, fpst); | ||
68 | } | ||
69 | - neon_store_reg32(tcg_res, rd); | ||
70 | + vfp_store_reg32(tcg_res, rd); | ||
71 | tcg_temp_free_i32(tcg_op); | ||
72 | tcg_temp_free_i32(tcg_res); | ||
73 | } | 29 | } |
74 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) | 30 | |
75 | gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst); | 31 | if (is_aa64) { |
76 | } | 32 | - CPUARMState *env = &cpu->env; |
77 | tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res); | 33 | - unsigned int pamax = arm_pamax(cpu); |
78 | - neon_store_reg32(tcg_tmp, rd); | 34 | - |
79 | + vfp_store_reg32(tcg_tmp, rd); | 35 | switch (stride) { |
80 | tcg_temp_free_i32(tcg_tmp); | 36 | case 13: /* 64KB Pages. */ |
81 | tcg_temp_free_i64(tcg_res); | 37 | - if (level == 0 || (level == 1 && pamax <= 42)) { |
82 | tcg_temp_free_i64(tcg_double); | 38 | + if (level == 0 || (level == 1 && outputsize <= 42)) { |
83 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) | 39 | return false; |
84 | TCGv_i32 tcg_single, tcg_res; | ||
85 | tcg_single = tcg_temp_new_i32(); | ||
86 | tcg_res = tcg_temp_new_i32(); | ||
87 | - neon_load_reg32(tcg_single, rm); | ||
88 | + vfp_load_reg32(tcg_single, rm); | ||
89 | if (sz == 1) { | ||
90 | if (is_signed) { | ||
91 | gen_helper_vfp_toslh(tcg_res, tcg_single, tcg_shift, fpst); | ||
92 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) | ||
93 | gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst); | ||
94 | } | ||
95 | } | ||
96 | - neon_store_reg32(tcg_res, rd); | ||
97 | + vfp_store_reg32(tcg_res, rd); | ||
98 | tcg_temp_free_i32(tcg_res); | ||
99 | tcg_temp_free_i32(tcg_single); | ||
100 | } | ||
101 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a) | ||
102 | if (a->l) { | ||
103 | /* VFP to general purpose register */ | ||
104 | tmp = tcg_temp_new_i32(); | ||
105 | - neon_load_reg32(tmp, a->vn); | ||
106 | + vfp_load_reg32(tmp, a->vn); | ||
107 | tcg_gen_andi_i32(tmp, tmp, 0xffff); | ||
108 | store_reg(s, a->rt, tmp); | ||
109 | } else { | ||
110 | /* general purpose register to VFP */ | ||
111 | tmp = load_reg(s, a->rt); | ||
112 | tcg_gen_andi_i32(tmp, tmp, 0xffff); | ||
113 | - neon_store_reg32(tmp, a->vn); | ||
114 | + vfp_store_reg32(tmp, a->vn); | ||
115 | tcg_temp_free_i32(tmp); | ||
116 | } | ||
117 | |||
118 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a) | ||
119 | if (a->l) { | ||
120 | /* VFP to general purpose register */ | ||
121 | tmp = tcg_temp_new_i32(); | ||
122 | - neon_load_reg32(tmp, a->vn); | ||
123 | + vfp_load_reg32(tmp, a->vn); | ||
124 | if (a->rt == 15) { | ||
125 | /* Set the 4 flag bits in the CPSR. */ | ||
126 | gen_set_nzcv(tmp); | ||
127 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a) | ||
128 | } else { | ||
129 | /* general purpose register to VFP */ | ||
130 | tmp = load_reg(s, a->rt); | ||
131 | - neon_store_reg32(tmp, a->vn); | ||
132 | + vfp_store_reg32(tmp, a->vn); | ||
133 | tcg_temp_free_i32(tmp); | ||
134 | } | ||
135 | |||
136 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a) | ||
137 | if (a->op) { | ||
138 | /* fpreg to gpreg */ | ||
139 | tmp = tcg_temp_new_i32(); | ||
140 | - neon_load_reg32(tmp, a->vm); | ||
141 | + vfp_load_reg32(tmp, a->vm); | ||
142 | store_reg(s, a->rt, tmp); | ||
143 | tmp = tcg_temp_new_i32(); | ||
144 | - neon_load_reg32(tmp, a->vm + 1); | ||
145 | + vfp_load_reg32(tmp, a->vm + 1); | ||
146 | store_reg(s, a->rt2, tmp); | ||
147 | } else { | ||
148 | /* gpreg to fpreg */ | ||
149 | tmp = load_reg(s, a->rt); | ||
150 | - neon_store_reg32(tmp, a->vm); | ||
151 | + vfp_store_reg32(tmp, a->vm); | ||
152 | tcg_temp_free_i32(tmp); | ||
153 | tmp = load_reg(s, a->rt2); | ||
154 | - neon_store_reg32(tmp, a->vm + 1); | ||
155 | + vfp_store_reg32(tmp, a->vm + 1); | ||
156 | tcg_temp_free_i32(tmp); | ||
157 | } | ||
158 | |||
159 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a) | ||
160 | if (a->op) { | ||
161 | /* fpreg to gpreg */ | ||
162 | tmp = tcg_temp_new_i32(); | ||
163 | - neon_load_reg32(tmp, a->vm * 2); | ||
164 | + vfp_load_reg32(tmp, a->vm * 2); | ||
165 | store_reg(s, a->rt, tmp); | ||
166 | tmp = tcg_temp_new_i32(); | ||
167 | - neon_load_reg32(tmp, a->vm * 2 + 1); | ||
168 | + vfp_load_reg32(tmp, a->vm * 2 + 1); | ||
169 | store_reg(s, a->rt2, tmp); | ||
170 | } else { | ||
171 | /* gpreg to fpreg */ | ||
172 | tmp = load_reg(s, a->rt); | ||
173 | - neon_store_reg32(tmp, a->vm * 2); | ||
174 | + vfp_store_reg32(tmp, a->vm * 2); | ||
175 | tcg_temp_free_i32(tmp); | ||
176 | tmp = load_reg(s, a->rt2); | ||
177 | - neon_store_reg32(tmp, a->vm * 2 + 1); | ||
178 | + vfp_store_reg32(tmp, a->vm * 2 + 1); | ||
179 | tcg_temp_free_i32(tmp); | ||
180 | } | ||
181 | |||
182 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_hp(DisasContext *s, arg_VLDR_VSTR_sp *a) | ||
183 | tmp = tcg_temp_new_i32(); | ||
184 | if (a->l) { | ||
185 | gen_aa32_ld16u(s, tmp, addr, get_mem_index(s)); | ||
186 | - neon_store_reg32(tmp, a->vd); | ||
187 | + vfp_store_reg32(tmp, a->vd); | ||
188 | } else { | ||
189 | - neon_load_reg32(tmp, a->vd); | ||
190 | + vfp_load_reg32(tmp, a->vd); | ||
191 | gen_aa32_st16(s, tmp, addr, get_mem_index(s)); | ||
192 | } | ||
193 | tcg_temp_free_i32(tmp); | ||
194 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a) | ||
195 | tmp = tcg_temp_new_i32(); | ||
196 | if (a->l) { | ||
197 | gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); | ||
198 | - neon_store_reg32(tmp, a->vd); | ||
199 | + vfp_store_reg32(tmp, a->vd); | ||
200 | } else { | ||
201 | - neon_load_reg32(tmp, a->vd); | ||
202 | + vfp_load_reg32(tmp, a->vd); | ||
203 | gen_aa32_st32(s, tmp, addr, get_mem_index(s)); | ||
204 | } | ||
205 | tcg_temp_free_i32(tmp); | ||
206 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a) | ||
207 | if (a->l) { | ||
208 | /* load */ | ||
209 | gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); | ||
210 | - neon_store_reg32(tmp, a->vd + i); | ||
211 | + vfp_store_reg32(tmp, a->vd + i); | ||
212 | } else { | ||
213 | /* store */ | ||
214 | - neon_load_reg32(tmp, a->vd + i); | ||
215 | + vfp_load_reg32(tmp, a->vd + i); | ||
216 | gen_aa32_st32(s, tmp, addr, get_mem_index(s)); | ||
217 | } | ||
218 | tcg_gen_addi_i32(addr, addr, offset); | ||
219 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, | ||
220 | fd = tcg_temp_new_i32(); | ||
221 | fpst = fpstatus_ptr(FPST_FPCR); | ||
222 | |||
223 | - neon_load_reg32(f0, vn); | ||
224 | - neon_load_reg32(f1, vm); | ||
225 | + vfp_load_reg32(f0, vn); | ||
226 | + vfp_load_reg32(f1, vm); | ||
227 | |||
228 | for (;;) { | ||
229 | if (reads_vd) { | ||
230 | - neon_load_reg32(fd, vd); | ||
231 | + vfp_load_reg32(fd, vd); | ||
232 | } | ||
233 | fn(fd, f0, f1, fpst); | ||
234 | - neon_store_reg32(fd, vd); | ||
235 | + vfp_store_reg32(fd, vd); | ||
236 | |||
237 | if (veclen == 0) { | ||
238 | break; | ||
239 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, | ||
240 | veclen--; | ||
241 | vd = vfp_advance_sreg(vd, delta_d); | ||
242 | vn = vfp_advance_sreg(vn, delta_d); | ||
243 | - neon_load_reg32(f0, vn); | ||
244 | + vfp_load_reg32(f0, vn); | ||
245 | if (delta_m) { | ||
246 | vm = vfp_advance_sreg(vm, delta_m); | ||
247 | - neon_load_reg32(f1, vm); | ||
248 | + vfp_load_reg32(f1, vm); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn, | ||
253 | fd = tcg_temp_new_i32(); | ||
254 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
255 | |||
256 | - neon_load_reg32(f0, vn); | ||
257 | - neon_load_reg32(f1, vm); | ||
258 | + vfp_load_reg32(f0, vn); | ||
259 | + vfp_load_reg32(f1, vm); | ||
260 | |||
261 | if (reads_vd) { | ||
262 | - neon_load_reg32(fd, vd); | ||
263 | + vfp_load_reg32(fd, vd); | ||
264 | } | ||
265 | fn(fd, f0, f1, fpst); | ||
266 | - neon_store_reg32(fd, vd); | ||
267 | + vfp_store_reg32(fd, vd); | ||
268 | |||
269 | tcg_temp_free_i32(f0); | ||
270 | tcg_temp_free_i32(f1); | ||
271 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) | ||
272 | f0 = tcg_temp_new_i32(); | ||
273 | fd = tcg_temp_new_i32(); | ||
274 | |||
275 | - neon_load_reg32(f0, vm); | ||
276 | + vfp_load_reg32(f0, vm); | ||
277 | |||
278 | for (;;) { | ||
279 | fn(fd, f0); | ||
280 | - neon_store_reg32(fd, vd); | ||
281 | + vfp_store_reg32(fd, vd); | ||
282 | |||
283 | if (veclen == 0) { | ||
284 | break; | ||
285 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) | ||
286 | /* single source one-many */ | ||
287 | while (veclen--) { | ||
288 | vd = vfp_advance_sreg(vd, delta_d); | ||
289 | - neon_store_reg32(fd, vd); | ||
290 | + vfp_store_reg32(fd, vd); | ||
291 | } | 40 | } |
292 | break; | 41 | break; |
42 | case 11: /* 16KB Pages. */ | ||
43 | - if (level == 0 || (level == 1 && pamax <= 40)) { | ||
44 | + if (level == 0 || (level == 1 && outputsize <= 40)) { | ||
45 | return false; | ||
46 | } | ||
47 | break; | ||
48 | case 9: /* 4KB Pages. */ | ||
49 | - if (level == 0 && pamax <= 42) { | ||
50 | + if (level == 0 && outputsize <= 42) { | ||
51 | return false; | ||
52 | } | ||
53 | break; | ||
54 | @@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, | ||
293 | } | 55 | } |
294 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) | 56 | |
295 | veclen--; | 57 | /* Inputsize checks. */ |
296 | vd = vfp_advance_sreg(vd, delta_d); | 58 | - if (inputsize > pamax && |
297 | vm = vfp_advance_sreg(vm, delta_m); | 59 | - (arm_el_is_aa64(env, 1) || inputsize > 40)) { |
298 | - neon_load_reg32(f0, vm); | 60 | + if (inputsize > outputsize && |
299 | + vfp_load_reg32(f0, vm); | 61 | + (arm_el_is_aa64(&cpu->env, 1) || inputsize > 40)) { |
62 | /* This is CONSTRAINED UNPREDICTABLE and we choose to fault. */ | ||
63 | return false; | ||
64 | } | ||
65 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, | ||
66 | target_ulong page_size; | ||
67 | uint32_t attrs; | ||
68 | int32_t stride; | ||
69 | - int addrsize, inputsize; | ||
70 | + int addrsize, inputsize, outputsize; | ||
71 | TCR *tcr = regime_tcr(env, mmu_idx); | ||
72 | int ap, ns, xn, pxn; | ||
73 | uint32_t el = regime_el(env, mmu_idx); | ||
74 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, | ||
75 | |||
76 | addrsize = 64 - 8 * param.tbi; | ||
77 | inputsize = 64 - param.tsz; | ||
78 | + outputsize = arm_pamax(cpu); | ||
79 | } else { | ||
80 | param = aa32_va_parameters(env, address, mmu_idx); | ||
81 | level = 1; | ||
82 | addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32); | ||
83 | inputsize = addrsize - param.tsz; | ||
84 | + outputsize = 40; | ||
300 | } | 85 | } |
301 | 86 | ||
302 | tcg_temp_free_i32(f0); | 87 | /* |
303 | @@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm) | 88 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
304 | } | 89 | |
305 | 90 | /* Check that the starting level is valid. */ | |
306 | f0 = tcg_temp_new_i32(); | 91 | ok = check_s2_mmu_setup(cpu, aarch64, startlevel, |
307 | - neon_load_reg32(f0, vm); | 92 | - inputsize, stride); |
308 | + vfp_load_reg32(f0, vm); | 93 | + inputsize, stride, outputsize); |
309 | fn(f0, f0); | 94 | if (!ok) { |
310 | - neon_store_reg32(f0, vd); | 95 | fault_type = ARMFault_Translation; |
311 | + vfp_store_reg32(f0, vd); | 96 | goto do_fault; |
312 | tcg_temp_free_i32(f0); | ||
313 | |||
314 | return true; | ||
315 | @@ -XXX,XX +XXX,XX @@ static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) | ||
316 | vm = tcg_temp_new_i32(); | ||
317 | vd = tcg_temp_new_i32(); | ||
318 | |||
319 | - neon_load_reg32(vn, a->vn); | ||
320 | - neon_load_reg32(vm, a->vm); | ||
321 | + vfp_load_reg32(vn, a->vn); | ||
322 | + vfp_load_reg32(vm, a->vm); | ||
323 | if (neg_n) { | ||
324 | /* VFNMS, VFMS */ | ||
325 | gen_helper_vfp_negh(vn, vn); | ||
326 | } | ||
327 | - neon_load_reg32(vd, a->vd); | ||
328 | + vfp_load_reg32(vd, a->vd); | ||
329 | if (neg_d) { | ||
330 | /* VFNMA, VFNMS */ | ||
331 | gen_helper_vfp_negh(vd, vd); | ||
332 | } | ||
333 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
334 | gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst); | ||
335 | - neon_store_reg32(vd, a->vd); | ||
336 | + vfp_store_reg32(vd, a->vd); | ||
337 | |||
338 | tcg_temp_free_ptr(fpst); | ||
339 | tcg_temp_free_i32(vn); | ||
340 | @@ -XXX,XX +XXX,XX @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) | ||
341 | vm = tcg_temp_new_i32(); | ||
342 | vd = tcg_temp_new_i32(); | ||
343 | |||
344 | - neon_load_reg32(vn, a->vn); | ||
345 | - neon_load_reg32(vm, a->vm); | ||
346 | + vfp_load_reg32(vn, a->vn); | ||
347 | + vfp_load_reg32(vm, a->vm); | ||
348 | if (neg_n) { | ||
349 | /* VFNMS, VFMS */ | ||
350 | gen_helper_vfp_negs(vn, vn); | ||
351 | } | ||
352 | - neon_load_reg32(vd, a->vd); | ||
353 | + vfp_load_reg32(vd, a->vd); | ||
354 | if (neg_d) { | ||
355 | /* VFNMA, VFNMS */ | ||
356 | gen_helper_vfp_negs(vd, vd); | ||
357 | } | ||
358 | fpst = fpstatus_ptr(FPST_FPCR); | ||
359 | gen_helper_vfp_muladds(vd, vn, vm, vd, fpst); | ||
360 | - neon_store_reg32(vd, a->vd); | ||
361 | + vfp_store_reg32(vd, a->vd); | ||
362 | |||
363 | tcg_temp_free_ptr(fpst); | ||
364 | tcg_temp_free_i32(vn); | ||
365 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a) | ||
366 | } | ||
367 | |||
368 | fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm)); | ||
369 | - neon_store_reg32(fd, a->vd); | ||
370 | + vfp_store_reg32(fd, a->vd); | ||
371 | tcg_temp_free_i32(fd); | ||
372 | return true; | ||
373 | } | ||
374 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a) | ||
375 | fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm)); | ||
376 | |||
377 | for (;;) { | ||
378 | - neon_store_reg32(fd, vd); | ||
379 | + vfp_store_reg32(fd, vd); | ||
380 | |||
381 | if (veclen == 0) { | ||
382 | break; | ||
383 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a) | ||
384 | vd = tcg_temp_new_i32(); | ||
385 | vm = tcg_temp_new_i32(); | ||
386 | |||
387 | - neon_load_reg32(vd, a->vd); | ||
388 | + vfp_load_reg32(vd, a->vd); | ||
389 | if (a->z) { | ||
390 | tcg_gen_movi_i32(vm, 0); | ||
391 | } else { | ||
392 | - neon_load_reg32(vm, a->vm); | ||
393 | + vfp_load_reg32(vm, a->vm); | ||
394 | } | ||
395 | |||
396 | if (a->e) { | ||
397 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a) | ||
398 | vd = tcg_temp_new_i32(); | ||
399 | vm = tcg_temp_new_i32(); | ||
400 | |||
401 | - neon_load_reg32(vd, a->vd); | ||
402 | + vfp_load_reg32(vd, a->vd); | ||
403 | if (a->z) { | ||
404 | tcg_gen_movi_i32(vm, 0); | ||
405 | } else { | ||
406 | - neon_load_reg32(vm, a->vm); | ||
407 | + vfp_load_reg32(vm, a->vm); | ||
408 | } | ||
409 | |||
410 | if (a->e) { | ||
411 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a) | ||
412 | /* The T bit tells us if we want the low or high 16 bits of Vm */ | ||
413 | tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t)); | ||
414 | gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp_mode); | ||
415 | - neon_store_reg32(tmp, a->vd); | ||
416 | + vfp_store_reg32(tmp, a->vd); | ||
417 | tcg_temp_free_i32(ahp_mode); | ||
418 | tcg_temp_free_ptr(fpst); | ||
419 | tcg_temp_free_i32(tmp); | ||
420 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a) | ||
421 | ahp_mode = get_ahp_flag(); | ||
422 | tmp = tcg_temp_new_i32(); | ||
423 | |||
424 | - neon_load_reg32(tmp, a->vm); | ||
425 | + vfp_load_reg32(tmp, a->vm); | ||
426 | gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp_mode); | ||
427 | tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t)); | ||
428 | tcg_temp_free_i32(ahp_mode); | ||
429 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_hp(DisasContext *s, arg_VRINTR_sp *a) | ||
430 | } | ||
431 | |||
432 | tmp = tcg_temp_new_i32(); | ||
433 | - neon_load_reg32(tmp, a->vm); | ||
434 | + vfp_load_reg32(tmp, a->vm); | ||
435 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
436 | gen_helper_rinth(tmp, tmp, fpst); | ||
437 | - neon_store_reg32(tmp, a->vd); | ||
438 | + vfp_store_reg32(tmp, a->vd); | ||
439 | tcg_temp_free_ptr(fpst); | ||
440 | tcg_temp_free_i32(tmp); | ||
441 | return true; | ||
442 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a) | ||
443 | } | ||
444 | |||
445 | tmp = tcg_temp_new_i32(); | ||
446 | - neon_load_reg32(tmp, a->vm); | ||
447 | + vfp_load_reg32(tmp, a->vm); | ||
448 | fpst = fpstatus_ptr(FPST_FPCR); | ||
449 | gen_helper_rints(tmp, tmp, fpst); | ||
450 | - neon_store_reg32(tmp, a->vd); | ||
451 | + vfp_store_reg32(tmp, a->vd); | ||
452 | tcg_temp_free_ptr(fpst); | ||
453 | tcg_temp_free_i32(tmp); | ||
454 | return true; | ||
455 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a) | ||
456 | } | ||
457 | |||
458 | tmp = tcg_temp_new_i32(); | ||
459 | - neon_load_reg32(tmp, a->vm); | ||
460 | + vfp_load_reg32(tmp, a->vm); | ||
461 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
462 | tcg_rmode = tcg_const_i32(float_round_to_zero); | ||
463 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
464 | gen_helper_rinth(tmp, tmp, fpst); | ||
465 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
466 | - neon_store_reg32(tmp, a->vd); | ||
467 | + vfp_store_reg32(tmp, a->vd); | ||
468 | tcg_temp_free_ptr(fpst); | ||
469 | tcg_temp_free_i32(tcg_rmode); | ||
470 | tcg_temp_free_i32(tmp); | ||
471 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a) | ||
472 | } | ||
473 | |||
474 | tmp = tcg_temp_new_i32(); | ||
475 | - neon_load_reg32(tmp, a->vm); | ||
476 | + vfp_load_reg32(tmp, a->vm); | ||
477 | fpst = fpstatus_ptr(FPST_FPCR); | ||
478 | tcg_rmode = tcg_const_i32(float_round_to_zero); | ||
479 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
480 | gen_helper_rints(tmp, tmp, fpst); | ||
481 | gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); | ||
482 | - neon_store_reg32(tmp, a->vd); | ||
483 | + vfp_store_reg32(tmp, a->vd); | ||
484 | tcg_temp_free_ptr(fpst); | ||
485 | tcg_temp_free_i32(tcg_rmode); | ||
486 | tcg_temp_free_i32(tmp); | ||
487 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_hp(DisasContext *s, arg_VRINTX_sp *a) | ||
488 | } | ||
489 | |||
490 | tmp = tcg_temp_new_i32(); | ||
491 | - neon_load_reg32(tmp, a->vm); | ||
492 | + vfp_load_reg32(tmp, a->vm); | ||
493 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
494 | gen_helper_rinth_exact(tmp, tmp, fpst); | ||
495 | - neon_store_reg32(tmp, a->vd); | ||
496 | + vfp_store_reg32(tmp, a->vd); | ||
497 | tcg_temp_free_ptr(fpst); | ||
498 | tcg_temp_free_i32(tmp); | ||
499 | return true; | ||
500 | @@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a) | ||
501 | } | ||
502 | |||
503 | tmp = tcg_temp_new_i32(); | ||
504 | - neon_load_reg32(tmp, a->vm); | ||
505 | + vfp_load_reg32(tmp, a->vm); | ||
506 | fpst = fpstatus_ptr(FPST_FPCR); | ||
507 | gen_helper_rints_exact(tmp, tmp, fpst); | ||
508 | - neon_store_reg32(tmp, a->vd); | ||
509 | + vfp_store_reg32(tmp, a->vd); | ||
510 | tcg_temp_free_ptr(fpst); | ||
511 | tcg_temp_free_i32(tmp); | ||
512 | return true; | ||
513 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a) | ||
514 | |||
515 | vm = tcg_temp_new_i32(); | ||
516 | vd = tcg_temp_new_i64(); | ||
517 | - neon_load_reg32(vm, a->vm); | ||
518 | + vfp_load_reg32(vm, a->vm); | ||
519 | gen_helper_vfp_fcvtds(vd, vm, cpu_env); | ||
520 | neon_store_reg64(vd, a->vd); | ||
521 | tcg_temp_free_i32(vm); | ||
522 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a) | ||
523 | vm = tcg_temp_new_i64(); | ||
524 | neon_load_reg64(vm, a->vm); | ||
525 | gen_helper_vfp_fcvtsd(vd, vm, cpu_env); | ||
526 | - neon_store_reg32(vd, a->vd); | ||
527 | + vfp_store_reg32(vd, a->vd); | ||
528 | tcg_temp_free_i32(vd); | ||
529 | tcg_temp_free_i64(vm); | ||
530 | return true; | ||
531 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a) | ||
532 | } | ||
533 | |||
534 | vm = tcg_temp_new_i32(); | ||
535 | - neon_load_reg32(vm, a->vm); | ||
536 | + vfp_load_reg32(vm, a->vm); | ||
537 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
538 | if (a->s) { | ||
539 | /* i32 -> f16 */ | ||
540 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a) | ||
541 | /* u32 -> f16 */ | ||
542 | gen_helper_vfp_uitoh(vm, vm, fpst); | ||
543 | } | ||
544 | - neon_store_reg32(vm, a->vd); | ||
545 | + vfp_store_reg32(vm, a->vd); | ||
546 | tcg_temp_free_i32(vm); | ||
547 | tcg_temp_free_ptr(fpst); | ||
548 | return true; | ||
549 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) | ||
550 | } | ||
551 | |||
552 | vm = tcg_temp_new_i32(); | ||
553 | - neon_load_reg32(vm, a->vm); | ||
554 | + vfp_load_reg32(vm, a->vm); | ||
555 | fpst = fpstatus_ptr(FPST_FPCR); | ||
556 | if (a->s) { | ||
557 | /* i32 -> f32 */ | ||
558 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) | ||
559 | /* u32 -> f32 */ | ||
560 | gen_helper_vfp_uitos(vm, vm, fpst); | ||
561 | } | ||
562 | - neon_store_reg32(vm, a->vd); | ||
563 | + vfp_store_reg32(vm, a->vd); | ||
564 | tcg_temp_free_i32(vm); | ||
565 | tcg_temp_free_ptr(fpst); | ||
566 | return true; | ||
567 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a) | ||
568 | |||
569 | vm = tcg_temp_new_i32(); | ||
570 | vd = tcg_temp_new_i64(); | ||
571 | - neon_load_reg32(vm, a->vm); | ||
572 | + vfp_load_reg32(vm, a->vm); | ||
573 | fpst = fpstatus_ptr(FPST_FPCR); | ||
574 | if (a->s) { | ||
575 | /* i32 -> f64 */ | ||
576 | @@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a) | ||
577 | vd = tcg_temp_new_i32(); | ||
578 | neon_load_reg64(vm, a->vm); | ||
579 | gen_helper_vjcvt(vd, vm, cpu_env); | ||
580 | - neon_store_reg32(vd, a->vd); | ||
581 | + vfp_store_reg32(vd, a->vd); | ||
582 | tcg_temp_free_i64(vm); | ||
583 | tcg_temp_free_i32(vd); | ||
584 | return true; | ||
585 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) | ||
586 | frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); | ||
587 | |||
588 | vd = tcg_temp_new_i32(); | ||
589 | - neon_load_reg32(vd, a->vd); | ||
590 | + vfp_load_reg32(vd, a->vd); | ||
591 | |||
592 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
593 | shift = tcg_const_i32(frac_bits); | ||
594 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) | ||
595 | g_assert_not_reached(); | ||
596 | } | ||
597 | |||
598 | - neon_store_reg32(vd, a->vd); | ||
599 | + vfp_store_reg32(vd, a->vd); | ||
600 | tcg_temp_free_i32(vd); | ||
601 | tcg_temp_free_i32(shift); | ||
602 | tcg_temp_free_ptr(fpst); | ||
603 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) | ||
604 | frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); | ||
605 | |||
606 | vd = tcg_temp_new_i32(); | ||
607 | - neon_load_reg32(vd, a->vd); | ||
608 | + vfp_load_reg32(vd, a->vd); | ||
609 | |||
610 | fpst = fpstatus_ptr(FPST_FPCR); | ||
611 | shift = tcg_const_i32(frac_bits); | ||
612 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) | ||
613 | g_assert_not_reached(); | ||
614 | } | ||
615 | |||
616 | - neon_store_reg32(vd, a->vd); | ||
617 | + vfp_store_reg32(vd, a->vd); | ||
618 | tcg_temp_free_i32(vd); | ||
619 | tcg_temp_free_i32(shift); | ||
620 | tcg_temp_free_ptr(fpst); | ||
621 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a) | ||
622 | |||
623 | fpst = fpstatus_ptr(FPST_FPCR_F16); | ||
624 | vm = tcg_temp_new_i32(); | ||
625 | - neon_load_reg32(vm, a->vm); | ||
626 | + vfp_load_reg32(vm, a->vm); | ||
627 | |||
628 | if (a->s) { | ||
629 | if (a->rz) { | ||
630 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a) | ||
631 | gen_helper_vfp_touih(vm, vm, fpst); | ||
632 | } | ||
633 | } | ||
634 | - neon_store_reg32(vm, a->vd); | ||
635 | + vfp_store_reg32(vm, a->vd); | ||
636 | tcg_temp_free_i32(vm); | ||
637 | tcg_temp_free_ptr(fpst); | ||
638 | return true; | ||
639 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) | ||
640 | |||
641 | fpst = fpstatus_ptr(FPST_FPCR); | ||
642 | vm = tcg_temp_new_i32(); | ||
643 | - neon_load_reg32(vm, a->vm); | ||
644 | + vfp_load_reg32(vm, a->vm); | ||
645 | |||
646 | if (a->s) { | ||
647 | if (a->rz) { | ||
648 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) | ||
649 | gen_helper_vfp_touis(vm, vm, fpst); | ||
650 | } | ||
651 | } | ||
652 | - neon_store_reg32(vm, a->vd); | ||
653 | + vfp_store_reg32(vm, a->vd); | ||
654 | tcg_temp_free_i32(vm); | ||
655 | tcg_temp_free_ptr(fpst); | ||
656 | return true; | ||
657 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) | ||
658 | gen_helper_vfp_touid(vd, vm, fpst); | ||
659 | } | ||
660 | } | ||
661 | - neon_store_reg32(vd, a->vd); | ||
662 | + vfp_store_reg32(vd, a->vd); | ||
663 | tcg_temp_free_i32(vd); | ||
664 | tcg_temp_free_i64(vm); | ||
665 | tcg_temp_free_ptr(fpst); | ||
666 | @@ -XXX,XX +XXX,XX @@ static bool trans_VINS(DisasContext *s, arg_VINS *a) | ||
667 | /* Insert low half of Vm into high half of Vd */ | ||
668 | rm = tcg_temp_new_i32(); | ||
669 | rd = tcg_temp_new_i32(); | ||
670 | - neon_load_reg32(rm, a->vm); | ||
671 | - neon_load_reg32(rd, a->vd); | ||
672 | + vfp_load_reg32(rm, a->vm); | ||
673 | + vfp_load_reg32(rd, a->vd); | ||
674 | tcg_gen_deposit_i32(rd, rd, rm, 16, 16); | ||
675 | - neon_store_reg32(rd, a->vd); | ||
676 | + vfp_store_reg32(rd, a->vd); | ||
677 | tcg_temp_free_i32(rm); | ||
678 | tcg_temp_free_i32(rd); | ||
679 | return true; | ||
680 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMOVX(DisasContext *s, arg_VINS *a) | ||
681 | |||
682 | /* Set Vd to high half of Vm */ | ||
683 | rm = tcg_temp_new_i32(); | ||
684 | - neon_load_reg32(rm, a->vm); | ||
685 | + vfp_load_reg32(rm, a->vm); | ||
686 | tcg_gen_shri_i32(rm, rm, 16); | ||
687 | - neon_store_reg32(rm, a->vd); | ||
688 | + vfp_store_reg32(rm, a->vd); | ||
689 | tcg_temp_free_i32(rm); | ||
690 | return true; | ||
691 | } | ||
692 | -- | 97 | -- |
693 | 2.20.1 | 98 | 2.25.1 |
694 | |||
695 | diff view generated by jsdifflib |
1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Use the BIT_ULL() macro to ensure we use 64-bit arithmetic. | 3 | The macro is a bit more readable than the inlined computation. |
4 | This fixes the following Coverity issue (OVERFLOW_BEFORE_WIDEN): | ||
5 | 4 | ||
6 | CID 1432363 (#1 of 1): Unintentional integer overflow: | 5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
7 | 6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | |
8 | overflow_before_widen: | 7 | Message-id: 20220301215958.157011-7-richard.henderson@linaro.org |
9 | Potentially overflowing expression 1 << scale with type int | ||
10 | (32 bits, signed) is evaluated using 32-bit arithmetic, and | ||
11 | then used in a context that expects an expression of type | ||
12 | hwaddr (64 bits, unsigned). | ||
13 | |||
14 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
15 | Acked-by: Eric Auger <eric.auger@redhat.com> | ||
16 | Message-id: 20201030144617.1535064-1-philmd@redhat.com | ||
17 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
19 | --- | 9 | --- |
20 | hw/arm/smmuv3.c | 3 ++- | 10 | target/arm/helper.c | 4 ++-- |
21 | 1 file changed, 2 insertions(+), 1 deletion(-) | 11 | 1 file changed, 2 insertions(+), 2 deletions(-) |
22 | 12 | ||
23 | diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c | 13 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
24 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/hw/arm/smmuv3.c | 15 | --- a/target/arm/helper.c |
26 | +++ b/hw/arm/smmuv3.c | 16 | +++ b/target/arm/helper.c |
27 | @@ -XXX,XX +XXX,XX @@ | 17 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
28 | */ | 18 | level = startlevel; |
29 | |||
30 | #include "qemu/osdep.h" | ||
31 | +#include "qemu/bitops.h" | ||
32 | #include "hw/irq.h" | ||
33 | #include "hw/sysbus.h" | ||
34 | #include "migration/vmstate.h" | ||
35 | @@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) | ||
36 | scale = CMD_SCALE(cmd); | ||
37 | num = CMD_NUM(cmd); | ||
38 | ttl = CMD_TTL(cmd); | ||
39 | - num_pages = (num + 1) * (1 << (scale)); | ||
40 | + num_pages = (num + 1) * BIT_ULL(scale); | ||
41 | } | 19 | } |
42 | 20 | ||
43 | if (type == SMMU_CMD_TLBI_NH_VA) { | 21 | - indexmask_grainsize = (1ULL << (stride + 3)) - 1; |
22 | - indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1; | ||
23 | + indexmask_grainsize = MAKE_64BIT_MASK(0, stride + 3); | ||
24 | + indexmask = MAKE_64BIT_MASK(0, inputsize - (stride * (4 - level))); | ||
25 | |||
26 | /* Now we can extract the actual base address from the TTBR */ | ||
27 | descaddr = extract64(ttbr, 0, 48); | ||
44 | -- | 28 | -- |
45 | 2.20.1 | 29 | 2.25.1 |
46 | 30 | ||
47 | 31 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | In both cases, we can sink the write-back and perform | 3 | This field controls the output (intermediate) physical address size |
4 | the accumulate into the normal destination temps. | 4 | of the translation process. V8 requires to raise an AddressSize |
5 | fault if the page tables are programmed incorrectly, such that any | ||
6 | intermediate descriptor address, or the final translated address, | ||
7 | is out of range. | ||
5 | 8 | ||
9 | Add a PS field to ARMVAParameters, and properly compute outputsize | ||
10 | in get_phys_addr_lpae. Test the descaddr as extracted from TTBR | ||
11 | and from page table entries. | ||
12 | |||
13 | Restrict descaddrmask so that we won't raise the fault for v7. | ||
14 | |||
15 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
16 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 17 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | Message-id: 20201030022618.785675-11-richard.henderson@linaro.org | 18 | Message-id: 20220301215958.157011-8-richard.henderson@linaro.org |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 20 | --- |
11 | target/arm/translate-neon.c.inc | 23 +++++++++-------------- | 21 | target/arm/internals.h | 1 + |
12 | 1 file changed, 9 insertions(+), 14 deletions(-) | 22 | target/arm/helper.c | 72 ++++++++++++++++++++++++++++++++---------- |
23 | 2 files changed, 57 insertions(+), 16 deletions(-) | ||
13 | 24 | ||
14 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | 25 | diff --git a/target/arm/internals.h b/target/arm/internals.h |
15 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/translate-neon.c.inc | 27 | --- a/target/arm/internals.h |
17 | +++ b/target/arm/translate-neon.c.inc | 28 | +++ b/target/arm/internals.h |
18 | @@ -XXX,XX +XXX,XX @@ static bool do_long_3d(DisasContext *s, arg_3diff *a, | 29 | @@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id) |
19 | if (accfn) { | 30 | */ |
20 | tmp = tcg_temp_new_i64(); | 31 | typedef struct ARMVAParameters { |
21 | read_neon_element64(tmp, a->vd, 0, MO_64); | 32 | unsigned tsz : 8; |
22 | - accfn(tmp, tmp, rd0); | 33 | + unsigned ps : 3; |
23 | - write_neon_element64(tmp, a->vd, 0, MO_64); | 34 | unsigned select : 1; |
24 | + accfn(rd0, tmp, rd0); | 35 | bool tbi : 1; |
25 | read_neon_element64(tmp, a->vd, 1, MO_64); | 36 | bool epd : 1; |
26 | - accfn(tmp, tmp, rd1); | 37 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
27 | - write_neon_element64(tmp, a->vd, 1, MO_64); | 38 | index XXXXXXX..XXXXXXX 100644 |
28 | + accfn(rd1, tmp, rd1); | 39 | --- a/target/arm/helper.c |
29 | tcg_temp_free_i64(tmp); | 40 | +++ b/target/arm/helper.c |
30 | - } else { | 41 | @@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs) |
31 | - write_neon_element64(rd0, a->vd, 0, MO_64); | 42 | } |
32 | - write_neon_element64(rd1, a->vd, 1, MO_64); | 43 | #endif /* !CONFIG_USER_ONLY */ |
44 | |||
45 | +/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */ | ||
46 | +static const uint8_t pamax_map[] = { | ||
47 | + [0] = 32, | ||
48 | + [1] = 36, | ||
49 | + [2] = 40, | ||
50 | + [3] = 42, | ||
51 | + [4] = 44, | ||
52 | + [5] = 48, | ||
53 | +}; | ||
54 | + | ||
55 | /* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */ | ||
56 | unsigned int arm_pamax(ARMCPU *cpu) | ||
57 | { | ||
58 | - static const unsigned int pamax_map[] = { | ||
59 | - [0] = 32, | ||
60 | - [1] = 36, | ||
61 | - [2] = 40, | ||
62 | - [3] = 42, | ||
63 | - [4] = 44, | ||
64 | - [5] = 48, | ||
65 | - }; | ||
66 | unsigned int parange = | ||
67 | FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); | ||
68 | |||
69 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
70 | { | ||
71 | uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; | ||
72 | bool epd, hpd, using16k, using64k, tsz_oob; | ||
73 | - int select, tsz, tbi, max_tsz, min_tsz; | ||
74 | + int select, tsz, tbi, max_tsz, min_tsz, ps; | ||
75 | |||
76 | if (!regime_has_2_ranges(mmu_idx)) { | ||
77 | select = 0; | ||
78 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
79 | hpd = extract32(tcr, 24, 1); | ||
80 | } | ||
81 | epd = false; | ||
82 | + ps = extract32(tcr, 16, 3); | ||
83 | } else { | ||
84 | /* | ||
85 | * Bit 55 is always between the two regions, and is canonical for | ||
86 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
87 | epd = extract32(tcr, 23, 1); | ||
88 | hpd = extract64(tcr, 42, 1); | ||
89 | } | ||
90 | + ps = extract64(tcr, 32, 3); | ||
33 | } | 91 | } |
34 | 92 | ||
35 | + write_neon_element64(rd0, a->vd, 0, MO_64); | 93 | if (cpu_isar_feature(aa64_st, env_archcpu(env))) { |
36 | + write_neon_element64(rd1, a->vd, 1, MO_64); | 94 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, |
37 | tcg_temp_free_i64(rd0); | 95 | |
38 | tcg_temp_free_i64(rd1); | 96 | return (ARMVAParameters) { |
39 | 97 | .tsz = tsz, | |
40 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar_long(DisasContext *s, arg_2scalar *a, | 98 | + .ps = ps, |
41 | if (accfn) { | 99 | .select = select, |
42 | TCGv_i64 t64 = tcg_temp_new_i64(); | 100 | .tbi = tbi, |
43 | read_neon_element64(t64, a->vd, 0, MO_64); | 101 | .epd = epd, |
44 | - accfn(t64, t64, rn0_64); | 102 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
45 | - write_neon_element64(t64, a->vd, 0, MO_64); | 103 | |
46 | + accfn(rn0_64, t64, rn0_64); | 104 | /* TODO: This code does not support shareability levels. */ |
47 | read_neon_element64(t64, a->vd, 1, MO_64); | 105 | if (aarch64) { |
48 | - accfn(t64, t64, rn1_64); | 106 | + int ps; |
49 | - write_neon_element64(t64, a->vd, 1, MO_64); | ||
50 | + accfn(rn1_64, t64, rn1_64); | ||
51 | tcg_temp_free_i64(t64); | ||
52 | - } else { | ||
53 | - write_neon_element64(rn0_64, a->vd, 0, MO_64); | ||
54 | - write_neon_element64(rn1_64, a->vd, 1, MO_64); | ||
55 | } | ||
56 | + | 107 | + |
57 | + write_neon_element64(rn0_64, a->vd, 0, MO_64); | 108 | param = aa64_va_parameters(env, address, mmu_idx, |
58 | + write_neon_element64(rn1_64, a->vd, 1, MO_64); | 109 | access_type != MMU_INST_FETCH); |
59 | tcg_temp_free_i64(rn0_64); | 110 | level = 0; |
60 | tcg_temp_free_i64(rn1_64); | 111 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
61 | return true; | 112 | |
113 | addrsize = 64 - 8 * param.tbi; | ||
114 | inputsize = 64 - param.tsz; | ||
115 | - outputsize = arm_pamax(cpu); | ||
116 | + | ||
117 | + /* | ||
118 | + * Bound PS by PARANGE to find the effective output address size. | ||
119 | + * ID_AA64MMFR0 is a read-only register so values outside of the | ||
120 | + * supported mappings can be considered an implementation error. | ||
121 | + */ | ||
122 | + ps = FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); | ||
123 | + ps = MIN(ps, param.ps); | ||
124 | + assert(ps < ARRAY_SIZE(pamax_map)); | ||
125 | + outputsize = pamax_map[ps]; | ||
126 | } else { | ||
127 | param = aa32_va_parameters(env, address, mmu_idx); | ||
128 | level = 1; | ||
129 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, | ||
130 | |||
131 | /* Now we can extract the actual base address from the TTBR */ | ||
132 | descaddr = extract64(ttbr, 0, 48); | ||
133 | + | ||
134 | + /* | ||
135 | + * If the base address is out of range, raise AddressSizeFault. | ||
136 | + * In the pseudocode, this is !IsZero(baseregister<47:outputsize>), | ||
137 | + * but we've just cleared the bits above 47, so simplify the test. | ||
138 | + */ | ||
139 | + if (descaddr >> outputsize) { | ||
140 | + level = 0; | ||
141 | + fault_type = ARMFault_AddressSize; | ||
142 | + goto do_fault; | ||
143 | + } | ||
144 | + | ||
145 | /* | ||
146 | * We rely on this masking to clear the RES0 bits at the bottom of the TTBR | ||
147 | * and also to mask out CnP (bit 0) which could validly be non-zero. | ||
148 | */ | ||
149 | descaddr &= ~indexmask; | ||
150 | |||
151 | - /* The address field in the descriptor goes up to bit 39 for ARMv7 | ||
152 | - * but up to bit 47 for ARMv8, but we use the descaddrmask | ||
153 | - * up to bit 39 for AArch32, because we don't need other bits in that case | ||
154 | - * to construct next descriptor address (anyway they should be all zeroes). | ||
155 | + /* | ||
156 | + * For AArch32, the address field in the descriptor goes up to bit 39 | ||
157 | + * for both v7 and v8. However, for v8 the SBZ bits [47:40] must be 0 | ||
158 | + * or an AddressSize fault is raised. So for v8 we extract those SBZ | ||
159 | + * bits as part of the address, which will be checked via outputsize. | ||
160 | + * For AArch64, the address field always goes up to bit 47 (with extra | ||
161 | + * bits for FEAT_LPA placed elsewhere). AArch64 implies v8. | ||
162 | */ | ||
163 | - descaddrmask = ((1ull << (aarch64 ? 48 : 40)) - 1) & | ||
164 | - ~indexmask_grainsize; | ||
165 | + if (arm_feature(env, ARM_FEATURE_V8)) { | ||
166 | + descaddrmask = MAKE_64BIT_MASK(0, 48); | ||
167 | + } else { | ||
168 | + descaddrmask = MAKE_64BIT_MASK(0, 40); | ||
169 | + } | ||
170 | + descaddrmask &= ~indexmask_grainsize; | ||
171 | |||
172 | /* Secure accesses start with the page table in secure memory and | ||
173 | * can be downgraded to non-secure at any step. Non-secure accesses | ||
174 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, | ||
175 | /* Invalid, or the Reserved level 3 encoding */ | ||
176 | goto do_fault; | ||
177 | } | ||
178 | + | ||
179 | descaddr = descriptor & descaddrmask; | ||
180 | + if (descaddr >> outputsize) { | ||
181 | + fault_type = ARMFault_AddressSize; | ||
182 | + goto do_fault; | ||
183 | + } | ||
184 | |||
185 | if ((descriptor & 2) && (level < 3)) { | ||
186 | /* Table entry. The top five bits are attributes which may | ||
62 | -- | 187 | -- |
63 | 2.20.1 | 188 | 2.25.1 |
64 | 189 | ||
65 | 190 | diff view generated by jsdifflib |
1 | From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Secure mode is not exempted from checking SCR_EL3.TLOR, and in the | 3 | The original A.a revision of the AArch64 ARM required that we |
4 | future HCR_EL2.TLOR when S-EL2 is enabled. | 4 | force-extend the addresses in these registers from 49 bits. |
5 | This language has been loosened via a combination of IMPLEMENTATION | ||
6 | DEFINED and CONSTRAINTED UNPREDICTABLE to allow consideration of | ||
7 | the entire aligned address. | ||
5 | 8 | ||
6 | Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | 9 | This means that we do not have to consider whether or not FEAT_LVA |
10 | is enabled, and decide from which bit an address might need to be | ||
11 | extended. | ||
12 | |||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
14 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | Message-id: 20220301215958.157011-9-richard.henderson@linaro.org | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 17 | --- |
10 | target/arm/helper.c | 19 +++++-------------- | 18 | target/arm/helper.c | 32 ++++++++++++++++++++++++-------- |
11 | 1 file changed, 5 insertions(+), 14 deletions(-) | 19 | 1 file changed, 24 insertions(+), 8 deletions(-) |
12 | 20 | ||
13 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 21 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
14 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/target/arm/helper.c | 23 | --- a/target/arm/helper.c |
16 | +++ b/target/arm/helper.c | 24 | +++ b/target/arm/helper.c |
17 | @@ -XXX,XX +XXX,XX @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) | 25 | @@ -XXX,XX +XXX,XX @@ static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, |
18 | #endif | 26 | ARMCPU *cpu = env_archcpu(env); |
19 | 27 | int i = ri->crm; | |
20 | /* Shared logic between LORID and the rest of the LOR* registers. | 28 | |
21 | - * Secure state has already been delt with. | 29 | - /* Bits [63:49] are hardwired to the value of bit [48]; that is, the |
22 | + * Secure state exclusion has already been dealt with. | 30 | - * register reads and behaves as if values written are sign extended. |
23 | */ | 31 | + /* |
24 | -static CPAccessResult access_lor_ns(CPUARMState *env) | 32 | * Bits [1:0] are RES0. |
25 | +static CPAccessResult access_lor_ns(CPUARMState *env, | 33 | + * |
26 | + const ARMCPRegInfo *ri, bool isread) | 34 | + * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) |
27 | { | 35 | + * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if |
28 | int el = arm_current_el(env); | 36 | + * they contain the value written. It is CONSTRAINED UNPREDICTABLE |
29 | 37 | + * whether the RESS bits are ignored when comparing an address. | |
30 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult access_lor_ns(CPUARMState *env) | 38 | + * |
31 | return CP_ACCESS_OK; | 39 | + * Therefore we are allowed to compare the entire register, which lets |
32 | } | 40 | + * us avoid considering whether or not FEAT_LVA is actually enabled. |
33 | 41 | */ | |
34 | -static CPAccessResult access_lorid(CPUARMState *env, const ARMCPRegInfo *ri, | 42 | - value = sextract64(value, 0, 49) & ~3ULL; |
35 | - bool isread) | 43 | + value &= ~3ULL; |
36 | -{ | 44 | |
37 | - if (arm_is_secure_below_el3(env)) { | 45 | raw_write(env, ri, value); |
38 | - /* Access ok in secure mode. */ | 46 | hw_watchpoint_update(cpu, i); |
39 | - return CP_ACCESS_OK; | 47 | @@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n) |
40 | - } | 48 | case 0: /* unlinked address match */ |
41 | - return access_lor_ns(env); | 49 | case 1: /* linked address match */ |
42 | -} | 50 | { |
43 | - | 51 | - /* Bits [63:49] are hardwired to the value of bit [48]; that is, |
44 | static CPAccessResult access_lor_other(CPUARMState *env, | 52 | - * we behave as if the register was sign extended. Bits [1:0] are |
45 | const ARMCPRegInfo *ri, bool isread) | 53 | - * RES0. The BAS field is used to allow setting breakpoints on 16 |
46 | { | 54 | - * bit wide instructions; it is CONSTRAINED UNPREDICTABLE whether |
47 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult access_lor_other(CPUARMState *env, | 55 | + /* |
48 | /* Access denied in secure mode. */ | 56 | + * Bits [1:0] are RES0. |
49 | return CP_ACCESS_TRAP; | 57 | + * |
50 | } | 58 | + * It is IMPLEMENTATION DEFINED whether bits [63:49] |
51 | - return access_lor_ns(env); | 59 | + * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit |
52 | + return access_lor_ns(env, ri, isread); | 60 | + * of the VA field ([48] or [52] for FEAT_LVA), or whether the |
53 | } | 61 | + * value is read as written. It is CONSTRAINED UNPREDICTABLE |
54 | 62 | + * whether the RESS bits are ignored when comparing an address. | |
55 | /* | 63 | + * Therefore we are allowed to compare the entire register, which |
56 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lor_reginfo[] = { | 64 | + * lets us avoid considering whether FEAT_LVA is actually enabled. |
57 | .type = ARM_CP_CONST, .resetvalue = 0 }, | 65 | + * |
58 | { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64, | 66 | + * The BAS field is used to allow setting breakpoints on 16-bit |
59 | .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7, | 67 | + * wide instructions; it is CONSTRAINED UNPREDICTABLE whether |
60 | - .access = PL1_R, .accessfn = access_lorid, | 68 | * a bp will fire if the addresses covered by the bp and the addresses |
61 | + .access = PL1_R, .accessfn = access_lor_ns, | 69 | * covered by the insn overlap but the insn doesn't start at the |
62 | .type = ARM_CP_CONST, .resetvalue = 0 }, | 70 | * start of the bp address range. We choose to require the insn and |
63 | REGINFO_SENTINEL | 71 | @@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n) |
64 | }; | 72 | * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). |
73 | */ | ||
74 | int bas = extract64(bcr, 5, 4); | ||
75 | - addr = sextract64(bvr, 0, 49) & ~3ULL; | ||
76 | + addr = bvr & ~3ULL; | ||
77 | if (bas == 0) { | ||
78 | return; | ||
79 | } | ||
65 | -- | 80 | -- |
66 | 2.20.1 | 81 | 2.25.1 |
67 | |||
68 | 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 will shortly have users outside of translate-neon.c.inc. | 3 | This feature is relatively small, as it applies only to |
4 | 64k pages and thus requires no additional changes to the | ||
5 | table descriptor walking algorithm, only a change to the | ||
6 | minimum TSZ (which is the inverse of the maximum virtual | ||
7 | address space size). | ||
4 | 8 | ||
9 | Note that this feature widens VBAR_ELx, but we already | ||
10 | treat the register as being 64 bits wide. | ||
11 | |||
12 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 13 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | Message-id: 20201030022618.785675-3-richard.henderson@linaro.org | 14 | Message-id: 20220301215958.157011-10-richard.henderson@linaro.org |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 16 | --- |
10 | target/arm/translate.c | 20 ++++++++++++++++++++ | 17 | docs/system/arm/emulation.rst | 1 + |
11 | target/arm/translate-neon.c.inc | 19 ------------------- | 18 | target/arm/cpu-param.h | 2 +- |
12 | 2 files changed, 20 insertions(+), 19 deletions(-) | 19 | target/arm/cpu.h | 5 +++++ |
20 | target/arm/cpu64.c | 1 + | ||
21 | target/arm/helper.c | 9 ++++++++- | ||
22 | 5 files changed, 16 insertions(+), 2 deletions(-) | ||
13 | 23 | ||
14 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 24 | diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst |
15 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/translate.c | 26 | --- a/docs/system/arm/emulation.rst |
17 | +++ b/target/arm/translate.c | 27 | +++ b/docs/system/arm/emulation.rst |
18 | @@ -XXX,XX +XXX,XX @@ static long neon_full_reg_offset(unsigned reg) | 28 | @@ -XXX,XX +XXX,XX @@ the following architecture extensions: |
19 | return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); | 29 | - FEAT_LRCPC (Load-acquire RCpc instructions) |
30 | - FEAT_LRCPC2 (Load-acquire RCpc instructions v2) | ||
31 | - FEAT_LSE (Large System Extensions) | ||
32 | +- FEAT_LVA (Large Virtual Address space) | ||
33 | - FEAT_MTE (Memory Tagging Extension) | ||
34 | - FEAT_MTE2 (Memory Tagging Extension) | ||
35 | - FEAT_MTE3 (MTE Asymmetric Fault Handling) | ||
36 | diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/target/arm/cpu-param.h | ||
39 | +++ b/target/arm/cpu-param.h | ||
40 | @@ -XXX,XX +XXX,XX @@ | ||
41 | #ifdef TARGET_AARCH64 | ||
42 | # define TARGET_LONG_BITS 64 | ||
43 | # define TARGET_PHYS_ADDR_SPACE_BITS 48 | ||
44 | -# define TARGET_VIRT_ADDR_SPACE_BITS 48 | ||
45 | +# define TARGET_VIRT_ADDR_SPACE_BITS 52 | ||
46 | #else | ||
47 | # define TARGET_LONG_BITS 32 | ||
48 | # define TARGET_PHYS_ADDR_SPACE_BITS 40 | ||
49 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | ||
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/target/arm/cpu.h | ||
52 | +++ b/target/arm/cpu.h | ||
53 | @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) | ||
54 | return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; | ||
20 | } | 55 | } |
21 | 56 | ||
22 | +/* | 57 | +static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) |
23 | + * Return the offset of a 2**SIZE piece of a NEON register, at index ELE, | ||
24 | + * where 0 is the least significant end of the register. | ||
25 | + */ | ||
26 | +static long neon_element_offset(int reg, int element, MemOp size) | ||
27 | +{ | 58 | +{ |
28 | + int element_size = 1 << size; | 59 | + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; |
29 | + int ofs = element * element_size; | ||
30 | +#ifdef HOST_WORDS_BIGENDIAN | ||
31 | + /* | ||
32 | + * Calculate the offset assuming fully little-endian, | ||
33 | + * then XOR to account for the order of the 8-byte units. | ||
34 | + */ | ||
35 | + if (element_size < 8) { | ||
36 | + ofs ^= 8 - element_size; | ||
37 | + } | ||
38 | +#endif | ||
39 | + return neon_full_reg_offset(reg) + ofs; | ||
40 | +} | 60 | +} |
41 | + | 61 | + |
42 | static inline long vfp_reg_offset(bool dp, unsigned reg) | 62 | static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) |
43 | { | 63 | { |
44 | if (dp) { | 64 | return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; |
45 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | 65 | diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c |
46 | index XXXXXXX..XXXXXXX 100644 | 66 | index XXXXXXX..XXXXXXX 100644 |
47 | --- a/target/arm/translate-neon.c.inc | 67 | --- a/target/arm/cpu64.c |
48 | +++ b/target/arm/translate-neon.c.inc | 68 | +++ b/target/arm/cpu64.c |
49 | @@ -XXX,XX +XXX,XX @@ static inline int neon_3same_fp_size(DisasContext *s, int x) | 69 | @@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj) |
50 | #include "decode-neon-ls.c.inc" | 70 | t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); |
51 | #include "decode-neon-shared.c.inc" | 71 | t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */ |
52 | 72 | t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */ | |
53 | -/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE, | 73 | + t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */ |
54 | - * where 0 is the least significant end of the register. | 74 | cpu->isar.id_aa64mmfr2 = t; |
55 | - */ | 75 | |
56 | -static inline long | 76 | t = cpu->isar.id_aa64zfr0; |
57 | -neon_element_offset(int reg, int element, MemOp size) | 77 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
58 | -{ | 78 | index XXXXXXX..XXXXXXX 100644 |
59 | - int element_size = 1 << size; | 79 | --- a/target/arm/helper.c |
60 | - int ofs = element * element_size; | 80 | +++ b/target/arm/helper.c |
61 | -#ifdef HOST_WORDS_BIGENDIAN | 81 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, |
62 | - /* Calculate the offset assuming fully little-endian, | 82 | } else { |
63 | - * then XOR to account for the order of the 8-byte units. | 83 | max_tsz = 39; |
64 | - */ | 84 | } |
65 | - if (element_size < 8) { | 85 | - min_tsz = 16; /* TODO: ARMv8.2-LVA */ |
66 | - ofs ^= 8 - element_size; | 86 | + |
67 | - } | 87 | + min_tsz = 16; |
68 | -#endif | 88 | + if (using64k) { |
69 | - return neon_full_reg_offset(reg) + ofs; | 89 | + if (cpu_isar_feature(aa64_lva, env_archcpu(env))) { |
70 | -} | 90 | + min_tsz = 12; |
71 | - | 91 | + } |
72 | static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop) | 92 | + } |
73 | { | 93 | + /* TODO: FEAT_LPA2 */ |
74 | long offset = neon_element_offset(reg, ele, mop & MO_SIZE); | 94 | |
95 | if (tsz > max_tsz) { | ||
96 | tsz = max_tsz; | ||
75 | -- | 97 | -- |
76 | 2.20.1 | 98 | 2.25.1 |
77 | |||
78 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | We can use proper widening loads to extend 32-bit inputs, | 3 | This feature widens physical addresses (and intermediate physical |
4 | and skip the "widenfn" step. | 4 | addresses for 2-stage translation) from 48 to 52 bits, when using |
5 | 64k pages. The only thing left at this point is to handle the | ||
6 | extra bits in the TTBR and in the table descriptors. | ||
5 | 7 | ||
8 | Note that PAR_EL1 and HPFAR_EL2 are nominally extended, but we don't | ||
9 | mask out the high bits when writing to those registers, so no changes | ||
10 | are required there. | ||
11 | |||
12 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 13 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | Message-id: 20201030022618.785675-12-richard.henderson@linaro.org | 14 | Message-id: 20220301215958.157011-11-richard.henderson@linaro.org |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 16 | --- |
11 | target/arm/translate.c | 6 +++ | 17 | docs/system/arm/emulation.rst | 1 + |
12 | target/arm/translate-neon.c.inc | 66 ++++++++++++++++++--------------- | 18 | target/arm/cpu-param.h | 2 +- |
13 | 2 files changed, 43 insertions(+), 29 deletions(-) | 19 | target/arm/cpu64.c | 2 +- |
20 | target/arm/helper.c | 19 ++++++++++++++++--- | ||
21 | 4 files changed, 19 insertions(+), 5 deletions(-) | ||
14 | 22 | ||
15 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 23 | diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst |
16 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/target/arm/translate.c | 25 | --- a/docs/system/arm/emulation.rst |
18 | +++ b/target/arm/translate.c | 26 | +++ b/docs/system/arm/emulation.rst |
19 | @@ -XXX,XX +XXX,XX @@ static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) | 27 | @@ -XXX,XX +XXX,XX @@ the following architecture extensions: |
20 | long off = neon_element_offset(reg, ele, memop); | 28 | - FEAT_I8MM (AArch64 Int8 matrix multiplication instructions) |
21 | 29 | - FEAT_JSCVT (JavaScript conversion instructions) | |
22 | switch (memop) { | 30 | - FEAT_LOR (Limited ordering regions) |
23 | + case MO_SL: | 31 | +- FEAT_LPA (Large Physical Address space) |
24 | + tcg_gen_ld32s_i64(dest, cpu_env, off); | 32 | - FEAT_LRCPC (Load-acquire RCpc instructions) |
25 | + break; | 33 | - FEAT_LRCPC2 (Load-acquire RCpc instructions v2) |
26 | + case MO_UL: | 34 | - FEAT_LSE (Large System Extensions) |
27 | + tcg_gen_ld32u_i64(dest, cpu_env, off); | 35 | diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h |
28 | + break; | ||
29 | case MO_Q: | ||
30 | tcg_gen_ld_i64(dest, cpu_env, off); | ||
31 | break; | ||
32 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | ||
33 | index XXXXXXX..XXXXXXX 100644 | 36 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/target/arm/translate-neon.c.inc | 37 | --- a/target/arm/cpu-param.h |
35 | +++ b/target/arm/translate-neon.c.inc | 38 | +++ b/target/arm/cpu-param.h |
36 | @@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a) | 39 | @@ -XXX,XX +XXX,XX @@ |
37 | static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | 40 | |
38 | NeonGenWidenFn *widenfn, | 41 | #ifdef TARGET_AARCH64 |
39 | NeonGenTwo64OpFn *opfn, | 42 | # define TARGET_LONG_BITS 64 |
40 | - bool src1_wide) | 43 | -# define TARGET_PHYS_ADDR_SPACE_BITS 48 |
41 | + int src1_mop, int src2_mop) | 44 | +# define TARGET_PHYS_ADDR_SPACE_BITS 52 |
42 | { | 45 | # define TARGET_VIRT_ADDR_SPACE_BITS 52 |
43 | /* 3-regs different lengths, prewidening case (VADDL/VSUBL/VAADW/VSUBW) */ | 46 | #else |
44 | TCGv_i64 rn0_64, rn1_64, rm_64; | 47 | # define TARGET_LONG_BITS 32 |
45 | - TCGv_i32 rm; | 48 | diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c |
46 | 49 | index XXXXXXX..XXXXXXX 100644 | |
47 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | 50 | --- a/target/arm/cpu64.c |
48 | return false; | 51 | +++ b/target/arm/cpu64.c |
49 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | 52 | @@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj) |
50 | return false; | 53 | cpu->isar.id_aa64pfr1 = t; |
51 | } | 54 | |
52 | 55 | t = cpu->isar.id_aa64mmfr0; | |
53 | - if (!widenfn || !opfn) { | 56 | - t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */ |
54 | + if (!opfn) { | 57 | + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ |
55 | /* size == 3 case, which is an entirely different insn group */ | 58 | cpu->isar.id_aa64mmfr0 = t; |
56 | return false; | 59 | |
57 | } | 60 | t = cpu->isar.id_aa64mmfr1; |
58 | 61 | diff --git a/target/arm/helper.c b/target/arm/helper.c | |
59 | - if ((a->vd & 1) || (src1_wide && (a->vn & 1))) { | 62 | index XXXXXXX..XXXXXXX 100644 |
60 | + if ((a->vd & 1) || (src1_mop == MO_Q && (a->vn & 1))) { | 63 | --- a/target/arm/helper.c |
61 | return false; | 64 | +++ b/target/arm/helper.c |
62 | } | 65 | @@ -XXX,XX +XXX,XX @@ static const uint8_t pamax_map[] = { |
63 | 66 | [3] = 42, | |
64 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | 67 | [4] = 44, |
65 | rn1_64 = tcg_temp_new_i64(); | 68 | [5] = 48, |
66 | rm_64 = tcg_temp_new_i64(); | 69 | + [6] = 52, |
67 | 70 | }; | |
68 | - if (src1_wide) { | 71 | |
69 | - read_neon_element64(rn0_64, a->vn, 0, MO_64); | 72 | /* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */ |
70 | + if (src1_mop >= 0) { | 73 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
71 | + read_neon_element64(rn0_64, a->vn, 0, src1_mop); | 74 | descaddr = extract64(ttbr, 0, 48); |
72 | } else { | ||
73 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
74 | read_neon_element32(tmp, a->vn, 0, MO_32); | ||
75 | widenfn(rn0_64, tmp); | ||
76 | tcg_temp_free_i32(tmp); | ||
77 | } | ||
78 | - rm = tcg_temp_new_i32(); | ||
79 | - read_neon_element32(rm, a->vm, 0, MO_32); | ||
80 | + if (src2_mop >= 0) { | ||
81 | + read_neon_element64(rm_64, a->vm, 0, src2_mop); | ||
82 | + } else { | ||
83 | + TCGv_i32 tmp = tcg_temp_new_i32(); | ||
84 | + read_neon_element32(tmp, a->vm, 0, MO_32); | ||
85 | + widenfn(rm_64, tmp); | ||
86 | + tcg_temp_free_i32(tmp); | ||
87 | + } | ||
88 | |||
89 | - widenfn(rm_64, rm); | ||
90 | - tcg_temp_free_i32(rm); | ||
91 | opfn(rn0_64, rn0_64, rm_64); | ||
92 | 75 | ||
93 | /* | 76 | /* |
94 | * Load second pass inputs before storing the first pass result, to | 77 | - * If the base address is out of range, raise AddressSizeFault. |
95 | * avoid incorrect results if a narrow input overlaps with the result. | 78 | + * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [5:2] of TTBR. |
79 | + * | ||
80 | + * Otherwise, if the base address is out of range, raise AddressSizeFault. | ||
81 | * In the pseudocode, this is !IsZero(baseregister<47:outputsize>), | ||
82 | * but we've just cleared the bits above 47, so simplify the test. | ||
96 | */ | 83 | */ |
97 | - if (src1_wide) { | 84 | - if (descaddr >> outputsize) { |
98 | - read_neon_element64(rn1_64, a->vn, 1, MO_64); | 85 | + if (outputsize > 48) { |
99 | + if (src1_mop >= 0) { | 86 | + descaddr |= extract64(ttbr, 2, 4) << 48; |
100 | + read_neon_element64(rn1_64, a->vn, 1, src1_mop); | 87 | + } else if (descaddr >> outputsize) { |
101 | } else { | 88 | level = 0; |
102 | TCGv_i32 tmp = tcg_temp_new_i32(); | 89 | fault_type = ARMFault_AddressSize; |
103 | read_neon_element32(tmp, a->vn, 1, MO_32); | 90 | goto do_fault; |
104 | widenfn(rn1_64, tmp); | 91 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
105 | tcg_temp_free_i32(tmp); | 92 | } |
106 | } | 93 | |
107 | - rm = tcg_temp_new_i32(); | 94 | descaddr = descriptor & descaddrmask; |
108 | - read_neon_element32(rm, a->vm, 1, MO_32); | 95 | - if (descaddr >> outputsize) { |
109 | + if (src2_mop >= 0) { | 96 | + |
110 | + read_neon_element64(rm_64, a->vm, 1, src2_mop); | 97 | + /* |
111 | + } else { | 98 | + * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12] |
112 | + TCGv_i32 tmp = tcg_temp_new_i32(); | 99 | + * of descriptor. Otherwise, if descaddr is out of range, raise |
113 | + read_neon_element32(tmp, a->vm, 1, MO_32); | 100 | + * AddressSizeFault. |
114 | + widenfn(rm_64, tmp); | 101 | + */ |
115 | + tcg_temp_free_i32(tmp); | 102 | + if (outputsize > 48) { |
116 | + } | 103 | + descaddr |= extract64(descriptor, 12, 4) << 48; |
117 | 104 | + } else if (descaddr >> outputsize) { | |
118 | write_neon_element64(rn0_64, a->vd, 0, MO_64); | 105 | fault_type = ARMFault_AddressSize; |
119 | 106 | goto do_fault; | |
120 | - widenfn(rm_64, rm); | 107 | } |
121 | - tcg_temp_free_i32(rm); | ||
122 | opfn(rn1_64, rn1_64, rm_64); | ||
123 | write_neon_element64(rn1_64, a->vd, 1, MO_64); | ||
124 | |||
125 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
126 | return true; | ||
127 | } | ||
128 | |||
129 | -#define DO_PREWIDEN(INSN, S, EXT, OP, SRC1WIDE) \ | ||
130 | +#define DO_PREWIDEN(INSN, S, OP, SRC1WIDE, SIGN) \ | ||
131 | static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \ | ||
132 | { \ | ||
133 | static NeonGenWidenFn * const widenfn[] = { \ | ||
134 | gen_helper_neon_widen_##S##8, \ | ||
135 | gen_helper_neon_widen_##S##16, \ | ||
136 | - tcg_gen_##EXT##_i32_i64, \ | ||
137 | - NULL, \ | ||
138 | + NULL, NULL, \ | ||
139 | }; \ | ||
140 | static NeonGenTwo64OpFn * const addfn[] = { \ | ||
141 | gen_helper_neon_##OP##l_u16, \ | ||
142 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
143 | tcg_gen_##OP##_i64, \ | ||
144 | NULL, \ | ||
145 | }; \ | ||
146 | - return do_prewiden_3d(s, a, widenfn[a->size], \ | ||
147 | - addfn[a->size], SRC1WIDE); \ | ||
148 | + int narrow_mop = a->size == MO_32 ? MO_32 | SIGN : -1; \ | ||
149 | + return do_prewiden_3d(s, a, widenfn[a->size], addfn[a->size], \ | ||
150 | + SRC1WIDE ? MO_Q : narrow_mop, \ | ||
151 | + narrow_mop); \ | ||
152 | } | ||
153 | |||
154 | -DO_PREWIDEN(VADDL_S, s, ext, add, false) | ||
155 | -DO_PREWIDEN(VADDL_U, u, extu, add, false) | ||
156 | -DO_PREWIDEN(VSUBL_S, s, ext, sub, false) | ||
157 | -DO_PREWIDEN(VSUBL_U, u, extu, sub, false) | ||
158 | -DO_PREWIDEN(VADDW_S, s, ext, add, true) | ||
159 | -DO_PREWIDEN(VADDW_U, u, extu, add, true) | ||
160 | -DO_PREWIDEN(VSUBW_S, s, ext, sub, true) | ||
161 | -DO_PREWIDEN(VSUBW_U, u, extu, sub, true) | ||
162 | +DO_PREWIDEN(VADDL_S, s, add, false, MO_SIGN) | ||
163 | +DO_PREWIDEN(VADDL_U, u, add, false, 0) | ||
164 | +DO_PREWIDEN(VSUBL_S, s, sub, false, MO_SIGN) | ||
165 | +DO_PREWIDEN(VSUBL_U, u, sub, false, 0) | ||
166 | +DO_PREWIDEN(VADDW_S, s, add, true, MO_SIGN) | ||
167 | +DO_PREWIDEN(VADDW_U, u, add, true, 0) | ||
168 | +DO_PREWIDEN(VSUBW_S, s, sub, true, MO_SIGN) | ||
169 | +DO_PREWIDEN(VSUBW_U, u, sub, true, 0) | ||
170 | |||
171 | static bool do_narrow_3d(DisasContext *s, arg_3diff *a, | ||
172 | NeonGenTwo64OpFn *opfn, NeonGenNarrowFn *narrowfn) | ||
173 | -- | 108 | -- |
174 | 2.20.1 | 109 | 2.25.1 |
175 | |||
176 | diff view generated by jsdifflib |
1 | The helper functions for performing the udot/sdot operations against | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | a scalar were not using an address-swizzling macro when converting | ||
3 | the index of the scalar element into a pointer into the vm array. | ||
4 | This had no effect on little-endian hosts but meant we generated | ||
5 | incorrect results on big-endian hosts. | ||
6 | 2 | ||
7 | For these insns, the index is indexing over group of 4 8-bit values, | 3 | With FEAT_LPA2, rather than introducing translation level 4, |
8 | so 32 bits per indexed entity, and H4() is therefore what we want. | 4 | we introduce level -1, below the current level 0. Extend |
9 | (For Neon the only possible input indexes are 0 and 1.) | 5 | arm_fi_to_lfsc to handle these faults. |
10 | 6 | ||
7 | Assert that this new translation level does not leak into | ||
8 | fault types for which it is not defined, which allows some | ||
9 | masking of fi->level to be removed. | ||
10 | |||
11 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
13 | Message-id: 20220301215958.157011-12-richard.henderson@linaro.org | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
12 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
13 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
14 | Message-id: 20201028191712.4910-3-peter.maydell@linaro.org | ||
15 | --- | 15 | --- |
16 | target/arm/vec_helper.c | 4 ++-- | 16 | target/arm/internals.h | 35 +++++++++++++++++++++++++++++------ |
17 | 1 file changed, 2 insertions(+), 2 deletions(-) | 17 | 1 file changed, 29 insertions(+), 6 deletions(-) |
18 | 18 | ||
19 | diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c | 19 | diff --git a/target/arm/internals.h b/target/arm/internals.h |
20 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/vec_helper.c | 21 | --- a/target/arm/internals.h |
22 | +++ b/target/arm/vec_helper.c | 22 | +++ b/target/arm/internals.h |
23 | @@ -XXX,XX +XXX,XX @@ void HELPER(gvec_sdot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc) | 23 | @@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi) |
24 | intptr_t index = simd_data(desc); | 24 | case ARMFault_None: |
25 | uint32_t *d = vd; | 25 | return 0; |
26 | int8_t *n = vn; | 26 | case ARMFault_AddressSize: |
27 | - int8_t *m_indexed = (int8_t *)vm + index * 4; | 27 | - fsc = fi->level & 3; |
28 | + int8_t *m_indexed = (int8_t *)vm + H4(index) * 4; | 28 | + assert(fi->level >= -1 && fi->level <= 3); |
29 | 29 | + if (fi->level < 0) { | |
30 | /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd. | 30 | + fsc = 0b101001; |
31 | * Otherwise opr_sz is a multiple of 16. | 31 | + } else { |
32 | @@ -XXX,XX +XXX,XX @@ void HELPER(gvec_udot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc) | 32 | + fsc = fi->level; |
33 | intptr_t index = simd_data(desc); | 33 | + } |
34 | uint32_t *d = vd; | 34 | break; |
35 | uint8_t *n = vn; | 35 | case ARMFault_AccessFlag: |
36 | - uint8_t *m_indexed = (uint8_t *)vm + index * 4; | 36 | - fsc = (fi->level & 3) | (0x2 << 2); |
37 | + uint8_t *m_indexed = (uint8_t *)vm + H4(index) * 4; | 37 | + assert(fi->level >= 0 && fi->level <= 3); |
38 | 38 | + fsc = 0b001000 | fi->level; | |
39 | /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd. | 39 | break; |
40 | * Otherwise opr_sz is a multiple of 16. | 40 | case ARMFault_Permission: |
41 | - fsc = (fi->level & 3) | (0x3 << 2); | ||
42 | + assert(fi->level >= 0 && fi->level <= 3); | ||
43 | + fsc = 0b001100 | fi->level; | ||
44 | break; | ||
45 | case ARMFault_Translation: | ||
46 | - fsc = (fi->level & 3) | (0x1 << 2); | ||
47 | + assert(fi->level >= -1 && fi->level <= 3); | ||
48 | + if (fi->level < 0) { | ||
49 | + fsc = 0b101011; | ||
50 | + } else { | ||
51 | + fsc = 0b000100 | fi->level; | ||
52 | + } | ||
53 | break; | ||
54 | case ARMFault_SyncExternal: | ||
55 | fsc = 0x10 | (fi->ea << 12); | ||
56 | break; | ||
57 | case ARMFault_SyncExternalOnWalk: | ||
58 | - fsc = (fi->level & 3) | (0x5 << 2) | (fi->ea << 12); | ||
59 | + assert(fi->level >= -1 && fi->level <= 3); | ||
60 | + if (fi->level < 0) { | ||
61 | + fsc = 0b010011; | ||
62 | + } else { | ||
63 | + fsc = 0b010100 | fi->level; | ||
64 | + } | ||
65 | + fsc |= fi->ea << 12; | ||
66 | break; | ||
67 | case ARMFault_SyncParity: | ||
68 | fsc = 0x18; | ||
69 | break; | ||
70 | case ARMFault_SyncParityOnWalk: | ||
71 | - fsc = (fi->level & 3) | (0x7 << 2); | ||
72 | + assert(fi->level >= -1 && fi->level <= 3); | ||
73 | + if (fi->level < 0) { | ||
74 | + fsc = 0b011011; | ||
75 | + } else { | ||
76 | + fsc = 0b011100 | fi->level; | ||
77 | + } | ||
78 | break; | ||
79 | case ARMFault_AsyncParity: | ||
80 | fsc = 0x19; | ||
41 | -- | 81 | -- |
42 | 2.20.1 | 82 | 2.25.1 |
43 | |||
44 | 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 seems a bit more readable than using offsetof CPU_DoubleU. | 3 | Merge tlbi_aa64_range_get_length and tlbi_aa64_range_get_base, |
4 | returning a structure containing both results. Pass in the | ||
5 | ARMMMUIdx, rather than the digested two_ranges boolean. | ||
4 | 6 | ||
7 | This is in preparation for FEAT_LPA2, where the interpretation | ||
8 | of 'value' depends on the effective value of DS for the regime. | ||
9 | |||
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 11 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | Message-id: 20201030022618.785675-5-richard.henderson@linaro.org | 12 | Message-id: 20220301215958.157011-13-richard.henderson@linaro.org |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 14 | --- |
10 | target/arm/translate.c | 13 ++++--------- | 15 | target/arm/helper.c | 58 +++++++++++++++++++-------------------------- |
11 | 1 file changed, 4 insertions(+), 9 deletions(-) | 16 | 1 file changed, 24 insertions(+), 34 deletions(-) |
12 | 17 | ||
13 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 18 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
14 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/target/arm/translate.c | 20 | --- a/target/arm/helper.c |
16 | +++ b/target/arm/translate.c | 21 | +++ b/target/arm/helper.c |
17 | @@ -XXX,XX +XXX,XX @@ static long neon_element_offset(int reg, int element, MemOp size) | 22 | @@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
18 | return neon_full_reg_offset(reg) + ofs; | ||
19 | } | 23 | } |
20 | 24 | ||
21 | -static inline long vfp_reg_offset(bool dp, unsigned reg) | 25 | #ifdef TARGET_AARCH64 |
22 | +/* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */ | 26 | -static uint64_t tlbi_aa64_range_get_length(CPUARMState *env, |
23 | +static long vfp_reg_offset(bool dp, unsigned reg) | 27 | - uint64_t value) |
28 | -{ | ||
29 | - unsigned int page_shift; | ||
30 | - unsigned int page_size_granule; | ||
31 | - uint64_t num; | ||
32 | - uint64_t scale; | ||
33 | - uint64_t exponent; | ||
34 | +typedef struct { | ||
35 | + uint64_t base; | ||
36 | uint64_t length; | ||
37 | +} TLBIRange; | ||
38 | + | ||
39 | +static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, | ||
40 | + uint64_t value) | ||
41 | +{ | ||
42 | + unsigned int page_size_granule, page_shift, num, scale, exponent; | ||
43 | + TLBIRange ret = { }; | ||
44 | |||
45 | - num = extract64(value, 39, 5); | ||
46 | - scale = extract64(value, 44, 2); | ||
47 | page_size_granule = extract64(value, 46, 2); | ||
48 | |||
49 | if (page_size_granule == 0) { | ||
50 | qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n", | ||
51 | page_size_granule); | ||
52 | - return 0; | ||
53 | + return ret; | ||
54 | } | ||
55 | |||
56 | page_shift = (page_size_granule - 1) * 2 + 12; | ||
57 | - | ||
58 | + num = extract64(value, 39, 5); | ||
59 | + scale = extract64(value, 44, 2); | ||
60 | exponent = (5 * scale) + 1; | ||
61 | - length = (num + 1) << (exponent + page_shift); | ||
62 | |||
63 | - return length; | ||
64 | -} | ||
65 | + ret.length = (num + 1) << (exponent + page_shift); | ||
66 | |||
67 | -static uint64_t tlbi_aa64_range_get_base(CPUARMState *env, uint64_t value, | ||
68 | - bool two_ranges) | ||
69 | -{ | ||
70 | - /* TODO: ARMv8.7 FEAT_LPA2 */ | ||
71 | - uint64_t pageaddr; | ||
72 | - | ||
73 | - if (two_ranges) { | ||
74 | - pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS; | ||
75 | + if (regime_has_2_ranges(mmuidx)) { | ||
76 | + ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS; | ||
77 | } else { | ||
78 | - pageaddr = extract64(value, 0, 37) << TARGET_PAGE_BITS; | ||
79 | + ret.base = extract64(value, 0, 37) << TARGET_PAGE_BITS; | ||
80 | } | ||
81 | |||
82 | - return pageaddr; | ||
83 | + return ret; | ||
84 | } | ||
85 | |||
86 | static void do_rvae_write(CPUARMState *env, uint64_t value, | ||
87 | int idxmap, bool synced) | ||
24 | { | 88 | { |
25 | if (dp) { | 89 | ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap); |
26 | - return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); | 90 | - bool two_ranges = regime_has_2_ranges(one_idx); |
27 | + return neon_element_offset(reg, 0, MO_64); | 91 | - uint64_t baseaddr, length; |
92 | + TLBIRange range; | ||
93 | int bits; | ||
94 | |||
95 | - baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges); | ||
96 | - length = tlbi_aa64_range_get_length(env, value); | ||
97 | - bits = tlbbits_for_regime(env, one_idx, baseaddr); | ||
98 | + range = tlbi_aa64_get_range(env, one_idx, value); | ||
99 | + bits = tlbbits_for_regime(env, one_idx, range.base); | ||
100 | |||
101 | if (synced) { | ||
102 | tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env), | ||
103 | - baseaddr, | ||
104 | - length, | ||
105 | + range.base, | ||
106 | + range.length, | ||
107 | idxmap, | ||
108 | bits); | ||
28 | } else { | 109 | } else { |
29 | - long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]); | 110 | - tlb_flush_range_by_mmuidx(env_cpu(env), baseaddr, |
30 | - if (reg & 1) { | 111 | - length, idxmap, bits); |
31 | - ofs += offsetof(CPU_DoubleU, l.upper); | 112 | + tlb_flush_range_by_mmuidx(env_cpu(env), range.base, |
32 | - } else { | 113 | + range.length, idxmap, bits); |
33 | - ofs += offsetof(CPU_DoubleU, l.lower); | ||
34 | - } | ||
35 | - return ofs; | ||
36 | + return neon_element_offset(reg >> 1, reg & 1, MO_32); | ||
37 | } | 114 | } |
38 | } | 115 | } |
39 | 116 | ||
40 | -- | 117 | -- |
41 | 2.20.1 | 118 | 2.25.1 |
42 | |||
43 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Model these off the aa64 read/write_vec_element functions. | 3 | The shift of the BaseADDR field depends on the translation |
4 | Use it within translate-neon.c.inc. The new functions do | 4 | granule in use. |
5 | not allocate or free temps, so this rearranges the calling | ||
6 | code a bit. | ||
7 | 5 | ||
6 | Fixes: 84940ed8255 ("target/arm: Add support for FEAT_TLBIRANGE") | ||
7 | Reported-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
9 | Message-id: 20201030022618.785675-6-richard.henderson@linaro.org | 10 | Message-id: 20220301215958.157011-14-richard.henderson@linaro.org |
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
12 | --- | 12 | --- |
13 | target/arm/translate.c | 26 ++++ | 13 | target/arm/helper.c | 5 +++-- |
14 | target/arm/translate-neon.c.inc | 256 ++++++++++++++++++++------------ | 14 | 1 file changed, 3 insertions(+), 2 deletions(-) |
15 | 2 files changed, 183 insertions(+), 99 deletions(-) | ||
16 | 15 | ||
17 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 16 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
18 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/target/arm/translate.c | 18 | --- a/target/arm/helper.c |
20 | +++ b/target/arm/translate.c | 19 | +++ b/target/arm/helper.c |
21 | @@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg32(TCGv_i32 var, int reg) | 20 | @@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, |
22 | tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 21 | ret.length = (num + 1) << (exponent + page_shift); |
23 | } | 22 | |
24 | 23 | if (regime_has_2_ranges(mmuidx)) { | |
25 | +static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp size) | 24 | - ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS; |
26 | +{ | 25 | + ret.base = sextract64(value, 0, 37); |
27 | + long off = neon_element_offset(reg, ele, size); | 26 | } else { |
28 | + | 27 | - ret.base = extract64(value, 0, 37) << TARGET_PAGE_BITS; |
29 | + switch (size) { | 28 | + ret.base = extract64(value, 0, 37); |
30 | + case MO_32: | ||
31 | + tcg_gen_ld_i32(dest, cpu_env, off); | ||
32 | + break; | ||
33 | + default: | ||
34 | + g_assert_not_reached(); | ||
35 | + } | ||
36 | +} | ||
37 | + | ||
38 | +static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp size) | ||
39 | +{ | ||
40 | + long off = neon_element_offset(reg, ele, size); | ||
41 | + | ||
42 | + switch (size) { | ||
43 | + case MO_32: | ||
44 | + tcg_gen_st_i32(src, cpu_env, off); | ||
45 | + break; | ||
46 | + default: | ||
47 | + g_assert_not_reached(); | ||
48 | + } | ||
49 | +} | ||
50 | + | ||
51 | static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
52 | { | ||
53 | TCGv_ptr ret = tcg_temp_new_ptr(); | ||
54 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/target/arm/translate-neon.c.inc | ||
57 | +++ b/target/arm/translate-neon.c.inc | ||
58 | @@ -XXX,XX +XXX,XX @@ static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn) | ||
59 | * early. Since Q is 0 there are always just two passes, so instead | ||
60 | * of a complicated loop over each pass we just unroll. | ||
61 | */ | ||
62 | - tmp = neon_load_reg(a->vn, 0); | ||
63 | - tmp2 = neon_load_reg(a->vn, 1); | ||
64 | + tmp = tcg_temp_new_i32(); | ||
65 | + tmp2 = tcg_temp_new_i32(); | ||
66 | + tmp3 = tcg_temp_new_i32(); | ||
67 | + | ||
68 | + read_neon_element32(tmp, a->vn, 0, MO_32); | ||
69 | + read_neon_element32(tmp2, a->vn, 1, MO_32); | ||
70 | fn(tmp, tmp, tmp2); | ||
71 | - tcg_temp_free_i32(tmp2); | ||
72 | |||
73 | - tmp3 = neon_load_reg(a->vm, 0); | ||
74 | - tmp2 = neon_load_reg(a->vm, 1); | ||
75 | + read_neon_element32(tmp3, a->vm, 0, MO_32); | ||
76 | + read_neon_element32(tmp2, a->vm, 1, MO_32); | ||
77 | fn(tmp3, tmp3, tmp2); | ||
78 | - tcg_temp_free_i32(tmp2); | ||
79 | |||
80 | - neon_store_reg(a->vd, 0, tmp); | ||
81 | - neon_store_reg(a->vd, 1, tmp3); | ||
82 | + write_neon_element32(tmp, a->vd, 0, MO_32); | ||
83 | + write_neon_element32(tmp3, a->vd, 1, MO_32); | ||
84 | + | ||
85 | + tcg_temp_free_i32(tmp); | ||
86 | + tcg_temp_free_i32(tmp2); | ||
87 | + tcg_temp_free_i32(tmp3); | ||
88 | return true; | ||
89 | } | ||
90 | |||
91 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a, | ||
92 | * 2-reg-and-shift operations, size < 3 case, where the | ||
93 | * helper needs to be passed cpu_env. | ||
94 | */ | ||
95 | - TCGv_i32 constimm; | ||
96 | + TCGv_i32 constimm, tmp; | ||
97 | int pass; | ||
98 | |||
99 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
100 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a, | ||
101 | * by immediate using the variable shift operations. | ||
102 | */ | ||
103 | constimm = tcg_const_i32(dup_const(a->size, a->shift)); | ||
104 | + tmp = tcg_temp_new_i32(); | ||
105 | |||
106 | for (pass = 0; pass < (a->q ? 4 : 2); pass++) { | ||
107 | - TCGv_i32 tmp = neon_load_reg(a->vm, pass); | ||
108 | + read_neon_element32(tmp, a->vm, pass, MO_32); | ||
109 | fn(tmp, cpu_env, tmp, constimm); | ||
110 | - neon_store_reg(a->vd, pass, tmp); | ||
111 | + write_neon_element32(tmp, a->vd, pass, MO_32); | ||
112 | } | 29 | } |
113 | + tcg_temp_free_i32(tmp); | 30 | + ret.base <<= page_shift; |
114 | tcg_temp_free_i32(constimm); | 31 | |
115 | return true; | 32 | return ret; |
116 | } | ||
117 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, | ||
118 | constimm = tcg_const_i64(-a->shift); | ||
119 | rm1 = tcg_temp_new_i64(); | ||
120 | rm2 = tcg_temp_new_i64(); | ||
121 | + rd = tcg_temp_new_i32(); | ||
122 | |||
123 | /* Load both inputs first to avoid potential overwrite if rm == rd */ | ||
124 | neon_load_reg64(rm1, a->vm); | ||
125 | neon_load_reg64(rm2, a->vm + 1); | ||
126 | |||
127 | shiftfn(rm1, rm1, constimm); | ||
128 | - rd = tcg_temp_new_i32(); | ||
129 | narrowfn(rd, cpu_env, rm1); | ||
130 | - neon_store_reg(a->vd, 0, rd); | ||
131 | + write_neon_element32(rd, a->vd, 0, MO_32); | ||
132 | |||
133 | shiftfn(rm2, rm2, constimm); | ||
134 | - rd = tcg_temp_new_i32(); | ||
135 | narrowfn(rd, cpu_env, rm2); | ||
136 | - neon_store_reg(a->vd, 1, rd); | ||
137 | + write_neon_element32(rd, a->vd, 1, MO_32); | ||
138 | |||
139 | + tcg_temp_free_i32(rd); | ||
140 | tcg_temp_free_i64(rm1); | ||
141 | tcg_temp_free_i64(rm2); | ||
142 | tcg_temp_free_i64(constimm); | ||
143 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, | ||
144 | constimm = tcg_const_i32(imm); | ||
145 | |||
146 | /* Load all inputs first to avoid potential overwrite */ | ||
147 | - rm1 = neon_load_reg(a->vm, 0); | ||
148 | - rm2 = neon_load_reg(a->vm, 1); | ||
149 | - rm3 = neon_load_reg(a->vm + 1, 0); | ||
150 | - rm4 = neon_load_reg(a->vm + 1, 1); | ||
151 | + rm1 = tcg_temp_new_i32(); | ||
152 | + rm2 = tcg_temp_new_i32(); | ||
153 | + rm3 = tcg_temp_new_i32(); | ||
154 | + rm4 = tcg_temp_new_i32(); | ||
155 | + read_neon_element32(rm1, a->vm, 0, MO_32); | ||
156 | + read_neon_element32(rm2, a->vm, 1, MO_32); | ||
157 | + read_neon_element32(rm3, a->vm, 2, MO_32); | ||
158 | + read_neon_element32(rm4, a->vm, 3, MO_32); | ||
159 | rtmp = tcg_temp_new_i64(); | ||
160 | |||
161 | shiftfn(rm1, rm1, constimm); | ||
162 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, | ||
163 | tcg_temp_free_i32(rm2); | ||
164 | |||
165 | narrowfn(rm1, cpu_env, rtmp); | ||
166 | - neon_store_reg(a->vd, 0, rm1); | ||
167 | + write_neon_element32(rm1, a->vd, 0, MO_32); | ||
168 | + tcg_temp_free_i32(rm1); | ||
169 | |||
170 | shiftfn(rm3, rm3, constimm); | ||
171 | shiftfn(rm4, rm4, constimm); | ||
172 | @@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, | ||
173 | |||
174 | narrowfn(rm3, cpu_env, rtmp); | ||
175 | tcg_temp_free_i64(rtmp); | ||
176 | - neon_store_reg(a->vd, 1, rm3); | ||
177 | + write_neon_element32(rm3, a->vd, 1, MO_32); | ||
178 | + tcg_temp_free_i32(rm3); | ||
179 | return true; | ||
180 | } | ||
181 | |||
182 | @@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a, | ||
183 | widen_mask = dup_const(a->size + 1, widen_mask); | ||
184 | } | ||
185 | |||
186 | - rm0 = neon_load_reg(a->vm, 0); | ||
187 | - rm1 = neon_load_reg(a->vm, 1); | ||
188 | + rm0 = tcg_temp_new_i32(); | ||
189 | + rm1 = tcg_temp_new_i32(); | ||
190 | + read_neon_element32(rm0, a->vm, 0, MO_32); | ||
191 | + read_neon_element32(rm1, a->vm, 1, MO_32); | ||
192 | tmp = tcg_temp_new_i64(); | ||
193 | |||
194 | widenfn(tmp, rm0); | ||
195 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
196 | if (src1_wide) { | ||
197 | neon_load_reg64(rn0_64, a->vn); | ||
198 | } else { | ||
199 | - TCGv_i32 tmp = neon_load_reg(a->vn, 0); | ||
200 | + TCGv_i32 tmp = tcg_temp_new_i32(); | ||
201 | + read_neon_element32(tmp, a->vn, 0, MO_32); | ||
202 | widenfn(rn0_64, tmp); | ||
203 | tcg_temp_free_i32(tmp); | ||
204 | } | ||
205 | - rm = neon_load_reg(a->vm, 0); | ||
206 | + rm = tcg_temp_new_i32(); | ||
207 | + read_neon_element32(rm, a->vm, 0, MO_32); | ||
208 | |||
209 | widenfn(rm_64, rm); | ||
210 | tcg_temp_free_i32(rm); | ||
211 | @@ -XXX,XX +XXX,XX @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, | ||
212 | if (src1_wide) { | ||
213 | neon_load_reg64(rn1_64, a->vn + 1); | ||
214 | } else { | ||
215 | - TCGv_i32 tmp = neon_load_reg(a->vn, 1); | ||
216 | + TCGv_i32 tmp = tcg_temp_new_i32(); | ||
217 | + read_neon_element32(tmp, a->vn, 1, MO_32); | ||
218 | widenfn(rn1_64, tmp); | ||
219 | tcg_temp_free_i32(tmp); | ||
220 | } | ||
221 | - rm = neon_load_reg(a->vm, 1); | ||
222 | + rm = tcg_temp_new_i32(); | ||
223 | + read_neon_element32(rm, a->vm, 1, MO_32); | ||
224 | |||
225 | neon_store_reg64(rn0_64, a->vd); | ||
226 | |||
227 | @@ -XXX,XX +XXX,XX @@ static bool do_narrow_3d(DisasContext *s, arg_3diff *a, | ||
228 | |||
229 | narrowfn(rd1, rn_64); | ||
230 | |||
231 | - neon_store_reg(a->vd, 0, rd0); | ||
232 | - neon_store_reg(a->vd, 1, rd1); | ||
233 | + write_neon_element32(rd0, a->vd, 0, MO_32); | ||
234 | + write_neon_element32(rd1, a->vd, 1, MO_32); | ||
235 | |||
236 | + tcg_temp_free_i32(rd0); | ||
237 | + tcg_temp_free_i32(rd1); | ||
238 | tcg_temp_free_i64(rn_64); | ||
239 | tcg_temp_free_i64(rm_64); | ||
240 | |||
241 | @@ -XXX,XX +XXX,XX @@ static bool do_long_3d(DisasContext *s, arg_3diff *a, | ||
242 | rd0 = tcg_temp_new_i64(); | ||
243 | rd1 = tcg_temp_new_i64(); | ||
244 | |||
245 | - rn = neon_load_reg(a->vn, 0); | ||
246 | - rm = neon_load_reg(a->vm, 0); | ||
247 | + rn = tcg_temp_new_i32(); | ||
248 | + rm = tcg_temp_new_i32(); | ||
249 | + read_neon_element32(rn, a->vn, 0, MO_32); | ||
250 | + read_neon_element32(rm, a->vm, 0, MO_32); | ||
251 | opfn(rd0, rn, rm); | ||
252 | - tcg_temp_free_i32(rn); | ||
253 | - tcg_temp_free_i32(rm); | ||
254 | |||
255 | - rn = neon_load_reg(a->vn, 1); | ||
256 | - rm = neon_load_reg(a->vm, 1); | ||
257 | + read_neon_element32(rn, a->vn, 1, MO_32); | ||
258 | + read_neon_element32(rm, a->vm, 1, MO_32); | ||
259 | opfn(rd1, rn, rm); | ||
260 | tcg_temp_free_i32(rn); | ||
261 | tcg_temp_free_i32(rm); | ||
262 | @@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var) | ||
263 | |||
264 | static inline TCGv_i32 neon_get_scalar(int size, int reg) | ||
265 | { | ||
266 | - TCGv_i32 tmp; | ||
267 | - if (size == 1) { | ||
268 | - tmp = neon_load_reg(reg & 7, reg >> 4); | ||
269 | + TCGv_i32 tmp = tcg_temp_new_i32(); | ||
270 | + if (size == MO_16) { | ||
271 | + read_neon_element32(tmp, reg & 7, reg >> 4, MO_32); | ||
272 | if (reg & 8) { | ||
273 | gen_neon_dup_high16(tmp); | ||
274 | } else { | ||
275 | gen_neon_dup_low16(tmp); | ||
276 | } | ||
277 | } else { | ||
278 | - tmp = neon_load_reg(reg & 15, reg >> 4); | ||
279 | + read_neon_element32(tmp, reg & 15, reg >> 4, MO_32); | ||
280 | } | ||
281 | return tmp; | ||
282 | } | ||
283 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar(DisasContext *s, arg_2scalar *a, | ||
284 | * perform an accumulation operation of that result into the | ||
285 | * destination. | ||
286 | */ | ||
287 | - TCGv_i32 scalar; | ||
288 | + TCGv_i32 scalar, tmp; | ||
289 | int pass; | ||
290 | |||
291 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
292 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar(DisasContext *s, arg_2scalar *a, | ||
293 | } | ||
294 | |||
295 | scalar = neon_get_scalar(a->size, a->vm); | ||
296 | + tmp = tcg_temp_new_i32(); | ||
297 | |||
298 | for (pass = 0; pass < (a->q ? 4 : 2); pass++) { | ||
299 | - TCGv_i32 tmp = neon_load_reg(a->vn, pass); | ||
300 | + read_neon_element32(tmp, a->vn, pass, MO_32); | ||
301 | opfn(tmp, tmp, scalar); | ||
302 | if (accfn) { | ||
303 | - TCGv_i32 rd = neon_load_reg(a->vd, pass); | ||
304 | + TCGv_i32 rd = tcg_temp_new_i32(); | ||
305 | + read_neon_element32(rd, a->vd, pass, MO_32); | ||
306 | accfn(tmp, rd, tmp); | ||
307 | tcg_temp_free_i32(rd); | ||
308 | } | ||
309 | - neon_store_reg(a->vd, pass, tmp); | ||
310 | + write_neon_element32(tmp, a->vd, pass, MO_32); | ||
311 | } | ||
312 | + tcg_temp_free_i32(tmp); | ||
313 | tcg_temp_free_i32(scalar); | ||
314 | return true; | ||
315 | } | ||
316 | @@ -XXX,XX +XXX,XX @@ static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a, | ||
317 | * performs a kind of fused op-then-accumulate using a helper | ||
318 | * function that takes all of rd, rn and the scalar at once. | ||
319 | */ | ||
320 | - TCGv_i32 scalar; | ||
321 | + TCGv_i32 scalar, rn, rd; | ||
322 | int pass; | ||
323 | |||
324 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
325 | @@ -XXX,XX +XXX,XX @@ static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a, | ||
326 | } | ||
327 | |||
328 | scalar = neon_get_scalar(a->size, a->vm); | ||
329 | + rn = tcg_temp_new_i32(); | ||
330 | + rd = tcg_temp_new_i32(); | ||
331 | |||
332 | for (pass = 0; pass < (a->q ? 4 : 2); pass++) { | ||
333 | - TCGv_i32 rn = neon_load_reg(a->vn, pass); | ||
334 | - TCGv_i32 rd = neon_load_reg(a->vd, pass); | ||
335 | + read_neon_element32(rn, a->vn, pass, MO_32); | ||
336 | + read_neon_element32(rd, a->vd, pass, MO_32); | ||
337 | opfn(rd, cpu_env, rn, scalar, rd); | ||
338 | - tcg_temp_free_i32(rn); | ||
339 | - neon_store_reg(a->vd, pass, rd); | ||
340 | + write_neon_element32(rd, a->vd, pass, MO_32); | ||
341 | } | ||
342 | + tcg_temp_free_i32(rn); | ||
343 | + tcg_temp_free_i32(rd); | ||
344 | tcg_temp_free_i32(scalar); | ||
345 | |||
346 | return true; | ||
347 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar_long(DisasContext *s, arg_2scalar *a, | ||
348 | scalar = neon_get_scalar(a->size, a->vm); | ||
349 | |||
350 | /* Load all inputs before writing any outputs, in case of overlap */ | ||
351 | - rn = neon_load_reg(a->vn, 0); | ||
352 | + rn = tcg_temp_new_i32(); | ||
353 | + read_neon_element32(rn, a->vn, 0, MO_32); | ||
354 | rn0_64 = tcg_temp_new_i64(); | ||
355 | opfn(rn0_64, rn, scalar); | ||
356 | - tcg_temp_free_i32(rn); | ||
357 | |||
358 | - rn = neon_load_reg(a->vn, 1); | ||
359 | + read_neon_element32(rn, a->vn, 1, MO_32); | ||
360 | rn1_64 = tcg_temp_new_i64(); | ||
361 | opfn(rn1_64, rn, scalar); | ||
362 | tcg_temp_free_i32(rn); | ||
363 | @@ -XXX,XX +XXX,XX @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a) | ||
364 | return false; | ||
365 | } | ||
366 | n <<= 3; | ||
367 | + tmp = tcg_temp_new_i32(); | ||
368 | if (a->op) { | ||
369 | - tmp = neon_load_reg(a->vd, 0); | ||
370 | + read_neon_element32(tmp, a->vd, 0, MO_32); | ||
371 | } else { | ||
372 | - tmp = tcg_temp_new_i32(); | ||
373 | tcg_gen_movi_i32(tmp, 0); | ||
374 | } | ||
375 | - tmp2 = neon_load_reg(a->vm, 0); | ||
376 | + tmp2 = tcg_temp_new_i32(); | ||
377 | + read_neon_element32(tmp2, a->vm, 0, MO_32); | ||
378 | ptr1 = vfp_reg_ptr(true, a->vn); | ||
379 | tmp4 = tcg_const_i32(n); | ||
380 | gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp4); | ||
381 | - tcg_temp_free_i32(tmp); | ||
382 | + | ||
383 | if (a->op) { | ||
384 | - tmp = neon_load_reg(a->vd, 1); | ||
385 | + read_neon_element32(tmp, a->vd, 1, MO_32); | ||
386 | } else { | ||
387 | - tmp = tcg_temp_new_i32(); | ||
388 | tcg_gen_movi_i32(tmp, 0); | ||
389 | } | ||
390 | - tmp3 = neon_load_reg(a->vm, 1); | ||
391 | + tmp3 = tcg_temp_new_i32(); | ||
392 | + read_neon_element32(tmp3, a->vm, 1, MO_32); | ||
393 | gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp4); | ||
394 | + tcg_temp_free_i32(tmp); | ||
395 | tcg_temp_free_i32(tmp4); | ||
396 | tcg_temp_free_ptr(ptr1); | ||
397 | - neon_store_reg(a->vd, 0, tmp2); | ||
398 | - neon_store_reg(a->vd, 1, tmp3); | ||
399 | - tcg_temp_free_i32(tmp); | ||
400 | + | ||
401 | + write_neon_element32(tmp2, a->vd, 0, MO_32); | ||
402 | + write_neon_element32(tmp3, a->vd, 1, MO_32); | ||
403 | + tcg_temp_free_i32(tmp2); | ||
404 | + tcg_temp_free_i32(tmp3); | ||
405 | return true; | ||
406 | } | ||
407 | |||
408 | @@ -XXX,XX +XXX,XX @@ static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a) | ||
409 | static bool trans_VREV64(DisasContext *s, arg_VREV64 *a) | ||
410 | { | ||
411 | int pass, half; | ||
412 | + TCGv_i32 tmp[2]; | ||
413 | |||
414 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
415 | return false; | ||
416 | @@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_VREV64 *a) | ||
417 | return true; | ||
418 | } | ||
419 | |||
420 | - for (pass = 0; pass < (a->q ? 2 : 1); pass++) { | ||
421 | - TCGv_i32 tmp[2]; | ||
422 | + tmp[0] = tcg_temp_new_i32(); | ||
423 | + tmp[1] = tcg_temp_new_i32(); | ||
424 | |||
425 | + for (pass = 0; pass < (a->q ? 2 : 1); pass++) { | ||
426 | for (half = 0; half < 2; half++) { | ||
427 | - tmp[half] = neon_load_reg(a->vm, pass * 2 + half); | ||
428 | + read_neon_element32(tmp[half], a->vm, pass * 2 + half, MO_32); | ||
429 | switch (a->size) { | ||
430 | case 0: | ||
431 | tcg_gen_bswap32_i32(tmp[half], tmp[half]); | ||
432 | @@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_VREV64 *a) | ||
433 | g_assert_not_reached(); | ||
434 | } | ||
435 | } | ||
436 | - neon_store_reg(a->vd, pass * 2, tmp[1]); | ||
437 | - neon_store_reg(a->vd, pass * 2 + 1, tmp[0]); | ||
438 | + write_neon_element32(tmp[1], a->vd, pass * 2, MO_32); | ||
439 | + write_neon_element32(tmp[0], a->vd, pass * 2 + 1, MO_32); | ||
440 | } | ||
441 | + | ||
442 | + tcg_temp_free_i32(tmp[0]); | ||
443 | + tcg_temp_free_i32(tmp[1]); | ||
444 | return true; | ||
445 | } | ||
446 | |||
447 | @@ -XXX,XX +XXX,XX @@ static bool do_2misc_pairwise(DisasContext *s, arg_2misc *a, | ||
448 | rm0_64 = tcg_temp_new_i64(); | ||
449 | rm1_64 = tcg_temp_new_i64(); | ||
450 | rd_64 = tcg_temp_new_i64(); | ||
451 | - tmp = neon_load_reg(a->vm, pass * 2); | ||
452 | + | ||
453 | + tmp = tcg_temp_new_i32(); | ||
454 | + read_neon_element32(tmp, a->vm, pass * 2, MO_32); | ||
455 | widenfn(rm0_64, tmp); | ||
456 | - tcg_temp_free_i32(tmp); | ||
457 | - tmp = neon_load_reg(a->vm, pass * 2 + 1); | ||
458 | + read_neon_element32(tmp, a->vm, pass * 2 + 1, MO_32); | ||
459 | widenfn(rm1_64, tmp); | ||
460 | tcg_temp_free_i32(tmp); | ||
461 | + | ||
462 | opfn(rd_64, rm0_64, rm1_64); | ||
463 | tcg_temp_free_i64(rm0_64); | ||
464 | tcg_temp_free_i64(rm1_64); | ||
465 | @@ -XXX,XX +XXX,XX @@ static bool do_vmovn(DisasContext *s, arg_2misc *a, | ||
466 | narrowfn(rd0, cpu_env, rm); | ||
467 | neon_load_reg64(rm, a->vm + 1); | ||
468 | narrowfn(rd1, cpu_env, rm); | ||
469 | - neon_store_reg(a->vd, 0, rd0); | ||
470 | - neon_store_reg(a->vd, 1, rd1); | ||
471 | + write_neon_element32(rd0, a->vd, 0, MO_32); | ||
472 | + write_neon_element32(rd1, a->vd, 1, MO_32); | ||
473 | + tcg_temp_free_i32(rd0); | ||
474 | + tcg_temp_free_i32(rd1); | ||
475 | tcg_temp_free_i64(rm); | ||
476 | return true; | ||
477 | } | ||
478 | @@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL(DisasContext *s, arg_2misc *a) | ||
479 | } | ||
480 | |||
481 | rd = tcg_temp_new_i64(); | ||
482 | + rm0 = tcg_temp_new_i32(); | ||
483 | + rm1 = tcg_temp_new_i32(); | ||
484 | |||
485 | - rm0 = neon_load_reg(a->vm, 0); | ||
486 | - rm1 = neon_load_reg(a->vm, 1); | ||
487 | + read_neon_element32(rm0, a->vm, 0, MO_32); | ||
488 | + read_neon_element32(rm1, a->vm, 1, MO_32); | ||
489 | |||
490 | widenfn(rd, rm0); | ||
491 | tcg_gen_shli_i64(rd, rd, 8 << a->size); | ||
492 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a) | ||
493 | |||
494 | fpst = fpstatus_ptr(FPST_STD); | ||
495 | ahp = get_ahp_flag(); | ||
496 | - tmp = neon_load_reg(a->vm, 0); | ||
497 | + tmp = tcg_temp_new_i32(); | ||
498 | + read_neon_element32(tmp, a->vm, 0, MO_32); | ||
499 | gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); | ||
500 | - tmp2 = neon_load_reg(a->vm, 1); | ||
501 | + tmp2 = tcg_temp_new_i32(); | ||
502 | + read_neon_element32(tmp2, a->vm, 1, MO_32); | ||
503 | gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp); | ||
504 | tcg_gen_shli_i32(tmp2, tmp2, 16); | ||
505 | tcg_gen_or_i32(tmp2, tmp2, tmp); | ||
506 | - tcg_temp_free_i32(tmp); | ||
507 | - tmp = neon_load_reg(a->vm, 2); | ||
508 | + read_neon_element32(tmp, a->vm, 2, MO_32); | ||
509 | gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); | ||
510 | - tmp3 = neon_load_reg(a->vm, 3); | ||
511 | - neon_store_reg(a->vd, 0, tmp2); | ||
512 | + tmp3 = tcg_temp_new_i32(); | ||
513 | + read_neon_element32(tmp3, a->vm, 3, MO_32); | ||
514 | + write_neon_element32(tmp2, a->vd, 0, MO_32); | ||
515 | + tcg_temp_free_i32(tmp2); | ||
516 | gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp); | ||
517 | tcg_gen_shli_i32(tmp3, tmp3, 16); | ||
518 | tcg_gen_or_i32(tmp3, tmp3, tmp); | ||
519 | - neon_store_reg(a->vd, 1, tmp3); | ||
520 | + write_neon_element32(tmp3, a->vd, 1, MO_32); | ||
521 | + tcg_temp_free_i32(tmp3); | ||
522 | tcg_temp_free_i32(tmp); | ||
523 | tcg_temp_free_i32(ahp); | ||
524 | tcg_temp_free_ptr(fpst); | ||
525 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a) | ||
526 | fpst = fpstatus_ptr(FPST_STD); | ||
527 | ahp = get_ahp_flag(); | ||
528 | tmp3 = tcg_temp_new_i32(); | ||
529 | - tmp = neon_load_reg(a->vm, 0); | ||
530 | - tmp2 = neon_load_reg(a->vm, 1); | ||
531 | + tmp2 = tcg_temp_new_i32(); | ||
532 | + tmp = tcg_temp_new_i32(); | ||
533 | + read_neon_element32(tmp, a->vm, 0, MO_32); | ||
534 | + read_neon_element32(tmp2, a->vm, 1, MO_32); | ||
535 | tcg_gen_ext16u_i32(tmp3, tmp); | ||
536 | gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); | ||
537 | - neon_store_reg(a->vd, 0, tmp3); | ||
538 | + write_neon_element32(tmp3, a->vd, 0, MO_32); | ||
539 | tcg_gen_shri_i32(tmp, tmp, 16); | ||
540 | gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp); | ||
541 | - neon_store_reg(a->vd, 1, tmp); | ||
542 | - tmp3 = tcg_temp_new_i32(); | ||
543 | + write_neon_element32(tmp, a->vd, 1, MO_32); | ||
544 | + tcg_temp_free_i32(tmp); | ||
545 | tcg_gen_ext16u_i32(tmp3, tmp2); | ||
546 | gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp); | ||
547 | - neon_store_reg(a->vd, 2, tmp3); | ||
548 | + write_neon_element32(tmp3, a->vd, 2, MO_32); | ||
549 | + tcg_temp_free_i32(tmp3); | ||
550 | tcg_gen_shri_i32(tmp2, tmp2, 16); | ||
551 | gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp); | ||
552 | - neon_store_reg(a->vd, 3, tmp2); | ||
553 | + write_neon_element32(tmp2, a->vd, 3, MO_32); | ||
554 | + tcg_temp_free_i32(tmp2); | ||
555 | tcg_temp_free_i32(ahp); | ||
556 | tcg_temp_free_ptr(fpst); | ||
557 | |||
558 | @@ -XXX,XX +XXX,XX @@ DO_2M_CRYPTO(SHA256SU0, aa32_sha2, 2) | ||
559 | |||
560 | static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn) | ||
561 | { | ||
562 | + TCGv_i32 tmp; | ||
563 | int pass; | ||
564 | |||
565 | /* Handle a 2-reg-misc operation by iterating 32 bits at a time */ | ||
566 | @@ -XXX,XX +XXX,XX @@ static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn) | ||
567 | return true; | ||
568 | } | ||
569 | |||
570 | + tmp = tcg_temp_new_i32(); | ||
571 | for (pass = 0; pass < (a->q ? 4 : 2); pass++) { | ||
572 | - TCGv_i32 tmp = neon_load_reg(a->vm, pass); | ||
573 | + read_neon_element32(tmp, a->vm, pass, MO_32); | ||
574 | fn(tmp, tmp); | ||
575 | - neon_store_reg(a->vd, pass, tmp); | ||
576 | + write_neon_element32(tmp, a->vd, pass, MO_32); | ||
577 | } | ||
578 | + tcg_temp_free_i32(tmp); | ||
579 | |||
580 | return true; | ||
581 | } | ||
582 | @@ -XXX,XX +XXX,XX @@ static bool trans_VTRN(DisasContext *s, arg_2misc *a) | ||
583 | return true; | ||
584 | } | ||
585 | |||
586 | - if (a->size == 2) { | ||
587 | + tmp = tcg_temp_new_i32(); | ||
588 | + tmp2 = tcg_temp_new_i32(); | ||
589 | + if (a->size == MO_32) { | ||
590 | for (pass = 0; pass < (a->q ? 4 : 2); pass += 2) { | ||
591 | - tmp = neon_load_reg(a->vm, pass); | ||
592 | - tmp2 = neon_load_reg(a->vd, pass + 1); | ||
593 | - neon_store_reg(a->vm, pass, tmp2); | ||
594 | - neon_store_reg(a->vd, pass + 1, tmp); | ||
595 | + read_neon_element32(tmp, a->vm, pass, MO_32); | ||
596 | + read_neon_element32(tmp2, a->vd, pass + 1, MO_32); | ||
597 | + write_neon_element32(tmp2, a->vm, pass, MO_32); | ||
598 | + write_neon_element32(tmp, a->vd, pass + 1, MO_32); | ||
599 | } | ||
600 | } else { | ||
601 | for (pass = 0; pass < (a->q ? 4 : 2); pass++) { | ||
602 | - tmp = neon_load_reg(a->vm, pass); | ||
603 | - tmp2 = neon_load_reg(a->vd, pass); | ||
604 | - if (a->size == 0) { | ||
605 | + read_neon_element32(tmp, a->vm, pass, MO_32); | ||
606 | + read_neon_element32(tmp2, a->vd, pass, MO_32); | ||
607 | + if (a->size == MO_8) { | ||
608 | gen_neon_trn_u8(tmp, tmp2); | ||
609 | } else { | ||
610 | gen_neon_trn_u16(tmp, tmp2); | ||
611 | } | ||
612 | - neon_store_reg(a->vm, pass, tmp2); | ||
613 | - neon_store_reg(a->vd, pass, tmp); | ||
614 | + write_neon_element32(tmp2, a->vm, pass, MO_32); | ||
615 | + write_neon_element32(tmp, a->vd, pass, MO_32); | ||
616 | } | ||
617 | } | ||
618 | + tcg_temp_free_i32(tmp); | ||
619 | + tcg_temp_free_i32(tmp2); | ||
620 | return true; | ||
621 | } | 33 | } |
622 | -- | 34 | -- |
623 | 2.20.1 | 35 | 2.25.1 |
624 | |||
625 | diff view generated by jsdifflib |
1 | From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | HCR should be applied when NS is set, not when it is cleared. | 3 | For FEAT_LPA2, we will need other ARMVAParameters, which themselves |
4 | depend on the translation granule in use. We might as well validate | ||
5 | that the given TG matches; the architecture "does not require that | ||
6 | the instruction invalidates any entries" if this is not true. | ||
4 | 7 | ||
5 | Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | ||
6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Message-id: 20220301215958.157011-15-richard.henderson@linaro.org | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | --- | 12 | --- |
9 | target/arm/helper.c | 5 ++--- | 13 | target/arm/helper.c | 10 +++++++--- |
10 | 1 file changed, 2 insertions(+), 3 deletions(-) | 14 | 1 file changed, 7 insertions(+), 3 deletions(-) |
11 | 15 | ||
12 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 16 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
13 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/target/arm/helper.c | 18 | --- a/target/arm/helper.c |
15 | +++ b/target/arm/helper.c | 19 | +++ b/target/arm/helper.c |
16 | @@ -XXX,XX +XXX,XX @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, | 20 | @@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, |
17 | 21 | uint64_t value) | |
18 | /* | ||
19 | * Non-IS variants of TLB operations are upgraded to | ||
20 | - * IS versions if we are at NS EL1 and HCR_EL2.FB is set to | ||
21 | + * IS versions if we are at EL1 and HCR_EL2.FB is effectively set to | ||
22 | * force broadcast of these operations. | ||
23 | */ | ||
24 | static bool tlb_force_broadcast(CPUARMState *env) | ||
25 | { | 22 | { |
26 | - return (env->cp15.hcr_el2 & HCR_FB) && | 23 | unsigned int page_size_granule, page_shift, num, scale, exponent; |
27 | - arm_current_el(env) == 1 && arm_is_secure_below_el3(env); | 24 | + /* Extract one bit to represent the va selector in use. */ |
28 | + return arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_FB); | 25 | + uint64_t select = sextract64(value, 36, 1); |
29 | } | 26 | + ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true); |
30 | 27 | TLBIRange ret = { }; | |
31 | static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, | 28 | |
29 | page_size_granule = extract64(value, 46, 2); | ||
30 | |||
31 | - if (page_size_granule == 0) { | ||
32 | - qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n", | ||
33 | + /* The granule encoded in value must match the granule in use. */ | ||
34 | + if (page_size_granule != (param.using64k ? 3 : param.using16k ? 2 : 1)) { | ||
35 | + qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n", | ||
36 | page_size_granule); | ||
37 | return ret; | ||
38 | } | ||
39 | @@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, | ||
40 | |||
41 | ret.length = (num + 1) << (exponent + page_shift); | ||
42 | |||
43 | - if (regime_has_2_ranges(mmuidx)) { | ||
44 | + if (param.select) { | ||
45 | ret.base = sextract64(value, 0, 37); | ||
46 | } else { | ||
47 | ret.base = extract64(value, 0, 37); | ||
32 | -- | 48 | -- |
33 | 2.20.1 | 49 | 2.25.1 |
34 | |||
35 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | These are the only users of neon_reg_offset, so remove that. | 3 | We support 16k pages, but do not advertize that in ID_AA64MMFR0. |
4 | |||
5 | The value 0 in the TGRAN*_2 fields indicates that stage2 lookups defer | ||
6 | to the same support as stage1 lookups. This setting is deprecated, so | ||
7 | indicate support for all stage2 page sizes directly. | ||
4 | 8 | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | Message-id: 20201030022618.785675-4-richard.henderson@linaro.org | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
11 | Message-id: 20220301215958.157011-16-richard.henderson@linaro.org | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 13 | --- |
10 | target/arm/translate.c | 14 ++------------ | 14 | target/arm/cpu64.c | 4 ++++ |
11 | 1 file changed, 2 insertions(+), 12 deletions(-) | 15 | 1 file changed, 4 insertions(+) |
12 | 16 | ||
13 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 17 | diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c |
14 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/target/arm/translate.c | 19 | --- a/target/arm/cpu64.c |
16 | +++ b/target/arm/translate.c | 20 | +++ b/target/arm/cpu64.c |
17 | @@ -XXX,XX +XXX,XX @@ static inline long vfp_reg_offset(bool dp, unsigned reg) | 21 | @@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj) |
18 | } | 22 | |
19 | } | 23 | t = cpu->isar.id_aa64mmfr0; |
20 | 24 | t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ | |
21 | -/* Return the offset of a 32-bit piece of a NEON register. | 25 | + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ |
22 | - zero is the least significant end of the register. */ | 26 | + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */ |
23 | -static inline long | 27 | + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */ |
24 | -neon_reg_offset (int reg, int n) | 28 | + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */ |
25 | -{ | 29 | cpu->isar.id_aa64mmfr0 = t; |
26 | - int sreg; | 30 | |
27 | - sreg = reg * 2 + n; | 31 | t = cpu->isar.id_aa64mmfr1; |
28 | - return vfp_reg_offset(0, sreg); | ||
29 | -} | ||
30 | - | ||
31 | static TCGv_i32 neon_load_reg(int reg, int pass) | ||
32 | { | ||
33 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
34 | - tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); | ||
35 | + tcg_gen_ld_i32(tmp, cpu_env, neon_element_offset(reg, pass, MO_32)); | ||
36 | return tmp; | ||
37 | } | ||
38 | |||
39 | static void neon_store_reg(int reg, int pass, TCGv_i32 var) | ||
40 | { | ||
41 | - tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); | ||
42 | + tcg_gen_st_i32(var, cpu_env, neon_element_offset(reg, pass, MO_32)); | ||
43 | tcg_temp_free_i32(var); | ||
44 | } | ||
45 | |||
46 | -- | 32 | -- |
47 | 2.20.1 | 33 | 2.25.1 |
48 | |||
49 | 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 function makes it clear that we're talking about the whole | 3 | This feature widens physical addresses (and intermediate physical |
4 | register, and not the 32-bit piece at index 0. This fixes a bug | 4 | addresses for 2-stage translation) from 48 to 52 bits, when using |
5 | when running on a big-endian host. | 5 | 4k or 16k pages. |
6 | 6 | ||
7 | This introduces the DS bit to TCR_ELx, which is RES0 unless the | ||
8 | page size is enabled and supports LPA2, resulting in the effective | ||
9 | value of DS for a given table walk. The DS bit changes the format | ||
10 | of the page table descriptor slightly, moving the PS field out to | ||
11 | TCR so that all pages have the same sharability and repurposing | ||
12 | those bits of the page table descriptor for the highest bits of | ||
13 | the output address. | ||
14 | |||
15 | Do not yet enable FEAT_LPA2; we need extra plumbing to avoid | ||
16 | tickling an old kernel bug. | ||
17 | |||
18 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 19 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
8 | Message-id: 20201030022618.785675-2-richard.henderson@linaro.org | 20 | Message-id: 20220301215958.157011-17-richard.henderson@linaro.org |
9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | --- | 22 | --- |
12 | target/arm/translate.c | 8 ++++++ | 23 | docs/system/arm/emulation.rst | 1 + |
13 | target/arm/translate-neon.c.inc | 44 ++++++++++++++++----------------- | 24 | target/arm/cpu.h | 22 ++++++++ |
14 | target/arm/translate-vfp.c.inc | 2 +- | 25 | target/arm/internals.h | 2 + |
15 | 3 files changed, 31 insertions(+), 23 deletions(-) | 26 | target/arm/helper.c | 102 +++++++++++++++++++++++++++++----- |
16 | 27 | 4 files changed, 112 insertions(+), 15 deletions(-) | |
17 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 28 | |
29 | diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst | ||
18 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/target/arm/translate.c | 31 | --- a/docs/system/arm/emulation.rst |
20 | +++ b/target/arm/translate.c | 32 | +++ b/docs/system/arm/emulation.rst |
21 | @@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm) | 33 | @@ -XXX,XX +XXX,XX @@ the following architecture extensions: |
22 | unallocated_encoding(s); | 34 | - FEAT_JSCVT (JavaScript conversion instructions) |
35 | - FEAT_LOR (Limited ordering regions) | ||
36 | - FEAT_LPA (Large Physical Address space) | ||
37 | +- FEAT_LPA2 (Large Physical and virtual Address space v2) | ||
38 | - FEAT_LRCPC (Load-acquire RCpc instructions) | ||
39 | - FEAT_LRCPC2 (Load-acquire RCpc instructions v2) | ||
40 | - FEAT_LSE (Large System Extensions) | ||
41 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/target/arm/cpu.h | ||
44 | +++ b/target/arm/cpu.h | ||
45 | @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) | ||
46 | return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; | ||
23 | } | 47 | } |
24 | 48 | ||
25 | +/* | 49 | +static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) |
26 | + * Return the offset of a "full" NEON Dreg. | ||
27 | + */ | ||
28 | +static long neon_full_reg_offset(unsigned reg) | ||
29 | +{ | 50 | +{ |
30 | + return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); | 51 | + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; |
31 | +} | 52 | +} |
32 | + | 53 | + |
33 | static inline long vfp_reg_offset(bool dp, unsigned reg) | 54 | +static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) |
55 | +{ | ||
56 | + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); | ||
57 | + return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); | ||
58 | +} | ||
59 | + | ||
60 | +static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) | ||
61 | +{ | ||
62 | + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; | ||
63 | +} | ||
64 | + | ||
65 | +static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) | ||
66 | +{ | ||
67 | + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); | ||
68 | + return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); | ||
69 | +} | ||
70 | + | ||
71 | static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) | ||
34 | { | 72 | { |
35 | if (dp) { | 73 | return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; |
36 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | 74 | diff --git a/target/arm/internals.h b/target/arm/internals.h |
37 | index XXXXXXX..XXXXXXX 100644 | 75 | index XXXXXXX..XXXXXXX 100644 |
38 | --- a/target/arm/translate-neon.c.inc | 76 | --- a/target/arm/internals.h |
39 | +++ b/target/arm/translate-neon.c.inc | 77 | +++ b/target/arm/internals.h |
40 | @@ -XXX,XX +XXX,XX @@ neon_element_offset(int reg, int element, MemOp size) | 78 | @@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id) |
41 | ofs ^= 8 - element_size; | 79 | typedef struct ARMVAParameters { |
42 | } | 80 | unsigned tsz : 8; |
43 | #endif | 81 | unsigned ps : 3; |
44 | - return neon_reg_offset(reg, 0) + ofs; | 82 | + unsigned sh : 2; |
45 | + return neon_full_reg_offset(reg) + ofs; | 83 | unsigned select : 1; |
84 | bool tbi : 1; | ||
85 | bool epd : 1; | ||
86 | @@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters { | ||
87 | bool using16k : 1; | ||
88 | bool using64k : 1; | ||
89 | bool tsz_oob : 1; /* tsz has been clamped to legal range */ | ||
90 | + bool ds : 1; | ||
91 | } ARMVAParameters; | ||
92 | |||
93 | ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
94 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
95 | index XXXXXXX..XXXXXXX 100644 | ||
96 | --- a/target/arm/helper.c | ||
97 | +++ b/target/arm/helper.c | ||
98 | @@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, | ||
99 | } else { | ||
100 | ret.base = extract64(value, 0, 37); | ||
101 | } | ||
102 | + if (param.ds) { | ||
103 | + /* | ||
104 | + * With DS=1, BaseADDR is always shifted 16 so that it is able | ||
105 | + * to address all 52 va bits. The input address is perforce | ||
106 | + * aligned on a 64k boundary regardless of translation granule. | ||
107 | + */ | ||
108 | + page_shift = 16; | ||
109 | + } | ||
110 | ret.base <<= page_shift; | ||
111 | |||
112 | return ret; | ||
113 | @@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, | ||
114 | const int grainsize = stride + 3; | ||
115 | int startsizecheck; | ||
116 | |||
117 | - /* Negative levels are never allowed. */ | ||
118 | - if (level < 0) { | ||
119 | + /* | ||
120 | + * Negative levels are usually not allowed... | ||
121 | + * Except for FEAT_LPA2, 4k page table, 52-bit address space, which | ||
122 | + * begins with level -1. Note that previous feature tests will have | ||
123 | + * eliminated this combination if it is not enabled. | ||
124 | + */ | ||
125 | + if (level < (inputsize == 52 && stride == 9 ? -1 : 0)) { | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
130 | ARMMMUIdx mmu_idx, bool data) | ||
131 | { | ||
132 | uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; | ||
133 | - bool epd, hpd, using16k, using64k, tsz_oob; | ||
134 | - int select, tsz, tbi, max_tsz, min_tsz, ps; | ||
135 | + bool epd, hpd, using16k, using64k, tsz_oob, ds; | ||
136 | + int select, tsz, tbi, max_tsz, min_tsz, ps, sh; | ||
137 | + ARMCPU *cpu = env_archcpu(env); | ||
138 | |||
139 | if (!regime_has_2_ranges(mmu_idx)) { | ||
140 | select = 0; | ||
141 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
142 | hpd = extract32(tcr, 24, 1); | ||
143 | } | ||
144 | epd = false; | ||
145 | + sh = extract32(tcr, 12, 2); | ||
146 | ps = extract32(tcr, 16, 3); | ||
147 | + ds = extract64(tcr, 32, 1); | ||
148 | } else { | ||
149 | /* | ||
150 | * Bit 55 is always between the two regions, and is canonical for | ||
151 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
152 | if (!select) { | ||
153 | tsz = extract32(tcr, 0, 6); | ||
154 | epd = extract32(tcr, 7, 1); | ||
155 | + sh = extract32(tcr, 12, 2); | ||
156 | using64k = extract32(tcr, 14, 1); | ||
157 | using16k = extract32(tcr, 15, 1); | ||
158 | hpd = extract64(tcr, 41, 1); | ||
159 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
160 | using64k = tg == 3; | ||
161 | tsz = extract32(tcr, 16, 6); | ||
162 | epd = extract32(tcr, 23, 1); | ||
163 | + sh = extract32(tcr, 28, 2); | ||
164 | hpd = extract64(tcr, 42, 1); | ||
165 | } | ||
166 | ps = extract64(tcr, 32, 3); | ||
167 | + ds = extract64(tcr, 59, 1); | ||
168 | } | ||
169 | |||
170 | - if (cpu_isar_feature(aa64_st, env_archcpu(env))) { | ||
171 | + if (cpu_isar_feature(aa64_st, cpu)) { | ||
172 | max_tsz = 48 - using64k; | ||
173 | } else { | ||
174 | max_tsz = 39; | ||
175 | } | ||
176 | |||
177 | + /* | ||
178 | + * DS is RES0 unless FEAT_LPA2 is supported for the given page size; | ||
179 | + * adjust the effective value of DS, as documented. | ||
180 | + */ | ||
181 | min_tsz = 16; | ||
182 | if (using64k) { | ||
183 | - if (cpu_isar_feature(aa64_lva, env_archcpu(env))) { | ||
184 | + if (cpu_isar_feature(aa64_lva, cpu)) { | ||
185 | + min_tsz = 12; | ||
186 | + } | ||
187 | + ds = false; | ||
188 | + } else if (ds) { | ||
189 | + switch (mmu_idx) { | ||
190 | + case ARMMMUIdx_Stage2: | ||
191 | + case ARMMMUIdx_Stage2_S: | ||
192 | + if (using16k) { | ||
193 | + ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu); | ||
194 | + } else { | ||
195 | + ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu); | ||
196 | + } | ||
197 | + break; | ||
198 | + default: | ||
199 | + if (using16k) { | ||
200 | + ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu); | ||
201 | + } else { | ||
202 | + ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu); | ||
203 | + } | ||
204 | + break; | ||
205 | + } | ||
206 | + if (ds) { | ||
207 | min_tsz = 12; | ||
208 | } | ||
209 | } | ||
210 | - /* TODO: FEAT_LPA2 */ | ||
211 | |||
212 | if (tsz > max_tsz) { | ||
213 | tsz = max_tsz; | ||
214 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
215 | return (ARMVAParameters) { | ||
216 | .tsz = tsz, | ||
217 | .ps = ps, | ||
218 | + .sh = sh, | ||
219 | .select = select, | ||
220 | .tbi = tbi, | ||
221 | .epd = epd, | ||
222 | @@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, | ||
223 | .using16k = using16k, | ||
224 | .using64k = using64k, | ||
225 | .tsz_oob = tsz_oob, | ||
226 | + .ds = ds, | ||
227 | }; | ||
46 | } | 228 | } |
47 | 229 | ||
48 | static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop) | 230 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
49 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) | 231 | * VTCR_EL2.SL0 field (whose interpretation depends on the page size) |
50 | * We cannot write 16 bytes at once because the | 232 | */ |
51 | * destination is unaligned. | 233 | uint32_t sl0 = extract32(tcr->raw_tcr, 6, 2); |
52 | */ | 234 | + uint32_t sl2 = extract64(tcr->raw_tcr, 33, 1); |
53 | - tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), | 235 | uint32_t startlevel; |
54 | + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(vd), | 236 | bool ok; |
55 | 8, 8, tmp); | 237 | |
56 | - tcg_gen_gvec_mov(0, neon_reg_offset(vd + 1, 0), | 238 | - if (!aarch64 || stride == 9) { |
57 | - neon_reg_offset(vd, 0), 8, 8); | 239 | + /* SL2 is RES0 unless DS=1 & 4kb granule. */ |
58 | + tcg_gen_gvec_mov(0, neon_full_reg_offset(vd + 1), | 240 | + if (param.ds && stride == 9 && sl2) { |
59 | + neon_full_reg_offset(vd), 8, 8); | 241 | + if (sl0 != 0) { |
60 | } else { | 242 | + level = 0; |
61 | - tcg_gen_gvec_dup_i32(size, neon_reg_offset(vd, 0), | 243 | + fault_type = ARMFault_Translation; |
62 | + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(vd), | 244 | + goto do_fault; |
63 | vec_size, vec_size, tmp); | 245 | + } |
64 | } | 246 | + startlevel = -1; |
65 | tcg_gen_addi_i32(addr, addr, 1 << size); | 247 | + } else if (!aarch64 || stride == 9) { |
66 | @@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) | 248 | /* AArch32 or 4KB pages */ |
67 | static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn) | 249 | startlevel = 2 - sl0; |
68 | { | 250 | |
69 | int vec_size = a->q ? 16 : 8; | 251 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
70 | - int rd_ofs = neon_reg_offset(a->vd, 0); | 252 | * for both v7 and v8. However, for v8 the SBZ bits [47:40] must be 0 |
71 | - int rn_ofs = neon_reg_offset(a->vn, 0); | 253 | * or an AddressSize fault is raised. So for v8 we extract those SBZ |
72 | - int rm_ofs = neon_reg_offset(a->vm, 0); | 254 | * bits as part of the address, which will be checked via outputsize. |
73 | + int rd_ofs = neon_full_reg_offset(a->vd); | 255 | - * For AArch64, the address field always goes up to bit 47 (with extra |
74 | + int rn_ofs = neon_full_reg_offset(a->vn); | 256 | - * bits for FEAT_LPA placed elsewhere). AArch64 implies v8. |
75 | + int rm_ofs = neon_full_reg_offset(a->vm); | 257 | + * For AArch64, the address field goes up to bit 47, or 49 with FEAT_LPA2; |
76 | 258 | + * the highest bits of a 52-bit output are placed elsewhere. | |
77 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | 259 | */ |
78 | return false; | 260 | - if (arm_feature(env, ARM_FEATURE_V8)) { |
79 | @@ -XXX,XX +XXX,XX @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn) | 261 | + if (param.ds) { |
80 | { | 262 | + descaddrmask = MAKE_64BIT_MASK(0, 50); |
81 | /* Handle a 2-reg-shift insn which can be vectorized. */ | 263 | + } else if (arm_feature(env, ARM_FEATURE_V8)) { |
82 | int vec_size = a->q ? 16 : 8; | 264 | descaddrmask = MAKE_64BIT_MASK(0, 48); |
83 | - int rd_ofs = neon_reg_offset(a->vd, 0); | 265 | } else { |
84 | - int rm_ofs = neon_reg_offset(a->vm, 0); | 266 | descaddrmask = MAKE_64BIT_MASK(0, 40); |
85 | + int rd_ofs = neon_full_reg_offset(a->vd); | 267 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
86 | + int rm_ofs = neon_full_reg_offset(a->vm); | 268 | |
87 | 269 | /* | |
88 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | 270 | * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12] |
89 | return false; | 271 | - * of descriptor. Otherwise, if descaddr is out of range, raise |
90 | @@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a, | 272 | - * AddressSizeFault. |
91 | { | 273 | + * of descriptor. For FEAT_LPA2 and effective DS, bits [51:50] of |
92 | /* FP operations in 2-reg-and-shift group */ | 274 | + * descaddr are in [9:8]. Otherwise, if descaddr is out of range, |
93 | int vec_size = a->q ? 16 : 8; | 275 | + * raise AddressSizeFault. |
94 | - int rd_ofs = neon_reg_offset(a->vd, 0); | 276 | */ |
95 | - int rm_ofs = neon_reg_offset(a->vm, 0); | 277 | if (outputsize > 48) { |
96 | + int rd_ofs = neon_full_reg_offset(a->vd); | 278 | - descaddr |= extract64(descriptor, 12, 4) << 48; |
97 | + int rm_ofs = neon_full_reg_offset(a->vm); | 279 | + if (param.ds) { |
98 | TCGv_ptr fpst; | 280 | + descaddr |= extract64(descriptor, 8, 2) << 50; |
99 | 281 | + } else { | |
100 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | 282 | + descaddr |= extract64(descriptor, 12, 4) << 48; |
101 | @@ -XXX,XX +XXX,XX @@ static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a, | 283 | + } |
102 | return true; | 284 | } else if (descaddr >> outputsize) { |
103 | } | 285 | fault_type = ARMFault_AddressSize; |
104 | 286 | goto do_fault; | |
105 | - reg_ofs = neon_reg_offset(a->vd, 0); | 287 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, |
106 | + reg_ofs = neon_full_reg_offset(a->vd); | 288 | assert(attrindx <= 7); |
107 | vec_size = a->q ? 16 : 8; | 289 | cacheattrs->attrs = extract64(mair, attrindx * 8, 8); |
108 | imm = asimd_imm_const(a->imm, a->cmode, a->op); | 290 | } |
109 | 291 | - cacheattrs->shareability = extract32(attrs, 6, 2); | |
110 | @@ -XXX,XX +XXX,XX @@ static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a) | 292 | + |
111 | return true; | 293 | + /* |
112 | } | 294 | + * For FEAT_LPA2 and effective DS, the SH field in the attributes |
113 | 295 | + * was re-purposed for output address bits. The SH attribute in | |
114 | - tcg_gen_gvec_3_ool(neon_reg_offset(a->vd, 0), | 296 | + * that case comes from TCR_ELx, which we extracted earlier. |
115 | - neon_reg_offset(a->vn, 0), | 297 | + */ |
116 | - neon_reg_offset(a->vm, 0), | 298 | + if (param.ds) { |
117 | + tcg_gen_gvec_3_ool(neon_full_reg_offset(a->vd), | 299 | + cacheattrs->shareability = param.sh; |
118 | + neon_full_reg_offset(a->vn), | 300 | + } else { |
119 | + neon_full_reg_offset(a->vm), | 301 | + cacheattrs->shareability = extract32(attrs, 6, 2); |
120 | 16, 16, 0, fn_gvec); | 302 | + } |
121 | return true; | 303 | |
122 | } | 304 | *phys_ptr = descaddr; |
123 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a, | 305 | *page_size_ptr = page_size; |
124 | { | ||
125 | /* Two registers and a scalar, using gvec */ | ||
126 | int vec_size = a->q ? 16 : 8; | ||
127 | - int rd_ofs = neon_reg_offset(a->vd, 0); | ||
128 | - int rn_ofs = neon_reg_offset(a->vn, 0); | ||
129 | + int rd_ofs = neon_full_reg_offset(a->vd); | ||
130 | + int rn_ofs = neon_full_reg_offset(a->vn); | ||
131 | int rm_ofs; | ||
132 | int idx; | ||
133 | TCGv_ptr fpstatus; | ||
134 | @@ -XXX,XX +XXX,XX @@ static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a, | ||
135 | /* a->vm is M:Vm, which encodes both register and index */ | ||
136 | idx = extract32(a->vm, a->size + 2, 2); | ||
137 | a->vm = extract32(a->vm, 0, a->size + 2); | ||
138 | - rm_ofs = neon_reg_offset(a->vm, 0); | ||
139 | + rm_ofs = neon_full_reg_offset(a->vm); | ||
140 | |||
141 | fpstatus = fpstatus_ptr(a->size == 1 ? FPST_STD_F16 : FPST_STD); | ||
142 | tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpstatus, | ||
143 | @@ -XXX,XX +XXX,XX @@ static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a) | ||
144 | return true; | ||
145 | } | ||
146 | |||
147 | - tcg_gen_gvec_dup_mem(a->size, neon_reg_offset(a->vd, 0), | ||
148 | + tcg_gen_gvec_dup_mem(a->size, neon_full_reg_offset(a->vd), | ||
149 | neon_element_offset(a->vm, a->index, a->size), | ||
150 | a->q ? 16 : 8, a->q ? 16 : 8); | ||
151 | return true; | ||
152 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a) | ||
153 | static bool do_2misc_vec(DisasContext *s, arg_2misc *a, GVecGen2Fn *fn) | ||
154 | { | ||
155 | int vec_size = a->q ? 16 : 8; | ||
156 | - int rd_ofs = neon_reg_offset(a->vd, 0); | ||
157 | - int rm_ofs = neon_reg_offset(a->vm, 0); | ||
158 | + int rd_ofs = neon_full_reg_offset(a->vd); | ||
159 | + int rm_ofs = neon_full_reg_offset(a->vm); | ||
160 | |||
161 | if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { | ||
162 | return false; | ||
163 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | ||
164 | index XXXXXXX..XXXXXXX 100644 | ||
165 | --- a/target/arm/translate-vfp.c.inc | ||
166 | +++ b/target/arm/translate-vfp.c.inc | ||
167 | @@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a) | ||
168 | } | ||
169 | |||
170 | tmp = load_reg(s, a->rt); | ||
171 | - tcg_gen_gvec_dup_i32(size, neon_reg_offset(a->vn, 0), | ||
172 | + tcg_gen_gvec_dup_i32(size, neon_full_reg_offset(a->vn), | ||
173 | vec_size, vec_size, tmp); | ||
174 | tcg_temp_free_i32(tmp); | ||
175 | |||
176 | -- | 306 | -- |
177 | 2.20.1 | 307 | 2.25.1 |
178 | |||
179 | diff view generated by jsdifflib |
1 | In the neon_padd/pmax/pmin helpers for float16, a cut-and-paste error | 1 | When we're using KVM, the PSCI implementation is provided by the |
---|---|---|---|
2 | meant we were using the H4() address swizzler macro rather than the | 2 | kernel, but QEMU has to tell the guest about it via the device tree. |
3 | H2() which is required for 2-byte data. This had no effect on | 3 | Currently we look at the KVM_CAP_ARM_PSCI_0_2 capability to determine |
4 | little-endian hosts but meant we put the result data into the | 4 | if the kernel is providing at least PSCI 0.2, but if the kernel |
5 | destination Dreg in the wrong order on big-endian hosts. | 5 | provides a newer version than that we will still only tell the guest |
6 | it has PSCI 0.2. (This is fairly harmless; it just means the guest | ||
7 | won't use newer parts of the PSCI API.) | ||
8 | |||
9 | The kernel exposes the specific PSCI version it is implementing via | ||
10 | the ONE_REG API; use this to report in the dtb that the PSCI | ||
11 | implementation is 1.0-compatible if appropriate. (The device tree | ||
12 | binding currently only distinguishes "pre-0.2", "0.2-compatible" and | ||
13 | "1.0-compatible".) | ||
6 | 14 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
16 | Reviewed-by: Marc Zyngier <maz@kernel.org> | ||
17 | Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 18 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 19 | Reviewed-by: Andrew Jones <drjones@redhat.com> |
10 | Message-id: 20201028191712.4910-2-peter.maydell@linaro.org | 20 | Message-id: 20220224134655.1207865-1-peter.maydell@linaro.org |
11 | --- | 21 | --- |
12 | target/arm/vec_helper.c | 8 ++++---- | 22 | target/arm/kvm-consts.h | 1 + |
13 | 1 file changed, 4 insertions(+), 4 deletions(-) | 23 | hw/arm/boot.c | 5 ++--- |
24 | target/arm/kvm64.c | 12 ++++++++++++ | ||
25 | 3 files changed, 15 insertions(+), 3 deletions(-) | ||
14 | 26 | ||
15 | diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c | 27 | diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h |
16 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/target/arm/vec_helper.c | 29 | --- a/target/arm/kvm-consts.h |
18 | +++ b/target/arm/vec_helper.c | 30 | +++ b/target/arm/kvm-consts.h |
19 | @@ -XXX,XX +XXX,XX @@ DO_ABA(gvec_uaba_d, uint64_t) | 31 | @@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_PSCI_FEATURES); |
20 | r2 = float16_##OP(m[H2(0)], m[H2(1)], fpst); \ | 32 | |
21 | r3 = float16_##OP(m[H2(2)], m[H2(3)], fpst); \ | 33 | #define QEMU_PSCI_VERSION_0_1 0x00001 |
22 | \ | 34 | #define QEMU_PSCI_VERSION_0_2 0x00002 |
23 | - d[H4(0)] = r0; \ | 35 | +#define QEMU_PSCI_VERSION_1_0 0x10000 |
24 | - d[H4(1)] = r1; \ | 36 | #define QEMU_PSCI_VERSION_1_1 0x10001 |
25 | - d[H4(2)] = r2; \ | 37 | |
26 | - d[H4(3)] = r3; \ | 38 | MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP); |
27 | + d[H2(0)] = r0; \ | 39 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c |
28 | + d[H2(1)] = r1; \ | 40 | index XXXXXXX..XXXXXXX 100644 |
29 | + d[H2(2)] = r2; \ | 41 | --- a/hw/arm/boot.c |
30 | + d[H2(3)] = r3; \ | 42 | +++ b/hw/arm/boot.c |
43 | @@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt) | ||
31 | } | 44 | } |
32 | 45 | ||
33 | DO_NEON_PAIRWISE(neon_padd, add) | 46 | qemu_fdt_add_subnode(fdt, "/psci"); |
47 | - if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2 || | ||
48 | - armcpu->psci_version == QEMU_PSCI_VERSION_1_1) { | ||
49 | - if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2) { | ||
50 | + if (armcpu->psci_version >= QEMU_PSCI_VERSION_0_2) { | ||
51 | + if (armcpu->psci_version < QEMU_PSCI_VERSION_1_0) { | ||
52 | const char comp[] = "arm,psci-0.2\0arm,psci"; | ||
53 | qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); | ||
54 | } else { | ||
55 | diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/target/arm/kvm64.c | ||
58 | +++ b/target/arm/kvm64.c | ||
59 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs) | ||
60 | uint64_t mpidr; | ||
61 | ARMCPU *cpu = ARM_CPU(cs); | ||
62 | CPUARMState *env = &cpu->env; | ||
63 | + uint64_t psciver; | ||
64 | |||
65 | if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE || | ||
66 | !object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) { | ||
67 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | + /* | ||
72 | + * KVM reports the exact PSCI version it is implementing via a | ||
73 | + * special sysreg. If it is present, use its contents to determine | ||
74 | + * what to report to the guest in the dtb (it is the PSCI version, | ||
75 | + * in the same 15-bits major 16-bits minor format that PSCI_VERSION | ||
76 | + * returns). | ||
77 | + */ | ||
78 | + if (!kvm_get_one_reg(cs, KVM_REG_ARM_PSCI_VERSION, &psciver)) { | ||
79 | + cpu->psci_version = psciver; | ||
80 | + } | ||
81 | + | ||
82 | /* | ||
83 | * When KVM is in use, PSCI is emulated in-kernel and not by qemu. | ||
84 | * Currently KVM has its own idea about MPIDR assignment, so we | ||
34 | -- | 85 | -- |
35 | 2.20.1 | 86 | 2.25.1 |
36 | |||
37 | diff view generated by jsdifflib |
1 | From: AlexChen <alex.chen@huawei.com> | 1 | The updateUIInfo method makes Cocoa API calls. It also calls back |
---|---|---|---|
2 | into QEMU functions like dpy_set_ui_info(). To do this safely, we | ||
3 | need to follow two rules: | ||
4 | * Cocoa API calls are made on the Cocoa UI thread | ||
5 | * When calling back into QEMU we must hold the iothread lock | ||
2 | 6 | ||
3 | In omap_lcd_interrupts(), the pointer omap_lcd is dereferinced before | 7 | Fix the places where we got this wrong, by taking the iothread lock |
4 | being check if it is valid, which may lead to NULL pointer dereference. | 8 | while executing updateUIInfo, and moving the call in cocoa_switch() |
5 | So move the assignment to surface after checking that the omap_lcd is valid | 9 | inside the dispatch_async block. |
6 | and move surface_bits_per_pixel(surface) to after the surface assignment. | ||
7 | 10 | ||
8 | Reported-by: Euler Robot <euler.robot@huawei.com> | 11 | Some of the Cocoa UI methods which call updateUIInfo are invoked as |
9 | Signed-off-by: AlexChen <alex.chen@huawei.com> | 12 | part of the initial application startup, while we're still doing the |
10 | Message-id: 5F9CDB8A.9000001@huawei.com | 13 | little cross-thread dance described in the comment just above |
11 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 14 | call_qemu_main(). This meant they were calling back into the QEMU UI |
15 | layer before we'd actually finished initializing our display and | ||
16 | registered the DisplayChangeListener, which isn't really valid. Once | ||
17 | updateUIInfo takes the iothread lock, we no longer get away with | ||
18 | this, because during this startup phase the iothread lock is held by | ||
19 | the QEMU main-loop thread which is waiting for us to finish our | ||
20 | display initialization. So we must suppress updateUIInfo until | ||
21 | applicationDidFinishLaunching allows the QEMU main-loop thread to | ||
22 | continue. | ||
23 | |||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 24 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
25 | Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com> | ||
26 | Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com> | ||
27 | Message-id: 20220224101330.967429-2-peter.maydell@linaro.org | ||
13 | --- | 28 | --- |
14 | hw/display/omap_lcdc.c | 10 +++++++--- | 29 | ui/cocoa.m | 25 ++++++++++++++++++++++--- |
15 | 1 file changed, 7 insertions(+), 3 deletions(-) | 30 | 1 file changed, 22 insertions(+), 3 deletions(-) |
16 | 31 | ||
17 | diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c | 32 | diff --git a/ui/cocoa.m b/ui/cocoa.m |
18 | index XXXXXXX..XXXXXXX 100644 | 33 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/hw/display/omap_lcdc.c | 34 | --- a/ui/cocoa.m |
20 | +++ b/hw/display/omap_lcdc.c | 35 | +++ b/ui/cocoa.m |
21 | @@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) | 36 | @@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView; |
22 | static void omap_update_display(void *opaque) | 37 | } |
38 | } | ||
39 | |||
40 | -- (void) updateUIInfo | ||
41 | +- (void) updateUIInfoLocked | ||
23 | { | 42 | { |
24 | struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; | 43 | + /* Must be called with the iothread lock, i.e. via updateUIInfo */ |
25 | - DisplaySurface *surface = qemu_console_surface(omap_lcd->con); | 44 | NSSize frameSize; |
26 | + DisplaySurface *surface; | 45 | QemuUIInfo info; |
27 | draw_line_func draw_line; | 46 | |
28 | int size, height, first, last; | 47 | @@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView; |
29 | int width, linesize, step, bpp, frame_offset; | 48 | dpy_set_ui_info(dcl.con, &info, TRUE); |
30 | hwaddr frame_base; | 49 | } |
31 | 50 | ||
32 | - if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || | 51 | +- (void) updateUIInfo |
33 | - !surface_bits_per_pixel(surface)) { | 52 | +{ |
34 | + if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable) { | 53 | + if (!allow_events) { |
54 | + /* | ||
55 | + * Don't try to tell QEMU about UI information in the application | ||
56 | + * startup phase -- we haven't yet registered dcl with the QEMU UI | ||
57 | + * layer, and also trying to take the iothread lock would deadlock. | ||
58 | + * When cocoa_display_init() does register the dcl, the UI layer | ||
59 | + * will call cocoa_switch(), which will call updateUIInfo, so | ||
60 | + * we don't lose any information here. | ||
61 | + */ | ||
35 | + return; | 62 | + return; |
36 | + } | 63 | + } |
37 | + | 64 | + |
38 | + surface = qemu_console_surface(omap_lcd->con); | 65 | + with_iothread_lock(^{ |
39 | + if (!surface_bits_per_pixel(surface)) { | 66 | + [self updateUIInfoLocked]; |
40 | return; | 67 | + }); |
41 | } | 68 | +} |
42 | 69 | + | |
70 | - (void)viewDidMoveToWindow | ||
71 | { | ||
72 | [self updateUIInfo]; | ||
73 | @@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl, | ||
74 | |||
75 | COCOA_DEBUG("qemu_cocoa: cocoa_switch\n"); | ||
76 | |||
77 | - [cocoaView updateUIInfo]; | ||
78 | - | ||
79 | // The DisplaySurface will be freed as soon as this callback returns. | ||
80 | // We take a reference to the underlying pixman image here so it does | ||
81 | // not disappear from under our feet; the switchSurface method will | ||
82 | @@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl, | ||
83 | pixman_image_ref(image); | ||
84 | |||
85 | dispatch_async(dispatch_get_main_queue(), ^{ | ||
86 | + [cocoaView updateUIInfo]; | ||
87 | [cocoaView switchSurface:image]; | ||
88 | }); | ||
89 | [pool release]; | ||
43 | -- | 90 | -- |
44 | 2.20.1 | 91 | 2.25.1 |
45 | |||
46 | diff view generated by jsdifflib |
1 | In gicv3_init_cpuif() we copy the ARMCPU gicv3_maintenance_interrupt | 1 | In commit 6e657e64cdc478 in 2013 we added some autorelease pools to |
---|---|---|---|
2 | into the GICv3CPUState struct's maintenance_irq field. This will | 2 | deal with complaints from macOS when we made calls into Cocoa from |
3 | only work if the board happens to have already wired up the CPU | 3 | threads that didn't have automatically created autorelease pools. |
4 | maintenance IRQ before the GIC was realized. Unfortunately this is | 4 | Later on, macOS got stricter about forbidding cross-thread Cocoa |
5 | not the case for the 'virt' board, and so the value that gets copied | 5 | calls, and in commit 5588840ff77800e839d8 we restructured the code to |
6 | is NULL (since a qemu_irq is really a pointer to an IRQState struct | 6 | avoid them. This left the autorelease pool creation in several |
7 | under the hood). The effect is that the CPU interface code never | 7 | functions without any purpose; delete it. |
8 | actually raises the maintenance interrupt line. | ||
9 | 8 | ||
10 | Instead, since the GICv3CPUState has a pointer to the CPUState, make | 9 | We still need the pool in cocoa_refresh() for the clipboard related |
11 | the dereference at the point where we want to raise the interrupt, to | 10 | code which is called directly there. |
12 | avoid an implicit requirement on board code to wire things up in a | ||
13 | particular order. | ||
14 | 11 | ||
15 | Reported-by: Jose Martins <josemartins90@gmail.com> | ||
16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
17 | Message-id: 20201009153904.28529-1-peter.maydell@linaro.org | 13 | Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com> |
18 | Reviewed-by: Luc Michel <luc@lmichel.fr> | 14 | Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com> |
15 | Message-id: 20220224101330.967429-3-peter.maydell@linaro.org | ||
19 | --- | 16 | --- |
20 | include/hw/intc/arm_gicv3_common.h | 1 - | 17 | ui/cocoa.m | 6 ------ |
21 | hw/intc/arm_gicv3_cpuif.c | 5 ++--- | 18 | 1 file changed, 6 deletions(-) |
22 | 2 files changed, 2 insertions(+), 4 deletions(-) | ||
23 | 19 | ||
24 | diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h | 20 | diff --git a/ui/cocoa.m b/ui/cocoa.m |
25 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/include/hw/intc/arm_gicv3_common.h | 22 | --- a/ui/cocoa.m |
27 | +++ b/include/hw/intc/arm_gicv3_common.h | 23 | +++ b/ui/cocoa.m |
28 | @@ -XXX,XX +XXX,XX @@ struct GICv3CPUState { | 24 | @@ -XXX,XX +XXX,XX @@ int main (int argc, char **argv) { |
29 | qemu_irq parent_fiq; | 25 | static void cocoa_update(DisplayChangeListener *dcl, |
30 | qemu_irq parent_virq; | 26 | int x, int y, int w, int h) |
31 | qemu_irq parent_vfiq; | 27 | { |
32 | - qemu_irq maintenance_irq; | 28 | - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; |
33 | 29 | - | |
34 | /* Redistributor */ | 30 | COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); |
35 | uint32_t level; /* Current IRQ level */ | 31 | |
36 | diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c | 32 | dispatch_async(dispatch_get_main_queue(), ^{ |
37 | index XXXXXXX..XXXXXXX 100644 | 33 | @@ -XXX,XX +XXX,XX @@ static void cocoa_update(DisplayChangeListener *dcl, |
38 | --- a/hw/intc/arm_gicv3_cpuif.c | 34 | } |
39 | +++ b/hw/intc/arm_gicv3_cpuif.c | 35 | [cocoaView setNeedsDisplayInRect:rect]; |
40 | @@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs) | 36 | }); |
41 | int irqlevel = 0; | 37 | - |
42 | int fiqlevel = 0; | 38 | - [pool release]; |
43 | int maintlevel = 0; | ||
44 | + ARMCPU *cpu = ARM_CPU(cs->cpu); | ||
45 | |||
46 | idx = hppvi_index(cs); | ||
47 | trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx); | ||
48 | @@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs) | ||
49 | |||
50 | qemu_set_irq(cs->parent_vfiq, fiqlevel); | ||
51 | qemu_set_irq(cs->parent_virq, irqlevel); | ||
52 | - qemu_set_irq(cs->maintenance_irq, maintlevel); | ||
53 | + qemu_set_irq(cpu->gicv3_maintenance_interrupt, maintlevel); | ||
54 | } | 39 | } |
55 | 40 | ||
56 | static uint64_t icv_ap_read(CPUARMState *env, const ARMCPRegInfo *ri) | 41 | static void cocoa_switch(DisplayChangeListener *dcl, |
57 | @@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s) | 42 | DisplaySurface *surface) |
58 | && cpu->gic_num_lrs) { | 43 | { |
59 | int j; | 44 | - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; |
60 | 45 | pixman_image_t *image = surface->image; | |
61 | - cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; | 46 | |
62 | - | 47 | COCOA_DEBUG("qemu_cocoa: cocoa_switch\n"); |
63 | cs->num_list_regs = cpu->gic_num_lrs; | 48 | @@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl, |
64 | cs->vpribits = cpu->gic_vpribits; | 49 | [cocoaView updateUIInfo]; |
65 | cs->vprebits = cpu->gic_vprebits; | 50 | [cocoaView switchSurface:image]; |
51 | }); | ||
52 | - [pool release]; | ||
53 | } | ||
54 | |||
55 | static void cocoa_refresh(DisplayChangeListener *dcl) | ||
66 | -- | 56 | -- |
67 | 2.20.1 | 57 | 2.25.1 |
68 | |||
69 | diff view generated by jsdifflib |