1 | Arm queue built up to a point where it seems worth sending: | 1 | target-arm queue: the big things here are the new nRF51 |
---|---|---|---|
2 | various bug fixes, plus RTH's refactoring in preparation for SVE. | 2 | (microbit) devices and Luc's gdbstub multiprocess work. |
3 | 3 | ||
4 | thanks | 4 | thanks |
5 | -- PMM | 5 | -- PMM |
6 | |||
7 | |||
8 | The following changes since commit 0f79bfe38a2cf0f43c7ea4959da7f8ebd7858f3d: | ||
9 | 6 | ||
10 | Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.12-pull-request' into staging (2018-01-25 09:53:53 +0000) | 7 | The following changes since commit a29644590f95166c8a13e5797f8e7701134b31d0: |
11 | 8 | ||
12 | are available in the git repository at: | 9 | Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-01-05' into staging (2019-01-07 11:55:52 +0000) |
13 | 10 | ||
14 | git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180125 | 11 | are available in the Git repository at: |
15 | 12 | ||
16 | for you to fetch changes up to 24da047af0e99a83fcc0d50b86c0f2627f7418b3: | 13 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190107 |
17 | 14 | ||
18 | pl110: Implement vertical compare/next base interrupts (2018-01-25 11:45:30 +0000) | 15 | for you to fetch changes up to f831f955d420966471f5f8b316ba50d2523b1ff0: |
16 | |||
17 | Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. (2019-01-07 15:46:20 +0000) | ||
19 | 18 | ||
20 | ---------------------------------------------------------------- | 19 | ---------------------------------------------------------------- |
21 | target-arm queue: | 20 | target-arm queue: |
22 | * target/arm: Fix address truncation in 64-bit pagetable walks | 21 | * Support u-boot 'noload' images for Arm (as used by NetBSD/evbarm GENERIC kernel) |
23 | * i.MX: Fix FEC/ENET receive functions | 22 | * hw/misc/tz-mpc: Fix value of BLK_MAX register |
24 | * target/arm: preparatory refactoring for SVE emulation | 23 | * target/arm: Emit barriers for A32/T32 load-acquire/store-release insns |
25 | * hw/intc/arm_gic: Prevent the GIC from signaling an IRQ when it's "active and pending" | 24 | * nRF51 SoC: add timer, GPIO, RNG peripherals |
26 | * hw/intc/arm_gic: Fix C_RPR value on idle priority | 25 | * hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller |
27 | * hw/intc/arm_gic: Fix group priority computation for group 1 IRQs | 26 | * cpus.c: Fix race condition in cpu_stop_current() |
28 | * hw/intc/arm_gic: Fix the NS view of C_BPR when C_CTRL.CBPR is 1 | 27 | * hw/arm: versal: Plug memory leaks |
29 | * hw/arm/virt: Check that the CPU realize method succeeded | 28 | * Allow M profile boards to run even if -kernel not specified |
30 | * sdhci: fix a NULL pointer dereference due to uninitialized AddressSpace object | 29 | * gdbstub: Add multiprocess extension support for use when the |
31 | * xilinx_spips: Correct usage of an uninitialized local variable | 30 | board has multiple CPUs of different types (like the Xilinx Zynq boards) |
32 | * pl110: Implement vertical compare/next base interrupts | 31 | * target/arm: Don't decode S bit in SVE brk[ab] merging insns |
32 | * target/arm: Convert ARM_TBFLAG_* to FIELDs | ||
33 | 33 | ||
34 | ---------------------------------------------------------------- | 34 | ---------------------------------------------------------------- |
35 | Ard Biesheuvel (1): | 35 | Edgar E. Iglesias (1): |
36 | target/arm: Fix 32-bit address truncation | 36 | hw/arm: versal: Plug memory leaks |
37 | 37 | ||
38 | Francisco Iglesias (1): | 38 | Luc Michel (16): |
39 | xilinx_spips: Correct usage of an uninitialized local variable | 39 | hw/cpu: introduce CPU clusters |
40 | gdbstub: introduce GDB processes | ||
41 | gdbstub: add multiprocess support to '?' packets | ||
42 | gdbstub: add multiprocess support to 'H' and 'T' packets | ||
43 | gdbstub: add multiprocess support to vCont packets | ||
44 | gdbstub: add multiprocess support to 'sC' packets | ||
45 | gdbstub: add multiprocess support to (f|s)ThreadInfo and ThreadExtraInfo | ||
46 | gdbstub: add multiprocess support to Xfer:features:read: | ||
47 | gdbstub: add multiprocess support to gdb_vm_state_change() | ||
48 | gdbstub: add multiprocess support to 'D' packets | ||
49 | gdbstub: add support for extended mode packet | ||
50 | gdbstub: add support for vAttach packets | ||
51 | gdbstub: processes initialization on new peer connection | ||
52 | gdbstub: gdb_set_stop_cpu: ignore request when process is not attached | ||
53 | gdbstub: add multiprocess extension support | ||
54 | arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters | ||
40 | 55 | ||
41 | Jean-Christophe Dubois (1): | 56 | Nick Hudson (1): |
42 | i.MX: Fix FEC/ENET receive funtions | 57 | Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. |
43 | 58 | ||
44 | Linus Walleij (1): | 59 | Peter Maydell (3): |
45 | pl110: Implement vertical compare/next base interrupts | 60 | cpus.c: Fix race condition in cpu_stop_current() |
46 | 61 | target/arm: Emit barriers for A32/T32 load-acquire/store-release insns | |
47 | Luc MICHEL (4): | 62 | hw/misc/tz-mpc: Fix value of BLK_MAX register |
48 | hw/intc/arm_gic: Prevent the GIC from signaling an IRQ when it's "active and pending" | ||
49 | hw/intc/arm_gic: Fix C_RPR value on idle priority | ||
50 | hw/intc/arm_gic: Fix group priority computation for group 1 IRQs | ||
51 | hw/intc/arm_gic: Fix the NS view of C_BPR when C_CTRL.CBPR is 1 | ||
52 | |||
53 | Peter Maydell (1): | ||
54 | hw/arm/virt: Check that the CPU realize method succeeded | ||
55 | 63 | ||
56 | Philippe Mathieu-Daudé (1): | 64 | Philippe Mathieu-Daudé (1): |
57 | sdhci: fix a NULL pointer dereference due to uninitialized AddresSpace object | 65 | hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller |
58 | 66 | ||
59 | Richard Henderson (11): | 67 | Richard Henderson (2): |
60 | target/arm: Mark disas_set_insn_syndrome inline | 68 | target/arm: Convert ARM_TBFLAG_* to FIELDs |
61 | target/arm: Use pointers in crypto helpers | 69 | target/arm: SVE brk[ab] merging does not have s bit |
62 | target/arm: Use pointers in neon zip/uzp helpers | ||
63 | target/arm: Use pointers in neon tbl helper | ||
64 | target/arm: Change the type of vfp.regs | ||
65 | target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers | ||
66 | vmstate: Add VMSTATE_UINT64_SUB_ARRAY | ||
67 | target/arm: Add ARM_FEATURE_SVE | ||
68 | target/arm: Move cpu_get_tb_cpu_state out of line | ||
69 | target/arm: Hoist store to flags output in cpu_get_tb_cpu_state | ||
70 | target/arm: Simplify fp_exception_el for user-only | ||
71 | 70 | ||
72 | include/hw/sd/sdhci.h | 1 + | 71 | Stefan Hajnoczi (1): |
73 | include/migration/vmstate.h | 9 ++- | 72 | Revert "armv7m: Guard against no -kernel argument" |
74 | target/arm/cpu.h | 157 ++++++++----------------------------- | ||
75 | target/arm/helper.h | 46 +++++------ | ||
76 | target/arm/translate.h | 2 +- | ||
77 | hw/arm/virt.c | 2 +- | ||
78 | hw/display/pl110.c | 30 +++++++- | ||
79 | hw/intc/arm_gic.c | 25 +++++- | ||
80 | hw/net/imx_fec.c | 8 +- | ||
81 | hw/sd/sdhci.c | 1 + | ||
82 | hw/ssi/xilinx_spips.c | 18 ++++- | ||
83 | linux-user/signal.c | 22 +++--- | ||
84 | target/arm/arch_dump.c | 8 +- | ||
85 | target/arm/crypto_helper.c | 184 +++++++++++++++++--------------------------- | ||
86 | target/arm/helper-a64.c | 5 +- | ||
87 | target/arm/helper.c | 164 +++++++++++++++++++++++++++++++++++---- | ||
88 | target/arm/kvm32.c | 4 +- | ||
89 | target/arm/kvm64.c | 31 +++----- | ||
90 | target/arm/machine.c | 2 +- | ||
91 | target/arm/neon_helper.c | 162 ++++++++++++++++++++------------------ | ||
92 | target/arm/op_helper.c | 17 ++-- | ||
93 | target/arm/translate-a64.c | 100 ++++++++++++------------ | ||
94 | target/arm/translate.c | 134 +++++++++++++++++--------------- | ||
95 | 23 files changed, 607 insertions(+), 525 deletions(-) | ||
96 | 73 | ||
74 | Steffen Görtz (11): | ||
75 | qtest: Add set_irq_in command to set IRQ/GPIO level | ||
76 | arm: Add header to host common definition for nRF51 SOC peripherals | ||
77 | hw/misc/nrf51_rng: Add NRF51 random number generator peripheral | ||
78 | arm: Instantiate NRF51 random number generator | ||
79 | hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral | ||
80 | arm: Instantiate NRF51 general purpose I/O | ||
81 | tests/microbit-test: Add Tests for nRF51 GPIO | ||
82 | hw/timer/nrf51_timer: Add nRF51 Timer peripheral | ||
83 | arm: Instantiate NRF51 Timers | ||
84 | tests/microbit-test: Add Tests for nRF51 Timer | ||
85 | arm: Add Clock peripheral stub to NRF51 SOC | ||
86 | |||
87 | Thomas Huth (1): | ||
88 | MAINTAINERS: Add ARM-related files for hw/[misc|input|timer]/ | ||
89 | |||
90 | Makefile.objs | 1 + | ||
91 | hw/cpu/Makefile.objs | 2 +- | ||
92 | hw/gpio/Makefile.objs | 1 + | ||
93 | hw/misc/Makefile.objs | 1 + | ||
94 | hw/timer/Makefile.objs | 1 + | ||
95 | tests/Makefile.include | 2 + | ||
96 | hw/core/uboot_image.h | 1 + | ||
97 | include/hw/arm/allwinner-a10.h | 1 + | ||
98 | include/hw/arm/nrf51.h | 45 +++ | ||
99 | include/hw/arm/nrf51_soc.h | 9 + | ||
100 | include/hw/arm/xlnx-zynqmp.h | 3 + | ||
101 | include/hw/char/nrf51_uart.h | 1 - | ||
102 | include/hw/cpu/cluster.h | 58 ++++ | ||
103 | include/hw/gpio/nrf51_gpio.h | 69 +++++ | ||
104 | include/hw/loader.h | 7 +- | ||
105 | include/hw/misc/nrf51_rng.h | 83 +++++ | ||
106 | include/hw/timer/nrf51_timer.h | 80 +++++ | ||
107 | target/arm/cpu.h | 102 ++----- | ||
108 | tests/libqtest.h | 13 + | ||
109 | cpus.c | 3 +- | ||
110 | gdbstub.c | 672 ++++++++++++++++++++++++++++++++++++----- | ||
111 | hw/arm/allwinner-a10.c | 6 + | ||
112 | hw/arm/armv7m.c | 5 - | ||
113 | hw/arm/boot.c | 8 +- | ||
114 | hw/arm/nrf51_soc.c | 117 +++++-- | ||
115 | hw/arm/xlnx-versal-virt.c | 2 + | ||
116 | hw/arm/xlnx-zynqmp.c | 23 +- | ||
117 | hw/core/loader.c | 19 +- | ||
118 | hw/cpu/cluster.c | 50 +++ | ||
119 | hw/gpio/nrf51_gpio.c | 300 ++++++++++++++++++ | ||
120 | hw/microblaze/boot.c | 2 +- | ||
121 | hw/misc/nrf51_rng.c | 262 ++++++++++++++++ | ||
122 | hw/misc/tz-mpc.c | 2 +- | ||
123 | hw/nios2/boot.c | 2 +- | ||
124 | hw/ppc/e500.c | 1 + | ||
125 | hw/ppc/ppc440_bamboo.c | 2 +- | ||
126 | hw/ppc/sam460ex.c | 2 +- | ||
127 | hw/timer/nrf51_timer.c | 393 ++++++++++++++++++++++++ | ||
128 | qtest.c | 43 +++ | ||
129 | target/arm/helper.c | 49 ++- | ||
130 | target/arm/translate-a64.c | 22 +- | ||
131 | target/arm/translate.c | 73 +++-- | ||
132 | tests/libqtest.c | 10 + | ||
133 | tests/microbit-test.c | 255 ++++++++++++++++ | ||
134 | MAINTAINERS | 18 +- | ||
135 | hw/gpio/trace-events | 7 + | ||
136 | hw/timer/trace-events | 5 + | ||
137 | target/arm/sve.decode | 5 +- | ||
138 | 48 files changed, 2567 insertions(+), 271 deletions(-) | ||
139 | create mode 100644 include/hw/arm/nrf51.h | ||
140 | create mode 100644 include/hw/cpu/cluster.h | ||
141 | create mode 100644 include/hw/gpio/nrf51_gpio.h | ||
142 | create mode 100644 include/hw/misc/nrf51_rng.h | ||
143 | create mode 100644 include/hw/timer/nrf51_timer.h | ||
144 | create mode 100644 hw/cpu/cluster.c | ||
145 | create mode 100644 hw/gpio/nrf51_gpio.c | ||
146 | create mode 100644 hw/misc/nrf51_rng.c | ||
147 | create mode 100644 hw/timer/nrf51_timer.c | ||
148 | create mode 100644 tests/microbit-test.c | ||
149 | create mode 100644 hw/gpio/trace-events | ||
150 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Use "register" TBFLAG_ANY to indicate shared state between | ||
4 | A32 and A64, and "registers" TBFLAG_A32 & TBFLAG_A64 for | ||
5 | fields that are specific to the given cpu state. | ||
6 | |||
7 | Move ARM_TBFLAG_BE_DATA to shared state, instead of its current | ||
8 | placement within "Bit usage when in AArch32 state". | ||
9 | |||
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 10 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
4 | Message-id: 20180119045438.28582-15-richard.henderson@linaro.org | 11 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
12 | Message-id: 20181218164348.7127-1-richard.henderson@linaro.org | ||
13 | [PMM: removed the renaming of BE_DATA flag to BE] | ||
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 14 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
6 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | --- | 16 | --- |
9 | target/arm/helper.c | 35 +++++++++++++++++++---------------- | 17 | target/arm/cpu.h | 102 ++++++++----------------------------- |
10 | 1 file changed, 19 insertions(+), 16 deletions(-) | 18 | target/arm/helper.c | 49 +++++++++--------- |
11 | 19 | target/arm/translate-a64.c | 22 ++++---- | |
20 | target/arm/translate.c | 40 ++++++++------- | ||
21 | 4 files changed, 78 insertions(+), 135 deletions(-) | ||
22 | |||
23 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/target/arm/cpu.h | ||
26 | +++ b/target/arm/cpu.h | ||
27 | @@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env) | ||
28 | * We put flags which are shared between 32 and 64 bit mode at the top | ||
29 | * of the word, and flags which apply to only one mode at the bottom. | ||
30 | */ | ||
31 | -#define ARM_TBFLAG_AARCH64_STATE_SHIFT 31 | ||
32 | -#define ARM_TBFLAG_AARCH64_STATE_MASK (1U << ARM_TBFLAG_AARCH64_STATE_SHIFT) | ||
33 | -#define ARM_TBFLAG_MMUIDX_SHIFT 28 | ||
34 | -#define ARM_TBFLAG_MMUIDX_MASK (0x7 << ARM_TBFLAG_MMUIDX_SHIFT) | ||
35 | -#define ARM_TBFLAG_SS_ACTIVE_SHIFT 27 | ||
36 | -#define ARM_TBFLAG_SS_ACTIVE_MASK (1 << ARM_TBFLAG_SS_ACTIVE_SHIFT) | ||
37 | -#define ARM_TBFLAG_PSTATE_SS_SHIFT 26 | ||
38 | -#define ARM_TBFLAG_PSTATE_SS_MASK (1 << ARM_TBFLAG_PSTATE_SS_SHIFT) | ||
39 | +FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1) | ||
40 | +FIELD(TBFLAG_ANY, MMUIDX, 28, 3) | ||
41 | +FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1) | ||
42 | +FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) | ||
43 | /* Target EL if we take a floating-point-disabled exception */ | ||
44 | -#define ARM_TBFLAG_FPEXC_EL_SHIFT 24 | ||
45 | -#define ARM_TBFLAG_FPEXC_EL_MASK (0x3 << ARM_TBFLAG_FPEXC_EL_SHIFT) | ||
46 | +FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2) | ||
47 | +FIELD(TBFLAG_ANY, BE_DATA, 23, 1) | ||
48 | |||
49 | /* Bit usage when in AArch32 state: */ | ||
50 | -#define ARM_TBFLAG_THUMB_SHIFT 0 | ||
51 | -#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT) | ||
52 | -#define ARM_TBFLAG_VECLEN_SHIFT 1 | ||
53 | -#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT) | ||
54 | -#define ARM_TBFLAG_VECSTRIDE_SHIFT 4 | ||
55 | -#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT) | ||
56 | -#define ARM_TBFLAG_VFPEN_SHIFT 7 | ||
57 | -#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT) | ||
58 | -#define ARM_TBFLAG_CONDEXEC_SHIFT 8 | ||
59 | -#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT) | ||
60 | -#define ARM_TBFLAG_SCTLR_B_SHIFT 16 | ||
61 | -#define ARM_TBFLAG_SCTLR_B_MASK (1 << ARM_TBFLAG_SCTLR_B_SHIFT) | ||
62 | +FIELD(TBFLAG_A32, THUMB, 0, 1) | ||
63 | +FIELD(TBFLAG_A32, VECLEN, 1, 3) | ||
64 | +FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) | ||
65 | +FIELD(TBFLAG_A32, VFPEN, 7, 1) | ||
66 | +FIELD(TBFLAG_A32, CONDEXEC, 8, 8) | ||
67 | +FIELD(TBFLAG_A32, SCTLR_B, 16, 1) | ||
68 | /* We store the bottom two bits of the CPAR as TB flags and handle | ||
69 | * checks on the other bits at runtime | ||
70 | */ | ||
71 | -#define ARM_TBFLAG_XSCALE_CPAR_SHIFT 17 | ||
72 | -#define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT) | ||
73 | +FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2) | ||
74 | /* Indicates whether cp register reads and writes by guest code should access | ||
75 | * the secure or nonsecure bank of banked registers; note that this is not | ||
76 | * the same thing as the current security state of the processor! | ||
77 | */ | ||
78 | -#define ARM_TBFLAG_NS_SHIFT 19 | ||
79 | -#define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT) | ||
80 | -#define ARM_TBFLAG_BE_DATA_SHIFT 20 | ||
81 | -#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT) | ||
82 | +FIELD(TBFLAG_A32, NS, 19, 1) | ||
83 | /* For M profile only, Handler (ie not Thread) mode */ | ||
84 | -#define ARM_TBFLAG_HANDLER_SHIFT 21 | ||
85 | -#define ARM_TBFLAG_HANDLER_MASK (1 << ARM_TBFLAG_HANDLER_SHIFT) | ||
86 | +FIELD(TBFLAG_A32, HANDLER, 21, 1) | ||
87 | /* For M profile only, whether we should generate stack-limit checks */ | ||
88 | -#define ARM_TBFLAG_STACKCHECK_SHIFT 22 | ||
89 | -#define ARM_TBFLAG_STACKCHECK_MASK (1 << ARM_TBFLAG_STACKCHECK_SHIFT) | ||
90 | +FIELD(TBFLAG_A32, STACKCHECK, 22, 1) | ||
91 | |||
92 | /* Bit usage when in AArch64 state */ | ||
93 | -#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */ | ||
94 | -#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT) | ||
95 | -#define ARM_TBFLAG_TBI1_SHIFT 1 /* TBI1 for EL0/1 */ | ||
96 | -#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT) | ||
97 | -#define ARM_TBFLAG_SVEEXC_EL_SHIFT 2 | ||
98 | -#define ARM_TBFLAG_SVEEXC_EL_MASK (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT) | ||
99 | -#define ARM_TBFLAG_ZCR_LEN_SHIFT 4 | ||
100 | -#define ARM_TBFLAG_ZCR_LEN_MASK (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT) | ||
101 | - | ||
102 | -/* some convenience accessor macros */ | ||
103 | -#define ARM_TBFLAG_AARCH64_STATE(F) \ | ||
104 | - (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT) | ||
105 | -#define ARM_TBFLAG_MMUIDX(F) \ | ||
106 | - (((F) & ARM_TBFLAG_MMUIDX_MASK) >> ARM_TBFLAG_MMUIDX_SHIFT) | ||
107 | -#define ARM_TBFLAG_SS_ACTIVE(F) \ | ||
108 | - (((F) & ARM_TBFLAG_SS_ACTIVE_MASK) >> ARM_TBFLAG_SS_ACTIVE_SHIFT) | ||
109 | -#define ARM_TBFLAG_PSTATE_SS(F) \ | ||
110 | - (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT) | ||
111 | -#define ARM_TBFLAG_FPEXC_EL(F) \ | ||
112 | - (((F) & ARM_TBFLAG_FPEXC_EL_MASK) >> ARM_TBFLAG_FPEXC_EL_SHIFT) | ||
113 | -#define ARM_TBFLAG_THUMB(F) \ | ||
114 | - (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT) | ||
115 | -#define ARM_TBFLAG_VECLEN(F) \ | ||
116 | - (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT) | ||
117 | -#define ARM_TBFLAG_VECSTRIDE(F) \ | ||
118 | - (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT) | ||
119 | -#define ARM_TBFLAG_VFPEN(F) \ | ||
120 | - (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT) | ||
121 | -#define ARM_TBFLAG_CONDEXEC(F) \ | ||
122 | - (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT) | ||
123 | -#define ARM_TBFLAG_SCTLR_B(F) \ | ||
124 | - (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT) | ||
125 | -#define ARM_TBFLAG_XSCALE_CPAR(F) \ | ||
126 | - (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT) | ||
127 | -#define ARM_TBFLAG_NS(F) \ | ||
128 | - (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT) | ||
129 | -#define ARM_TBFLAG_BE_DATA(F) \ | ||
130 | - (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT) | ||
131 | -#define ARM_TBFLAG_HANDLER(F) \ | ||
132 | - (((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT) | ||
133 | -#define ARM_TBFLAG_STACKCHECK(F) \ | ||
134 | - (((F) & ARM_TBFLAG_STACKCHECK_MASK) >> ARM_TBFLAG_STACKCHECK_SHIFT) | ||
135 | -#define ARM_TBFLAG_TBI0(F) \ | ||
136 | - (((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT) | ||
137 | -#define ARM_TBFLAG_TBI1(F) \ | ||
138 | - (((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT) | ||
139 | -#define ARM_TBFLAG_SVEEXC_EL(F) \ | ||
140 | - (((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT) | ||
141 | -#define ARM_TBFLAG_ZCR_LEN(F) \ | ||
142 | - (((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT) | ||
143 | +FIELD(TBFLAG_A64, TBI0, 0, 1) | ||
144 | +FIELD(TBFLAG_A64, TBI1, 1, 1) | ||
145 | +FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2) | ||
146 | +FIELD(TBFLAG_A64, ZCR_LEN, 4, 4) | ||
147 | |||
148 | static inline bool bswap_code(bool sctlr_b) | ||
149 | { | ||
12 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 150 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
13 | index XXXXXXX..XXXXXXX 100644 | 151 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/target/arm/helper.c | 152 | --- a/target/arm/helper.c |
15 | +++ b/target/arm/helper.c | 153 | +++ b/target/arm/helper.c |
16 | @@ -XXX,XX +XXX,XX @@ static inline int fp_exception_el(CPUARMState *env) | 154 | @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, |
17 | } | ||
18 | |||
19 | void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | ||
20 | - target_ulong *cs_base, uint32_t *flags) | ||
21 | + target_ulong *cs_base, uint32_t *pflags) | ||
22 | { | ||
23 | ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false)); | 155 | ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false)); |
24 | + uint32_t flags; | 156 | int current_el = arm_current_el(env); |
25 | + | 157 | int fp_el = fp_exception_el(env, current_el); |
158 | - uint32_t flags; | ||
159 | + uint32_t flags = 0; | ||
160 | |||
26 | if (is_a64(env)) { | 161 | if (is_a64(env)) { |
162 | ARMCPU *cpu = arm_env_get_cpu(env); | ||
163 | |||
27 | *pc = env->pc; | 164 | *pc = env->pc; |
28 | - *flags = ARM_TBFLAG_AARCH64_STATE_MASK; | 165 | - flags = ARM_TBFLAG_AARCH64_STATE_MASK; |
29 | + flags = ARM_TBFLAG_AARCH64_STATE_MASK; | 166 | + flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1); |
30 | /* Get control bits for tagged addresses */ | 167 | /* Get control bits for tagged addresses */ |
31 | - *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); | 168 | - flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); |
32 | - *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); | 169 | - flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); |
33 | + flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); | 170 | + flags = FIELD_DP32(flags, TBFLAG_A64, TBI0, |
34 | + flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); | 171 | + arm_regime_tbi0(env, mmu_idx)); |
172 | + flags = FIELD_DP32(flags, TBFLAG_A64, TBI1, | ||
173 | + arm_regime_tbi1(env, mmu_idx)); | ||
174 | |||
175 | if (cpu_isar_feature(aa64_sve, cpu)) { | ||
176 | int sve_el = sve_exception_el(env, current_el); | ||
177 | @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | ||
178 | } else { | ||
179 | zcr_len = sve_zcr_len_for_el(env, current_el); | ||
180 | } | ||
181 | - flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT; | ||
182 | - flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT; | ||
183 | + flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el); | ||
184 | + flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len); | ||
185 | } | ||
35 | } else { | 186 | } else { |
36 | *pc = env->regs[15]; | 187 | *pc = env->regs[15]; |
37 | - *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | 188 | - flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) |
38 | + flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | 189 | - | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) |
39 | | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) | 190 | - | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) |
40 | | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) | 191 | - | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) |
41 | | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) | 192 | - | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT); |
42 | | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT); | 193 | - if (!(access_secure_reg(env))) { |
43 | if (!(access_secure_reg(env))) { | 194 | - flags |= ARM_TBFLAG_NS_MASK; |
44 | - *flags |= ARM_TBFLAG_NS_MASK; | 195 | - } |
45 | + flags |= ARM_TBFLAG_NS_MASK; | 196 | + flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb); |
46 | } | 197 | + flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len); |
198 | + flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride); | ||
199 | + flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits); | ||
200 | + flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env)); | ||
201 | + flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env)); | ||
47 | if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) | 202 | if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) |
48 | || arm_el_is_aa64(env, 1)) { | 203 | || arm_el_is_aa64(env, 1)) { |
49 | - *flags |= ARM_TBFLAG_VFPEN_MASK; | 204 | - flags |= ARM_TBFLAG_VFPEN_MASK; |
50 | + flags |= ARM_TBFLAG_VFPEN_MASK; | 205 | + flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1); |
51 | } | 206 | } |
52 | - *flags |= (extract32(env->cp15.c15_cpar, 0, 2) | 207 | - flags |= (extract32(env->cp15.c15_cpar, 0, 2) |
53 | - << ARM_TBFLAG_XSCALE_CPAR_SHIFT); | 208 | - << ARM_TBFLAG_XSCALE_CPAR_SHIFT); |
54 | + flags |= (extract32(env->cp15.c15_cpar, 0, 2) | 209 | + flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar); |
55 | + << ARM_TBFLAG_XSCALE_CPAR_SHIFT); | 210 | } |
56 | } | 211 | |
57 | 212 | - flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT); | |
58 | - *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT); | 213 | + flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); |
59 | + flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT); | ||
60 | 214 | ||
61 | /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine | 215 | /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine |
62 | * states defined in the ARM ARM for software singlestep: | 216 | * states defined in the ARM ARM for software singlestep: |
63 | @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | 217 | @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, |
64 | * 1 1 Active-not-pending | 218 | * 1 1 Active-not-pending |
65 | */ | 219 | */ |
66 | if (arm_singlestep_active(env)) { | 220 | if (arm_singlestep_active(env)) { |
67 | - *flags |= ARM_TBFLAG_SS_ACTIVE_MASK; | 221 | - flags |= ARM_TBFLAG_SS_ACTIVE_MASK; |
68 | + flags |= ARM_TBFLAG_SS_ACTIVE_MASK; | 222 | + flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1); |
69 | if (is_a64(env)) { | 223 | if (is_a64(env)) { |
70 | if (env->pstate & PSTATE_SS) { | 224 | if (env->pstate & PSTATE_SS) { |
71 | - *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | 225 | - flags |= ARM_TBFLAG_PSTATE_SS_MASK; |
72 | + flags |= ARM_TBFLAG_PSTATE_SS_MASK; | 226 | + flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); |
73 | } | 227 | } |
74 | } else { | 228 | } else { |
75 | if (env->uncached_cpsr & PSTATE_SS) { | 229 | if (env->uncached_cpsr & PSTATE_SS) { |
76 | - *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | 230 | - flags |= ARM_TBFLAG_PSTATE_SS_MASK; |
77 | + flags |= ARM_TBFLAG_PSTATE_SS_MASK; | 231 | + flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); |
78 | } | 232 | } |
79 | } | 233 | } |
80 | } | 234 | } |
81 | if (arm_cpu_data_is_big_endian(env)) { | 235 | if (arm_cpu_data_is_big_endian(env)) { |
82 | - *flags |= ARM_TBFLAG_BE_DATA_MASK; | 236 | - flags |= ARM_TBFLAG_BE_DATA_MASK; |
83 | + flags |= ARM_TBFLAG_BE_DATA_MASK; | 237 | + flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1); |
84 | } | 238 | } |
85 | - *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT; | 239 | - flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT; |
86 | + flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT; | 240 | + flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el); |
87 | 241 | ||
88 | if (arm_v7m_is_handler_mode(env)) { | 242 | if (arm_v7m_is_handler_mode(env)) { |
89 | - *flags |= ARM_TBFLAG_HANDLER_MASK; | 243 | - flags |= ARM_TBFLAG_HANDLER_MASK; |
90 | + flags |= ARM_TBFLAG_HANDLER_MASK; | 244 | + flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1); |
91 | } | 245 | } |
92 | 246 | ||
93 | + *pflags = flags; | 247 | /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is |
94 | *cs_base = 0; | 248 | @@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, |
95 | } | 249 | arm_feature(env, ARM_FEATURE_M) && |
250 | !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && | ||
251 | (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) { | ||
252 | - flags |= ARM_TBFLAG_STACKCHECK_MASK; | ||
253 | + flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1); | ||
254 | } | ||
255 | |||
256 | *pflags = flags; | ||
257 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
258 | index XXXXXXX..XXXXXXX 100644 | ||
259 | --- a/target/arm/translate-a64.c | ||
260 | +++ b/target/arm/translate-a64.c | ||
261 | @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, | ||
262 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
263 | CPUARMState *env = cpu->env_ptr; | ||
264 | ARMCPU *arm_cpu = arm_env_get_cpu(env); | ||
265 | - int bound; | ||
266 | + uint32_t tb_flags = dc->base.tb->flags; | ||
267 | + int bound, core_mmu_idx; | ||
268 | |||
269 | dc->isar = &arm_cpu->isar; | ||
270 | dc->pc = dc->base.pc_first; | ||
271 | @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, | ||
272 | !arm_el_is_aa64(env, 3); | ||
273 | dc->thumb = 0; | ||
274 | dc->sctlr_b = 0; | ||
275 | - dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE; | ||
276 | + dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE; | ||
277 | dc->condexec_mask = 0; | ||
278 | dc->condexec_cond = 0; | ||
279 | - dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags)); | ||
280 | - dc->tbi0 = ARM_TBFLAG_TBI0(dc->base.tb->flags); | ||
281 | - dc->tbi1 = ARM_TBFLAG_TBI1(dc->base.tb->flags); | ||
282 | + core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX); | ||
283 | + dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx); | ||
284 | + dc->tbi0 = FIELD_EX32(tb_flags, TBFLAG_A64, TBI0); | ||
285 | + dc->tbi1 = FIELD_EX32(tb_flags, TBFLAG_A64, TBI1); | ||
286 | dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx); | ||
287 | #if !defined(CONFIG_USER_ONLY) | ||
288 | dc->user = (dc->current_el == 0); | ||
289 | #endif | ||
290 | - dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags); | ||
291 | - dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags); | ||
292 | - dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16; | ||
293 | + dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL); | ||
294 | + dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL); | ||
295 | + dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16; | ||
296 | dc->vec_len = 0; | ||
297 | dc->vec_stride = 0; | ||
298 | dc->cp_regs = arm_cpu->cp_regs; | ||
299 | @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, | ||
300 | * emit code to generate a software step exception | ||
301 | * end the TB | ||
302 | */ | ||
303 | - dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags); | ||
304 | - dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags); | ||
305 | + dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE); | ||
306 | + dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS); | ||
307 | dc->is_ldex = false; | ||
308 | dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el); | ||
309 | |||
310 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
311 | index XXXXXXX..XXXXXXX 100644 | ||
312 | --- a/target/arm/translate.c | ||
313 | +++ b/target/arm/translate.c | ||
314 | @@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) | ||
315 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
316 | CPUARMState *env = cs->env_ptr; | ||
317 | ARMCPU *cpu = arm_env_get_cpu(env); | ||
318 | + uint32_t tb_flags = dc->base.tb->flags; | ||
319 | + uint32_t condexec, core_mmu_idx; | ||
320 | |||
321 | dc->isar = &cpu->isar; | ||
322 | dc->pc = dc->base.pc_first; | ||
323 | @@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) | ||
324 | */ | ||
325 | dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && | ||
326 | !arm_el_is_aa64(env, 3); | ||
327 | - dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags); | ||
328 | - dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags); | ||
329 | - dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE; | ||
330 | - dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1; | ||
331 | - dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4; | ||
332 | - dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags)); | ||
333 | + dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB); | ||
334 | + dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B); | ||
335 | + dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE; | ||
336 | + condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC); | ||
337 | + dc->condexec_mask = (condexec & 0xf) << 1; | ||
338 | + dc->condexec_cond = condexec >> 4; | ||
339 | + core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX); | ||
340 | + dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx); | ||
341 | dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx); | ||
342 | #if !defined(CONFIG_USER_ONLY) | ||
343 | dc->user = (dc->current_el == 0); | ||
344 | #endif | ||
345 | - dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags); | ||
346 | - dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags); | ||
347 | - dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags); | ||
348 | - dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags); | ||
349 | - dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags); | ||
350 | - dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags); | ||
351 | - dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags); | ||
352 | + dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS); | ||
353 | + dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL); | ||
354 | + dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN); | ||
355 | + dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN); | ||
356 | + dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE); | ||
357 | + dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR); | ||
358 | + dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER); | ||
359 | dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) && | ||
360 | regime_is_secure(env, dc->mmu_idx); | ||
361 | - dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags); | ||
362 | + dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK); | ||
363 | dc->cp_regs = cpu->cp_regs; | ||
364 | dc->features = env->features; | ||
365 | |||
366 | @@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) | ||
367 | * emit code to generate a software step exception | ||
368 | * end the TB | ||
369 | */ | ||
370 | - dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags); | ||
371 | - dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags); | ||
372 | + dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE); | ||
373 | + dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS); | ||
374 | dc->is_ldex = false; | ||
375 | dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */ | ||
376 | |||
377 | @@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb) | ||
378 | DisasContext dc; | ||
379 | const TranslatorOps *ops = &arm_translator_ops; | ||
380 | |||
381 | - if (ARM_TBFLAG_THUMB(tb->flags)) { | ||
382 | + if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) { | ||
383 | ops = &thumb_translator_ops; | ||
384 | } | ||
385 | #ifdef TARGET_AARCH64 | ||
386 | - if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { | ||
387 | + if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) { | ||
388 | ops = &aarch64_translator_ops; | ||
389 | } | ||
390 | #endif | ||
96 | -- | 391 | -- |
97 | 2.7.4 | 392 | 2.19.2 |
98 | 393 | ||
99 | 394 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Richard Henderson <richard.henderson@linaro.org> |
---|---|---|---|
2 | 2 | ||
3 | Not enabled anywhere so far. | 3 | While brk[ab] zeroing has a flags setting option, the merging variant |
4 | does not. Retain the same argument structure, to share expansion but | ||
5 | force the flag zero and do not decode bit 22. | ||
4 | 6 | ||
7 | Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com> | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | Message-id: 20180119045438.28582-11-richard.henderson@linaro.org | 9 | Message-id: 20181226215003.31438-1-richard.henderson@linaro.org |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 12 | --- |
11 | target/arm/cpu.h | 1 + | 13 | target/arm/sve.decode | 5 +++-- |
12 | 1 file changed, 1 insertion(+) | 14 | 1 file changed, 3 insertions(+), 2 deletions(-) |
13 | 15 | ||
14 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 16 | diff --git a/target/arm/sve.decode b/target/arm/sve.decode |
15 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/cpu.h | 18 | --- a/target/arm/sve.decode |
17 | +++ b/target/arm/cpu.h | 19 | +++ b/target/arm/sve.decode |
18 | @@ -XXX,XX +XXX,XX @@ enum arm_features { | 20 | @@ -XXX,XX +XXX,XX @@ |
19 | ARM_FEATURE_VBAR, /* has cp15 VBAR */ | 21 | |
20 | ARM_FEATURE_M_SECURITY, /* M profile Security Extension */ | 22 | # Two operand with governing predicate, flags setting |
21 | ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */ | 23 | @pd_pg_pn_s ........ . s:1 ...... .. pg:4 . rn:4 . rd:4 &rpr_s |
22 | + ARM_FEATURE_SVE, /* has Scalable Vector Extension */ | 24 | +@pd_pg_pn_s0 ........ . . ...... .. pg:4 . rn:4 . rd:4 &rpr_s s=0 |
23 | }; | 25 | |
24 | 26 | # Three operand with unused vector element size | |
25 | static inline int arm_feature(CPUARMState *env, int feature) | 27 | @rd_rn_rm_e0 ........ ... rm:5 ... ... rn:5 rd:5 &rrr_esz esz=0 |
28 | @@ -XXX,XX +XXX,XX @@ BRKPB 00100101 0. 00 .... 11 .... 0 .... 1 .... @pd_pg_pn_pm_s | ||
29 | # SVE partition break condition | ||
30 | BRKA_z 00100101 0. 01000001 .... 0 .... 0 .... @pd_pg_pn_s | ||
31 | BRKB_z 00100101 1. 01000001 .... 0 .... 0 .... @pd_pg_pn_s | ||
32 | -BRKA_m 00100101 0. 01000001 .... 0 .... 1 .... @pd_pg_pn_s | ||
33 | -BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s | ||
34 | +BRKA_m 00100101 00 01000001 .... 0 .... 1 .... @pd_pg_pn_s0 | ||
35 | +BRKB_m 00100101 10 01000001 .... 0 .... 1 .... @pd_pg_pn_s0 | ||
36 | |||
37 | # SVE propagate break to next partition | ||
38 | BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s | ||
26 | -- | 39 | -- |
27 | 2.7.4 | 40 | 2.19.2 |
28 | 41 | ||
29 | 42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | This commit adds the cpu-cluster type. It aims at gathering CPUs from | ||
4 | the same cluster in a machine. | ||
5 | |||
6 | For now it only has a `cluster-id` property. | ||
7 | |||
8 | Documentation in cluster.h written with the help of Peter Maydell. | ||
9 | |||
10 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
11 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
14 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
15 | Message-id: 20181207090135.7651-2-luc.michel@greensocs.com | ||
16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
17 | --- | ||
18 | hw/cpu/Makefile.objs | 2 +- | ||
19 | include/hw/cpu/cluster.h | 58 ++++++++++++++++++++++++++++++++++++++++ | ||
20 | hw/cpu/cluster.c | 50 ++++++++++++++++++++++++++++++++++ | ||
21 | MAINTAINERS | 2 ++ | ||
22 | 4 files changed, 111 insertions(+), 1 deletion(-) | ||
23 | create mode 100644 include/hw/cpu/cluster.h | ||
24 | create mode 100644 hw/cpu/cluster.c | ||
25 | |||
26 | diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/hw/cpu/Makefile.objs | ||
29 | +++ b/hw/cpu/Makefile.objs | ||
30 | @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o | ||
31 | obj-$(CONFIG_REALVIEW) += realview_mpcore.o | ||
32 | obj-$(CONFIG_A9MPCORE) += a9mpcore.o | ||
33 | obj-$(CONFIG_A15MPCORE) += a15mpcore.o | ||
34 | -common-obj-y += core.o | ||
35 | +common-obj-y += core.o cluster.o | ||
36 | diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h | ||
37 | new file mode 100644 | ||
38 | index XXXXXXX..XXXXXXX | ||
39 | --- /dev/null | ||
40 | +++ b/include/hw/cpu/cluster.h | ||
41 | @@ -XXX,XX +XXX,XX @@ | ||
42 | +/* | ||
43 | + * QEMU CPU cluster | ||
44 | + * | ||
45 | + * Copyright (c) 2018 GreenSocs SAS | ||
46 | + * | ||
47 | + * This program is free software; you can redistribute it and/or | ||
48 | + * modify it under the terms of the GNU General Public License | ||
49 | + * as published by the Free Software Foundation; either version 2 | ||
50 | + * of the License, or (at your option) any later version. | ||
51 | + * | ||
52 | + * This program is distributed in the hope that it will be useful, | ||
53 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
54 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
55 | + * GNU General Public License for more details. | ||
56 | + * | ||
57 | + * You should have received a copy of the GNU General Public License | ||
58 | + * along with this program; if not, see | ||
59 | + * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
60 | + */ | ||
61 | +#ifndef HW_CPU_CLUSTER_H | ||
62 | +#define HW_CPU_CLUSTER_H | ||
63 | + | ||
64 | +#include "qemu/osdep.h" | ||
65 | +#include "hw/qdev.h" | ||
66 | + | ||
67 | +/* | ||
68 | + * CPU Cluster type | ||
69 | + * | ||
70 | + * A cluster is a group of CPUs which are all identical and have the same view | ||
71 | + * of the rest of the system. It is mainly an internal QEMU representation and | ||
72 | + * does not necessarily match with the notion of clusters on the real hardware. | ||
73 | + * | ||
74 | + * If CPUs are not identical (for example, Cortex-A53 and Cortex-A57 CPUs in an | ||
75 | + * Arm big.LITTLE system) they should be in different clusters. If the CPUs do | ||
76 | + * not have the same view of memory (for example the main CPU and a management | ||
77 | + * controller processor) they should be in different clusters. | ||
78 | + */ | ||
79 | + | ||
80 | +#define TYPE_CPU_CLUSTER "cpu-cluster" | ||
81 | +#define CPU_CLUSTER(obj) \ | ||
82 | + OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER) | ||
83 | + | ||
84 | +/** | ||
85 | + * CPUClusterState: | ||
86 | + * @cluster_id: The cluster ID. This value is for internal use only and should | ||
87 | + * not be exposed directly to the user or to the guest. | ||
88 | + * | ||
89 | + * State of a CPU cluster. | ||
90 | + */ | ||
91 | +typedef struct CPUClusterState { | ||
92 | + /*< private >*/ | ||
93 | + DeviceState parent_obj; | ||
94 | + | ||
95 | + /*< public >*/ | ||
96 | + uint32_t cluster_id; | ||
97 | +} CPUClusterState; | ||
98 | + | ||
99 | +#endif | ||
100 | diff --git a/hw/cpu/cluster.c b/hw/cpu/cluster.c | ||
101 | new file mode 100644 | ||
102 | index XXXXXXX..XXXXXXX | ||
103 | --- /dev/null | ||
104 | +++ b/hw/cpu/cluster.c | ||
105 | @@ -XXX,XX +XXX,XX @@ | ||
106 | +/* | ||
107 | + * QEMU CPU cluster | ||
108 | + * | ||
109 | + * Copyright (c) 2018 GreenSocs SAS | ||
110 | + * | ||
111 | + * This program is free software; you can redistribute it and/or | ||
112 | + * modify it under the terms of the GNU General Public License | ||
113 | + * as published by the Free Software Foundation; either version 2 | ||
114 | + * of the License, or (at your option) any later version. | ||
115 | + * | ||
116 | + * This program is distributed in the hope that it will be useful, | ||
117 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
118 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
119 | + * GNU General Public License for more details. | ||
120 | + * | ||
121 | + * You should have received a copy of the GNU General Public License | ||
122 | + * along with this program; if not, see | ||
123 | + * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
124 | + */ | ||
125 | + | ||
126 | +#include "qemu/osdep.h" | ||
127 | +#include "hw/cpu/cluster.h" | ||
128 | +#include "qapi/error.h" | ||
129 | +#include "qemu/module.h" | ||
130 | + | ||
131 | +static Property cpu_cluster_properties[] = { | ||
132 | + DEFINE_PROP_UINT32("cluster-id", CPUClusterState, cluster_id, 0), | ||
133 | + DEFINE_PROP_END_OF_LIST() | ||
134 | +}; | ||
135 | + | ||
136 | +static void cpu_cluster_class_init(ObjectClass *klass, void *data) | ||
137 | +{ | ||
138 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
139 | + | ||
140 | + dc->props = cpu_cluster_properties; | ||
141 | +} | ||
142 | + | ||
143 | +static const TypeInfo cpu_cluster_type_info = { | ||
144 | + .name = TYPE_CPU_CLUSTER, | ||
145 | + .parent = TYPE_DEVICE, | ||
146 | + .instance_size = sizeof(CPUClusterState), | ||
147 | + .class_init = cpu_cluster_class_init, | ||
148 | +}; | ||
149 | + | ||
150 | +static void cpu_cluster_register_types(void) | ||
151 | +{ | ||
152 | + type_register_static(&cpu_cluster_type_info); | ||
153 | +} | ||
154 | + | ||
155 | +type_init(cpu_cluster_register_types) | ||
156 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
157 | index XXXXXXX..XXXXXXX 100644 | ||
158 | --- a/MAINTAINERS | ||
159 | +++ b/MAINTAINERS | ||
160 | @@ -XXX,XX +XXX,XX @@ M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
161 | S: Supported | ||
162 | F: hw/core/machine.c | ||
163 | F: hw/core/null-machine.c | ||
164 | +F: hw/cpu/cluster.c | ||
165 | F: include/hw/boards.h | ||
166 | +F: include/hw/cpu/cluster.h | ||
167 | T: git https://github.com/ehabkost/qemu.git machine-next | ||
168 | |||
169 | Xtensa Machines | ||
170 | -- | ||
171 | 2.19.2 | ||
172 | |||
173 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Luc Michel <luc.michel@greensocs.com> |
---|---|---|---|
2 | 2 | ||
3 | Rather than passing regnos to the helpers, pass pointers to the | 3 | Add a structure GDBProcess that represents processes from the GDB |
4 | vector registers directly. This eliminates the need to pass in | 4 | semantic point of view. |
5 | the environment pointer and reduces the number of places that | ||
6 | directly access env->vfp.regs[]. | ||
7 | 5 | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 6 | CPUs can be split into different processes, by grouping them under |
9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 7 | different cpu-cluster objects. Each occurrence of a cpu-cluster object |
10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 8 | implies the existence of the corresponding process in the GDB stub. The |
11 | Message-id: 20180119045438.28582-3-richard.henderson@linaro.org | 9 | GDB process ID is derived from the corresponding cluster ID as follows: |
10 | |||
11 | GDB PID = cluster ID + 1 | ||
12 | |||
13 | This is because PIDs -1 and 0 are reserved in GDB and cannot be used by | ||
14 | processes. | ||
15 | |||
16 | A default process is created to handle CPUs that are not in a cluster. | ||
17 | This process gets the PID of the last process PID + 1. | ||
18 | |||
19 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
20 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
21 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
22 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
23 | Message-id: 20181207090135.7651-3-luc.michel@greensocs.com | ||
24 | [PMM: fixed checkpatch nit about block comment style] | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 25 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
13 | --- | 26 | --- |
14 | target/arm/helper.h | 18 ++--- | 27 | gdbstub.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
15 | target/arm/crypto_helper.c | 184 +++++++++++++++++---------------------------- | 28 | 1 file changed, 97 insertions(+) |
16 | target/arm/translate-a64.c | 75 ++++++++++-------- | ||
17 | target/arm/translate.c | 68 +++++++++-------- | ||
18 | 4 files changed, 161 insertions(+), 184 deletions(-) | ||
19 | 29 | ||
20 | diff --git a/target/arm/helper.h b/target/arm/helper.h | 30 | diff --git a/gdbstub.c b/gdbstub.c |
21 | index XXXXXXX..XXXXXXX 100644 | 31 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/target/arm/helper.h | 32 | --- a/gdbstub.c |
23 | +++ b/target/arm/helper.h | 33 | +++ b/gdbstub.c |
24 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(neon_qzip8, void, env, i32, i32) | 34 | @@ -XXX,XX +XXX,XX @@ |
25 | DEF_HELPER_3(neon_qzip16, void, env, i32, i32) | 35 | #include "chardev/char-fe.h" |
26 | DEF_HELPER_3(neon_qzip32, void, env, i32, i32) | 36 | #include "sysemu/sysemu.h" |
27 | 37 | #include "exec/gdbstub.h" | |
28 | -DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32) | 38 | +#include "hw/cpu/cluster.h" |
29 | -DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32) | ||
30 | +DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32) | ||
31 | +DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32) | ||
32 | |||
33 | -DEF_HELPER_5(crypto_sha1_3reg, void, env, i32, i32, i32, i32) | ||
34 | -DEF_HELPER_3(crypto_sha1h, void, env, i32, i32) | ||
35 | -DEF_HELPER_3(crypto_sha1su1, void, env, i32, i32) | ||
36 | +DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) | ||
37 | +DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr) | ||
38 | +DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr) | ||
39 | |||
40 | -DEF_HELPER_4(crypto_sha256h, void, env, i32, i32, i32) | ||
41 | -DEF_HELPER_4(crypto_sha256h2, void, env, i32, i32, i32) | ||
42 | -DEF_HELPER_3(crypto_sha256su0, void, env, i32, i32) | ||
43 | -DEF_HELPER_4(crypto_sha256su1, void, env, i32, i32, i32) | ||
44 | +DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) | ||
45 | +DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) | ||
46 | +DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr) | ||
47 | +DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) | ||
48 | |||
49 | DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) | ||
50 | DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) | ||
51 | diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/target/arm/crypto_helper.c | ||
54 | +++ b/target/arm/crypto_helper.c | ||
55 | @@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE { | ||
56 | #define CR_ST_WORD(state, i) (state.words[i]) | ||
57 | #endif | 39 | #endif |
58 | 40 | ||
59 | -void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, | 41 | #define MAX_PACKET_LENGTH 4096 |
60 | - uint32_t decrypt) | 42 | @@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState { |
61 | +void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt) | 43 | struct GDBRegisterState *next; |
62 | { | 44 | } GDBRegisterState; |
63 | static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox }; | 45 | |
64 | static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts }; | 46 | +typedef struct GDBProcess { |
65 | - | 47 | + uint32_t pid; |
66 | - union CRYPTO_STATE rk = { .l = { | 48 | + bool attached; |
67 | - float64_val(env->vfp.regs[rm]), | 49 | +} GDBProcess; |
68 | - float64_val(env->vfp.regs[rm + 1]) | 50 | + |
69 | - } }; | 51 | enum RSState { |
70 | - union CRYPTO_STATE st = { .l = { | 52 | RS_INACTIVE, |
71 | - float64_val(env->vfp.regs[rd]), | 53 | RS_IDLE, |
72 | - float64_val(env->vfp.regs[rd + 1]) | 54 | @@ -XXX,XX +XXX,XX @@ typedef struct GDBState { |
73 | - } }; | 55 | CharBackend chr; |
74 | + uint64_t *rd = vd; | 56 | Chardev *mon_chr; |
75 | + uint64_t *rm = vm; | 57 | #endif |
76 | + union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } }; | 58 | + bool multiprocess; |
77 | + union CRYPTO_STATE st = { .l = { rd[0], rd[1] } }; | 59 | + GDBProcess *processes; |
78 | int i; | 60 | + int process_num; |
79 | 61 | char syscall_buf[256]; | |
80 | assert(decrypt < 2); | 62 | gdb_syscall_complete_cb current_syscall_cb; |
81 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, | 63 | } GDBState; |
82 | CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])]; | 64 | @@ -XXX,XX +XXX,XX @@ void gdb_exit(CPUArchState *env, int code) |
83 | } | 65 | #endif |
84 | |||
85 | - env->vfp.regs[rd] = make_float64(st.l[0]); | ||
86 | - env->vfp.regs[rd + 1] = make_float64(st.l[1]); | ||
87 | + rd[0] = st.l[0]; | ||
88 | + rd[1] = st.l[1]; | ||
89 | } | 66 | } |
90 | 67 | ||
91 | -void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, | 68 | +/* |
92 | - uint32_t decrypt) | 69 | + * Create the process that will contain all the "orphan" CPUs (that are not |
93 | +void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt) | 70 | + * part of a CPU cluster). Note that if this process contains no CPUs, it won't |
94 | { | 71 | + * be attachable and thus will be invisible to the user. |
95 | static uint32_t const mc[][256] = { { | 72 | + */ |
96 | /* MixColumns lookup table */ | 73 | +static void create_default_process(GDBState *s) |
97 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, | 74 | +{ |
98 | 0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5, | 75 | + GDBProcess *process; |
99 | 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d, | 76 | + int max_pid = 0; |
100 | } }; | ||
101 | - union CRYPTO_STATE st = { .l = { | ||
102 | - float64_val(env->vfp.regs[rm]), | ||
103 | - float64_val(env->vfp.regs[rm + 1]) | ||
104 | - } }; | ||
105 | + | 77 | + |
106 | + uint64_t *rd = vd; | 78 | + if (s->process_num) { |
107 | + uint64_t *rm = vm; | 79 | + max_pid = s->processes[s->process_num - 1].pid; |
108 | + union CRYPTO_STATE st = { .l = { rm[0], rm[1] } }; | 80 | + } |
109 | int i; | 81 | + |
110 | 82 | + s->processes = g_renew(GDBProcess, s->processes, ++s->process_num); | |
111 | assert(decrypt < 2); | 83 | + process = &s->processes[s->process_num - 1]; |
112 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, | 84 | + |
113 | rol32(mc[decrypt][CR_ST_BYTE(st, i + 3)], 24); | 85 | + /* We need an available PID slot for this process */ |
114 | } | 86 | + assert(max_pid < UINT32_MAX); |
115 | 87 | + | |
116 | - env->vfp.regs[rd] = make_float64(st.l[0]); | 88 | + process->pid = max_pid + 1; |
117 | - env->vfp.regs[rd + 1] = make_float64(st.l[1]); | 89 | + process->attached = false; |
118 | + rd[0] = st.l[0]; | ||
119 | + rd[1] = st.l[1]; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | @@ -XXX,XX +XXX,XX @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z) | ||
124 | return (x & y) | ((x | y) & z); | ||
125 | } | ||
126 | |||
127 | -void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
128 | - uint32_t rm, uint32_t op) | ||
129 | +void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op) | ||
130 | { | ||
131 | - union CRYPTO_STATE d = { .l = { | ||
132 | - float64_val(env->vfp.regs[rd]), | ||
133 | - float64_val(env->vfp.regs[rd + 1]) | ||
134 | - } }; | ||
135 | - union CRYPTO_STATE n = { .l = { | ||
136 | - float64_val(env->vfp.regs[rn]), | ||
137 | - float64_val(env->vfp.regs[rn + 1]) | ||
138 | - } }; | ||
139 | - union CRYPTO_STATE m = { .l = { | ||
140 | - float64_val(env->vfp.regs[rm]), | ||
141 | - float64_val(env->vfp.regs[rm + 1]) | ||
142 | - } }; | ||
143 | + uint64_t *rd = vd; | ||
144 | + uint64_t *rn = vn; | ||
145 | + uint64_t *rm = vm; | ||
146 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
147 | + union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; | ||
148 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
149 | |||
150 | if (op == 3) { /* sha1su0 */ | ||
151 | d.l[0] ^= d.l[1] ^ m.l[0]; | ||
152 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
153 | CR_ST_WORD(d, 0) = t; | ||
154 | } | ||
155 | } | ||
156 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
157 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
158 | + rd[0] = d.l[0]; | ||
159 | + rd[1] = d.l[1]; | ||
160 | } | ||
161 | |||
162 | -void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
163 | +void HELPER(crypto_sha1h)(void *vd, void *vm) | ||
164 | { | ||
165 | - union CRYPTO_STATE m = { .l = { | ||
166 | - float64_val(env->vfp.regs[rm]), | ||
167 | - float64_val(env->vfp.regs[rm + 1]) | ||
168 | - } }; | ||
169 | + uint64_t *rd = vd; | ||
170 | + uint64_t *rm = vm; | ||
171 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
172 | |||
173 | CR_ST_WORD(m, 0) = ror32(CR_ST_WORD(m, 0), 2); | ||
174 | CR_ST_WORD(m, 1) = CR_ST_WORD(m, 2) = CR_ST_WORD(m, 3) = 0; | ||
175 | |||
176 | - env->vfp.regs[rd] = make_float64(m.l[0]); | ||
177 | - env->vfp.regs[rd + 1] = make_float64(m.l[1]); | ||
178 | + rd[0] = m.l[0]; | ||
179 | + rd[1] = m.l[1]; | ||
180 | } | ||
181 | |||
182 | -void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
183 | +void HELPER(crypto_sha1su1)(void *vd, void *vm) | ||
184 | { | ||
185 | - union CRYPTO_STATE d = { .l = { | ||
186 | - float64_val(env->vfp.regs[rd]), | ||
187 | - float64_val(env->vfp.regs[rd + 1]) | ||
188 | - } }; | ||
189 | - union CRYPTO_STATE m = { .l = { | ||
190 | - float64_val(env->vfp.regs[rm]), | ||
191 | - float64_val(env->vfp.regs[rm + 1]) | ||
192 | - } }; | ||
193 | + uint64_t *rd = vd; | ||
194 | + uint64_t *rm = vm; | ||
195 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
196 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
197 | |||
198 | CR_ST_WORD(d, 0) = rol32(CR_ST_WORD(d, 0) ^ CR_ST_WORD(m, 1), 1); | ||
199 | CR_ST_WORD(d, 1) = rol32(CR_ST_WORD(d, 1) ^ CR_ST_WORD(m, 2), 1); | ||
200 | CR_ST_WORD(d, 2) = rol32(CR_ST_WORD(d, 2) ^ CR_ST_WORD(m, 3), 1); | ||
201 | CR_ST_WORD(d, 3) = rol32(CR_ST_WORD(d, 3) ^ CR_ST_WORD(d, 0), 1); | ||
202 | |||
203 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
204 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
205 | + rd[0] = d.l[0]; | ||
206 | + rd[1] = d.l[1]; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | @@ -XXX,XX +XXX,XX @@ static uint32_t s1(uint32_t x) | ||
211 | return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10); | ||
212 | } | ||
213 | |||
214 | -void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
215 | - uint32_t rm) | ||
216 | +void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm) | ||
217 | { | ||
218 | - union CRYPTO_STATE d = { .l = { | ||
219 | - float64_val(env->vfp.regs[rd]), | ||
220 | - float64_val(env->vfp.regs[rd + 1]) | ||
221 | - } }; | ||
222 | - union CRYPTO_STATE n = { .l = { | ||
223 | - float64_val(env->vfp.regs[rn]), | ||
224 | - float64_val(env->vfp.regs[rn + 1]) | ||
225 | - } }; | ||
226 | - union CRYPTO_STATE m = { .l = { | ||
227 | - float64_val(env->vfp.regs[rm]), | ||
228 | - float64_val(env->vfp.regs[rm + 1]) | ||
229 | - } }; | ||
230 | + uint64_t *rd = vd; | ||
231 | + uint64_t *rn = vn; | ||
232 | + uint64_t *rm = vm; | ||
233 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
234 | + union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; | ||
235 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
236 | int i; | ||
237 | |||
238 | for (i = 0; i < 4; i++) { | ||
239 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
240 | CR_ST_WORD(d, 0) = t; | ||
241 | } | ||
242 | |||
243 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
244 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
245 | + rd[0] = d.l[0]; | ||
246 | + rd[1] = d.l[1]; | ||
247 | } | ||
248 | |||
249 | -void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
250 | - uint32_t rm) | ||
251 | +void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm) | ||
252 | { | ||
253 | - union CRYPTO_STATE d = { .l = { | ||
254 | - float64_val(env->vfp.regs[rd]), | ||
255 | - float64_val(env->vfp.regs[rd + 1]) | ||
256 | - } }; | ||
257 | - union CRYPTO_STATE n = { .l = { | ||
258 | - float64_val(env->vfp.regs[rn]), | ||
259 | - float64_val(env->vfp.regs[rn + 1]) | ||
260 | - } }; | ||
261 | - union CRYPTO_STATE m = { .l = { | ||
262 | - float64_val(env->vfp.regs[rm]), | ||
263 | - float64_val(env->vfp.regs[rm + 1]) | ||
264 | - } }; | ||
265 | + uint64_t *rd = vd; | ||
266 | + uint64_t *rn = vn; | ||
267 | + uint64_t *rm = vm; | ||
268 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
269 | + union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; | ||
270 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
271 | int i; | ||
272 | |||
273 | for (i = 0; i < 4; i++) { | ||
274 | @@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
275 | CR_ST_WORD(d, 0) = CR_ST_WORD(n, 3 - i) + t; | ||
276 | } | ||
277 | |||
278 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
279 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
280 | + rd[0] = d.l[0]; | ||
281 | + rd[1] = d.l[1]; | ||
282 | } | ||
283 | |||
284 | -void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
285 | +void HELPER(crypto_sha256su0)(void *vd, void *vm) | ||
286 | { | ||
287 | - union CRYPTO_STATE d = { .l = { | ||
288 | - float64_val(env->vfp.regs[rd]), | ||
289 | - float64_val(env->vfp.regs[rd + 1]) | ||
290 | - } }; | ||
291 | - union CRYPTO_STATE m = { .l = { | ||
292 | - float64_val(env->vfp.regs[rm]), | ||
293 | - float64_val(env->vfp.regs[rm + 1]) | ||
294 | - } }; | ||
295 | + uint64_t *rd = vd; | ||
296 | + uint64_t *rm = vm; | ||
297 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
298 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
299 | |||
300 | CR_ST_WORD(d, 0) += s0(CR_ST_WORD(d, 1)); | ||
301 | CR_ST_WORD(d, 1) += s0(CR_ST_WORD(d, 2)); | ||
302 | CR_ST_WORD(d, 2) += s0(CR_ST_WORD(d, 3)); | ||
303 | CR_ST_WORD(d, 3) += s0(CR_ST_WORD(m, 0)); | ||
304 | |||
305 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
306 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
307 | + rd[0] = d.l[0]; | ||
308 | + rd[1] = d.l[1]; | ||
309 | } | ||
310 | |||
311 | -void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn, | ||
312 | - uint32_t rm) | ||
313 | +void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm) | ||
314 | { | ||
315 | - union CRYPTO_STATE d = { .l = { | ||
316 | - float64_val(env->vfp.regs[rd]), | ||
317 | - float64_val(env->vfp.regs[rd + 1]) | ||
318 | - } }; | ||
319 | - union CRYPTO_STATE n = { .l = { | ||
320 | - float64_val(env->vfp.regs[rn]), | ||
321 | - float64_val(env->vfp.regs[rn + 1]) | ||
322 | - } }; | ||
323 | - union CRYPTO_STATE m = { .l = { | ||
324 | - float64_val(env->vfp.regs[rm]), | ||
325 | - float64_val(env->vfp.regs[rm + 1]) | ||
326 | - } }; | ||
327 | + uint64_t *rd = vd; | ||
328 | + uint64_t *rn = vn; | ||
329 | + uint64_t *rm = vm; | ||
330 | + union CRYPTO_STATE d = { .l = { rd[0], rd[1] } }; | ||
331 | + union CRYPTO_STATE n = { .l = { rn[0], rn[1] } }; | ||
332 | + union CRYPTO_STATE m = { .l = { rm[0], rm[1] } }; | ||
333 | |||
334 | CR_ST_WORD(d, 0) += s1(CR_ST_WORD(m, 2)) + CR_ST_WORD(n, 1); | ||
335 | CR_ST_WORD(d, 1) += s1(CR_ST_WORD(m, 3)) + CR_ST_WORD(n, 2); | ||
336 | CR_ST_WORD(d, 2) += s1(CR_ST_WORD(d, 0)) + CR_ST_WORD(n, 3); | ||
337 | CR_ST_WORD(d, 3) += s1(CR_ST_WORD(d, 1)) + CR_ST_WORD(m, 0); | ||
338 | |||
339 | - env->vfp.regs[rd] = make_float64(d.l[0]); | ||
340 | - env->vfp.regs[rd + 1] = make_float64(d.l[1]); | ||
341 | + rd[0] = d.l[0]; | ||
342 | + rd[1] = d.l[1]; | ||
343 | } | ||
344 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
345 | index XXXXXXX..XXXXXXX 100644 | ||
346 | --- a/target/arm/translate-a64.c | ||
347 | +++ b/target/arm/translate-a64.c | ||
348 | @@ -XXX,XX +XXX,XX @@ typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32); | ||
349 | typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); | ||
350 | typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); | ||
351 | typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64); | ||
352 | -typedef void CryptoTwoOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32); | ||
353 | -typedef void CryptoThreeOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32); | ||
354 | +typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr); | ||
355 | +typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); | ||
356 | +typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); | ||
357 | |||
358 | /* initialize TCG globals. */ | ||
359 | void a64_translate_init(void) | ||
360 | @@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno, | ||
361 | return offs; | ||
362 | } | ||
363 | |||
364 | +/* Return the offset info CPUARMState of the "whole" vector register Qn. */ | ||
365 | +static inline int vec_full_reg_offset(DisasContext *s, int regno) | ||
366 | +{ | ||
367 | + assert_fp_access_checked(s); | ||
368 | + return offsetof(CPUARMState, vfp.regs[regno * 2]); | ||
369 | +} | 90 | +} |
370 | + | 91 | + |
371 | +/* Return a newly allocated pointer to the vector register. */ | 92 | #ifdef CONFIG_USER_ONLY |
372 | +static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno) | 93 | int |
94 | gdb_handlesig(CPUState *cpu, int sig) | ||
95 | @@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void) | ||
96 | s = g_malloc0(sizeof(GDBState)); | ||
97 | s->c_cpu = first_cpu; | ||
98 | s->g_cpu = first_cpu; | ||
99 | + create_default_process(s); | ||
100 | s->fd = fd; | ||
101 | gdb_has_xml = false; | ||
102 | |||
103 | @@ -XXX,XX +XXX,XX @@ static const TypeInfo char_gdb_type_info = { | ||
104 | .class_init = char_gdb_class_init, | ||
105 | }; | ||
106 | |||
107 | +static int find_cpu_clusters(Object *child, void *opaque) | ||
373 | +{ | 108 | +{ |
374 | + TCGv_ptr ret = tcg_temp_new_ptr(); | 109 | + if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) { |
375 | + tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno)); | 110 | + GDBState *s = (GDBState *) opaque; |
376 | + return ret; | 111 | + CPUClusterState *cluster = CPU_CLUSTER(child); |
112 | + GDBProcess *process; | ||
113 | + | ||
114 | + s->processes = g_renew(GDBProcess, s->processes, ++s->process_num); | ||
115 | + | ||
116 | + process = &s->processes[s->process_num - 1]; | ||
117 | + | ||
118 | + /* | ||
119 | + * GDB process IDs -1 and 0 are reserved. To avoid subtle errors at | ||
120 | + * runtime, we enforce here that the machine does not use a cluster ID | ||
121 | + * that would lead to PID 0. | ||
122 | + */ | ||
123 | + assert(cluster->cluster_id != UINT32_MAX); | ||
124 | + process->pid = cluster->cluster_id + 1; | ||
125 | + process->attached = false; | ||
126 | + | ||
127 | + return 0; | ||
128 | + } | ||
129 | + | ||
130 | + return object_child_foreach(child, find_cpu_clusters, opaque); | ||
377 | +} | 131 | +} |
378 | + | 132 | + |
379 | /* Return the offset into CPUARMState of a slice (from | 133 | +static int pid_order(const void *a, const void *b) |
380 | * the least significant end) of FP register Qn (ie | ||
381 | * Dn, Sn, Hn or Bn). | ||
382 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn) | ||
383 | int rn = extract32(insn, 5, 5); | ||
384 | int rd = extract32(insn, 0, 5); | ||
385 | int decrypt; | ||
386 | - TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_decrypt; | ||
387 | - CryptoThreeOpEnvFn *genfn; | ||
388 | + TCGv_ptr tcg_rd_ptr, tcg_rn_ptr; | ||
389 | + TCGv_i32 tcg_decrypt; | ||
390 | + CryptoThreeOpIntFn *genfn; | ||
391 | |||
392 | if (!arm_dc_feature(s, ARM_FEATURE_V8_AES) | ||
393 | || size != 0) { | ||
394 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn) | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | - /* Note that we convert the Vx register indexes into the | ||
399 | - * index within the vfp.regs[] array, so we can share the | ||
400 | - * helper with the AArch32 instructions. | ||
401 | - */ | ||
402 | - tcg_rd_regno = tcg_const_i32(rd << 1); | ||
403 | - tcg_rn_regno = tcg_const_i32(rn << 1); | ||
404 | + tcg_rd_ptr = vec_full_reg_ptr(s, rd); | ||
405 | + tcg_rn_ptr = vec_full_reg_ptr(s, rn); | ||
406 | tcg_decrypt = tcg_const_i32(decrypt); | ||
407 | |||
408 | - genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_decrypt); | ||
409 | + genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt); | ||
410 | |||
411 | - tcg_temp_free_i32(tcg_rd_regno); | ||
412 | - tcg_temp_free_i32(tcg_rn_regno); | ||
413 | + tcg_temp_free_ptr(tcg_rd_ptr); | ||
414 | + tcg_temp_free_ptr(tcg_rn_ptr); | ||
415 | tcg_temp_free_i32(tcg_decrypt); | ||
416 | } | ||
417 | |||
418 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn) | ||
419 | int rm = extract32(insn, 16, 5); | ||
420 | int rn = extract32(insn, 5, 5); | ||
421 | int rd = extract32(insn, 0, 5); | ||
422 | - CryptoThreeOpEnvFn *genfn; | ||
423 | - TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_rm_regno; | ||
424 | + CryptoThreeOpFn *genfn; | ||
425 | + TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr; | ||
426 | int feature = ARM_FEATURE_V8_SHA256; | ||
427 | |||
428 | if (size != 0) { | ||
429 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn) | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | - tcg_rd_regno = tcg_const_i32(rd << 1); | ||
434 | - tcg_rn_regno = tcg_const_i32(rn << 1); | ||
435 | - tcg_rm_regno = tcg_const_i32(rm << 1); | ||
436 | + tcg_rd_ptr = vec_full_reg_ptr(s, rd); | ||
437 | + tcg_rn_ptr = vec_full_reg_ptr(s, rn); | ||
438 | + tcg_rm_ptr = vec_full_reg_ptr(s, rm); | ||
439 | |||
440 | if (genfn) { | ||
441 | - genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_rm_regno); | ||
442 | + genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr); | ||
443 | } else { | ||
444 | TCGv_i32 tcg_opcode = tcg_const_i32(opcode); | ||
445 | |||
446 | - gen_helper_crypto_sha1_3reg(cpu_env, tcg_rd_regno, | ||
447 | - tcg_rn_regno, tcg_rm_regno, tcg_opcode); | ||
448 | + gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr, | ||
449 | + tcg_rm_ptr, tcg_opcode); | ||
450 | tcg_temp_free_i32(tcg_opcode); | ||
451 | } | ||
452 | |||
453 | - tcg_temp_free_i32(tcg_rd_regno); | ||
454 | - tcg_temp_free_i32(tcg_rn_regno); | ||
455 | - tcg_temp_free_i32(tcg_rm_regno); | ||
456 | + tcg_temp_free_ptr(tcg_rd_ptr); | ||
457 | + tcg_temp_free_ptr(tcg_rn_ptr); | ||
458 | + tcg_temp_free_ptr(tcg_rm_ptr); | ||
459 | } | ||
460 | |||
461 | /* Crypto two-reg SHA | ||
462 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn) | ||
463 | int opcode = extract32(insn, 12, 5); | ||
464 | int rn = extract32(insn, 5, 5); | ||
465 | int rd = extract32(insn, 0, 5); | ||
466 | - CryptoTwoOpEnvFn *genfn; | ||
467 | + CryptoTwoOpFn *genfn; | ||
468 | int feature; | ||
469 | - TCGv_i32 tcg_rd_regno, tcg_rn_regno; | ||
470 | + TCGv_ptr tcg_rd_ptr, tcg_rn_ptr; | ||
471 | |||
472 | if (size != 0) { | ||
473 | unallocated_encoding(s); | ||
474 | @@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn) | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | - tcg_rd_regno = tcg_const_i32(rd << 1); | ||
479 | - tcg_rn_regno = tcg_const_i32(rn << 1); | ||
480 | + tcg_rd_ptr = vec_full_reg_ptr(s, rd); | ||
481 | + tcg_rn_ptr = vec_full_reg_ptr(s, rn); | ||
482 | |||
483 | - genfn(cpu_env, tcg_rd_regno, tcg_rn_regno); | ||
484 | + genfn(tcg_rd_ptr, tcg_rn_ptr); | ||
485 | |||
486 | - tcg_temp_free_i32(tcg_rd_regno); | ||
487 | - tcg_temp_free_i32(tcg_rn_regno); | ||
488 | + tcg_temp_free_ptr(tcg_rd_ptr); | ||
489 | + tcg_temp_free_ptr(tcg_rn_ptr); | ||
490 | } | ||
491 | |||
492 | /* C3.6 Data processing - SIMD, inc Crypto | ||
493 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
494 | index XXXXXXX..XXXXXXX 100644 | ||
495 | --- a/target/arm/translate.c | ||
496 | +++ b/target/arm/translate.c | ||
497 | @@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg64(TCGv_i64 var, int reg) | ||
498 | tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); | ||
499 | } | ||
500 | |||
501 | +static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
502 | +{ | 134 | +{ |
503 | + TCGv_ptr ret = tcg_temp_new_ptr(); | 135 | + GDBProcess *pa = (GDBProcess *) a; |
504 | + tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg)); | 136 | + GDBProcess *pb = (GDBProcess *) b; |
505 | + return ret; | 137 | + |
138 | + if (pa->pid < pb->pid) { | ||
139 | + return -1; | ||
140 | + } else if (pa->pid > pb->pid) { | ||
141 | + return 1; | ||
142 | + } else { | ||
143 | + return 0; | ||
144 | + } | ||
506 | +} | 145 | +} |
507 | + | 146 | + |
508 | #define tcg_gen_ld_f32 tcg_gen_ld_i32 | 147 | +static void create_processes(GDBState *s) |
509 | #define tcg_gen_ld_f64 tcg_gen_ld_i64 | 148 | +{ |
510 | #define tcg_gen_st_f32 tcg_gen_st_i32 | 149 | + object_child_foreach(object_get_root(), find_cpu_clusters, s); |
511 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | 150 | + |
512 | int u; | 151 | + if (s->processes) { |
513 | uint32_t imm, mask; | 152 | + /* Sort by PID */ |
514 | TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; | 153 | + qsort(s->processes, s->process_num, sizeof(s->processes[0]), pid_order); |
515 | + TCGv_ptr ptr1, ptr2, ptr3; | 154 | + } |
516 | TCGv_i64 tmp64; | 155 | + |
517 | 156 | + create_default_process(s); | |
518 | /* FIXME: this access check should not take precedence over UNDEF | 157 | +} |
519 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | 158 | + |
520 | if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) { | 159 | +static void cleanup_processes(GDBState *s) |
521 | return 1; | 160 | +{ |
522 | } | 161 | + g_free(s->processes); |
523 | - tmp = tcg_const_i32(rd); | 162 | + s->process_num = 0; |
524 | - tmp2 = tcg_const_i32(rn); | 163 | + s->processes = NULL; |
525 | - tmp3 = tcg_const_i32(rm); | 164 | +} |
526 | + ptr1 = vfp_reg_ptr(true, rd); | 165 | + |
527 | + ptr2 = vfp_reg_ptr(true, rn); | 166 | int gdbserver_start(const char *device) |
528 | + ptr3 = vfp_reg_ptr(true, rm); | 167 | { |
529 | tmp4 = tcg_const_i32(size); | 168 | trace_gdbstub_op_start(device); |
530 | - gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4); | 169 | @@ -XXX,XX +XXX,XX @@ int gdbserver_start(const char *device) |
531 | + gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4); | 170 | } else { |
532 | tcg_temp_free_i32(tmp4); | 171 | qemu_chr_fe_deinit(&s->chr, true); |
533 | } else { /* SHA-256 */ | 172 | mon_chr = s->mon_chr; |
534 | if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) { | 173 | + cleanup_processes(s); |
535 | return 1; | 174 | memset(s, 0, sizeof(GDBState)); |
536 | } | 175 | s->mon_chr = mon_chr; |
537 | - tmp = tcg_const_i32(rd); | 176 | } |
538 | - tmp2 = tcg_const_i32(rn); | 177 | s->c_cpu = first_cpu; |
539 | - tmp3 = tcg_const_i32(rm); | 178 | s->g_cpu = first_cpu; |
540 | + ptr1 = vfp_reg_ptr(true, rd); | 179 | + |
541 | + ptr2 = vfp_reg_ptr(true, rn); | 180 | + create_processes(s); |
542 | + ptr3 = vfp_reg_ptr(true, rm); | 181 | + |
543 | switch (size) { | 182 | if (chr) { |
544 | case 0: | 183 | qemu_chr_fe_init(&s->chr, chr, &error_abort); |
545 | - gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3); | 184 | qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive, |
546 | + gen_helper_crypto_sha256h(ptr1, ptr2, ptr3); | ||
547 | break; | ||
548 | case 1: | ||
549 | - gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3); | ||
550 | + gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3); | ||
551 | break; | ||
552 | case 2: | ||
553 | - gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3); | ||
554 | + gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3); | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | - tcg_temp_free_i32(tmp); | ||
559 | - tcg_temp_free_i32(tmp2); | ||
560 | - tcg_temp_free_i32(tmp3); | ||
561 | + tcg_temp_free_ptr(ptr1); | ||
562 | + tcg_temp_free_ptr(ptr2); | ||
563 | + tcg_temp_free_ptr(ptr3); | ||
564 | return 0; | ||
565 | } | ||
566 | if (size == 3 && op != NEON_3R_LOGIC) { | ||
567 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
568 | || ((rm | rd) & 1)) { | ||
569 | return 1; | ||
570 | } | ||
571 | - tmp = tcg_const_i32(rd); | ||
572 | - tmp2 = tcg_const_i32(rm); | ||
573 | + ptr1 = vfp_reg_ptr(true, rd); | ||
574 | + ptr2 = vfp_reg_ptr(true, rm); | ||
575 | |||
576 | /* Bit 6 is the lowest opcode bit; it distinguishes between | ||
577 | * encryption (AESE/AESMC) and decryption (AESD/AESIMC) | ||
578 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
579 | tmp3 = tcg_const_i32(extract32(insn, 6, 1)); | ||
580 | |||
581 | if (op == NEON_2RM_AESE) { | ||
582 | - gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3); | ||
583 | + gen_helper_crypto_aese(ptr1, ptr2, tmp3); | ||
584 | } else { | ||
585 | - gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3); | ||
586 | + gen_helper_crypto_aesmc(ptr1, ptr2, tmp3); | ||
587 | } | ||
588 | - tcg_temp_free_i32(tmp); | ||
589 | - tcg_temp_free_i32(tmp2); | ||
590 | + tcg_temp_free_ptr(ptr1); | ||
591 | + tcg_temp_free_ptr(ptr2); | ||
592 | tcg_temp_free_i32(tmp3); | ||
593 | break; | ||
594 | case NEON_2RM_SHA1H: | ||
595 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
596 | || ((rm | rd) & 1)) { | ||
597 | return 1; | ||
598 | } | ||
599 | - tmp = tcg_const_i32(rd); | ||
600 | - tmp2 = tcg_const_i32(rm); | ||
601 | + ptr1 = vfp_reg_ptr(true, rd); | ||
602 | + ptr2 = vfp_reg_ptr(true, rm); | ||
603 | |||
604 | - gen_helper_crypto_sha1h(cpu_env, tmp, tmp2); | ||
605 | + gen_helper_crypto_sha1h(ptr1, ptr2); | ||
606 | |||
607 | - tcg_temp_free_i32(tmp); | ||
608 | - tcg_temp_free_i32(tmp2); | ||
609 | + tcg_temp_free_ptr(ptr1); | ||
610 | + tcg_temp_free_ptr(ptr2); | ||
611 | break; | ||
612 | case NEON_2RM_SHA1SU1: | ||
613 | if ((rm | rd) & 1) { | ||
614 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
615 | } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) { | ||
616 | return 1; | ||
617 | } | ||
618 | - tmp = tcg_const_i32(rd); | ||
619 | - tmp2 = tcg_const_i32(rm); | ||
620 | + ptr1 = vfp_reg_ptr(true, rd); | ||
621 | + ptr2 = vfp_reg_ptr(true, rm); | ||
622 | if (q) { | ||
623 | - gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2); | ||
624 | + gen_helper_crypto_sha256su0(ptr1, ptr2); | ||
625 | } else { | ||
626 | - gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2); | ||
627 | + gen_helper_crypto_sha1su1(ptr1, ptr2); | ||
628 | } | ||
629 | - tcg_temp_free_i32(tmp); | ||
630 | - tcg_temp_free_i32(tmp2); | ||
631 | + tcg_temp_free_ptr(ptr1); | ||
632 | + tcg_temp_free_ptr(ptr2); | ||
633 | break; | ||
634 | default: | ||
635 | elementwise: | ||
636 | -- | 185 | -- |
637 | 2.7.4 | 186 | 2.19.2 |
638 | 187 | ||
639 | 188 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | The gdb_get_cpu_pid() function does the PID lookup for the given CPU. It | ||
4 | checks if the CPU is a direct child of a CPU cluster. If it is, the | ||
5 | returned PID is the cluster ID plus one (cluster IDs start at 0, GDB | ||
6 | PIDs at 1). When the CPU is not a child of such a container, the PID of | ||
7 | the default process is returned. | ||
8 | |||
9 | The gdb_fmt_thread_id() function generates the string to be used to identify | ||
10 | a given thread, in a response packet for the peer. This function | ||
11 | supports generating thread IDs when multiprocess mode is enabled (in the | ||
12 | form `p<pid>.<tid>'). | ||
13 | |||
14 | Use them in the reply to a '?' request. | ||
15 | |||
16 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
17 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
18 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
19 | Message-id: 20181207090135.7651-4-luc.michel@greensocs.com | ||
20 | [PMM: fixed checkpatch blockquote style nit] | ||
21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
22 | --- | ||
23 | gdbstub.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- | ||
24 | 1 file changed, 64 insertions(+), 2 deletions(-) | ||
25 | |||
26 | diff --git a/gdbstub.c b/gdbstub.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/gdbstub.c | ||
29 | +++ b/gdbstub.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static int memtox(char *buf, const char *mem, int len) | ||
31 | return p - buf; | ||
32 | } | ||
33 | |||
34 | +static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu) | ||
35 | +{ | ||
36 | +#ifndef CONFIG_USER_ONLY | ||
37 | + gchar *path, *name = NULL; | ||
38 | + Object *obj; | ||
39 | + CPUClusterState *cluster; | ||
40 | + uint32_t ret; | ||
41 | + | ||
42 | + path = object_get_canonical_path(OBJECT(cpu)); | ||
43 | + | ||
44 | + if (path == NULL) { | ||
45 | + /* Return the default process' PID */ | ||
46 | + ret = s->processes[s->process_num - 1].pid; | ||
47 | + goto out; | ||
48 | + } | ||
49 | + | ||
50 | + name = object_get_canonical_path_component(OBJECT(cpu)); | ||
51 | + assert(name != NULL); | ||
52 | + | ||
53 | + /* | ||
54 | + * Retrieve the CPU parent path by removing the last '/' and the CPU name | ||
55 | + * from the CPU canonical path. | ||
56 | + */ | ||
57 | + path[strlen(path) - strlen(name) - 1] = '\0'; | ||
58 | + | ||
59 | + obj = object_resolve_path_type(path, TYPE_CPU_CLUSTER, NULL); | ||
60 | + | ||
61 | + if (obj == NULL) { | ||
62 | + /* Return the default process' PID */ | ||
63 | + ret = s->processes[s->process_num - 1].pid; | ||
64 | + goto out; | ||
65 | + } | ||
66 | + | ||
67 | + cluster = CPU_CLUSTER(obj); | ||
68 | + ret = cluster->cluster_id + 1; | ||
69 | + | ||
70 | +out: | ||
71 | + g_free(name); | ||
72 | + g_free(path); | ||
73 | + | ||
74 | + return ret; | ||
75 | + | ||
76 | +#else | ||
77 | + /* TODO: In user mode, we should use the task state PID */ | ||
78 | + return s->processes[s->process_num - 1].pid; | ||
79 | +#endif | ||
80 | +} | ||
81 | + | ||
82 | static const char *get_feature_xml(const char *p, const char **newp, | ||
83 | CPUClass *cc) | ||
84 | { | ||
85 | @@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id) | ||
86 | return NULL; | ||
87 | } | ||
88 | |||
89 | +static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu, | ||
90 | + char *buf, size_t buf_size) | ||
91 | +{ | ||
92 | + if (s->multiprocess) { | ||
93 | + snprintf(buf, buf_size, "p%02x.%02x", | ||
94 | + gdb_get_cpu_pid(s, cpu), cpu_gdb_index(cpu)); | ||
95 | + } else { | ||
96 | + snprintf(buf, buf_size, "%02x", cpu_gdb_index(cpu)); | ||
97 | + } | ||
98 | + | ||
99 | + return buf; | ||
100 | +} | ||
101 | + | ||
102 | static int is_query_packet(const char *p, const char *query, char separator) | ||
103 | { | ||
104 | unsigned int query_len = strlen(query); | ||
105 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
106 | int ch, reg_size, type, res; | ||
107 | uint8_t mem_buf[MAX_PACKET_LENGTH]; | ||
108 | char buf[sizeof(mem_buf) + 1 /* trailing NUL */]; | ||
109 | + char thread_id[16]; | ||
110 | uint8_t *registers; | ||
111 | target_ulong addr, len; | ||
112 | |||
113 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
114 | switch(ch) { | ||
115 | case '?': | ||
116 | /* TODO: Make this return the correct value for user-mode. */ | ||
117 | - snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP, | ||
118 | - cpu_gdb_index(s->c_cpu)); | ||
119 | + snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP, | ||
120 | + gdb_fmt_thread_id(s, s->c_cpu, thread_id, sizeof(thread_id))); | ||
121 | put_packet(s, buf); | ||
122 | /* Remove all the breakpoints when this query is issued, | ||
123 | * because gdb is doing and initial connect and the state | ||
124 | -- | ||
125 | 2.19.2 | ||
126 | |||
127 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Luc Michel <luc.michel@greensocs.com> | |
2 | |||
3 | Add a couple of helper functions to cope with GDB threads and processes. | ||
4 | |||
5 | The gdb_get_process() function looks for a process given a pid. | ||
6 | |||
7 | The gdb_get_cpu() function returns the CPU corresponding to the (pid, | ||
8 | tid) pair given as parameters. | ||
9 | |||
10 | The read_thread_id() function parses the thread-id sent by the peer. | ||
11 | This function supports the multiprocess extension thread-id syntax. The | ||
12 | return value specifies if the parsing failed, or if a special case was | ||
13 | encountered (all processes or all threads). | ||
14 | |||
15 | Use them in 'H' and 'T' packets handling to support the multiprocess | ||
16 | extension. | ||
17 | |||
18 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
19 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
20 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
21 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
22 | Message-id: 20181207090135.7651-5-luc.michel@greensocs.com | ||
23 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
24 | --- | ||
25 | gdbstub.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++------- | ||
26 | 1 file changed, 136 insertions(+), 18 deletions(-) | ||
27 | |||
28 | diff --git a/gdbstub.c b/gdbstub.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/gdbstub.c | ||
31 | +++ b/gdbstub.c | ||
32 | @@ -XXX,XX +XXX,XX @@ out: | ||
33 | #endif | ||
34 | } | ||
35 | |||
36 | +static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid) | ||
37 | +{ | ||
38 | + int i; | ||
39 | + | ||
40 | + if (!pid) { | ||
41 | + /* 0 means any process, we take the first one */ | ||
42 | + return &s->processes[0]; | ||
43 | + } | ||
44 | + | ||
45 | + for (i = 0; i < s->process_num; i++) { | ||
46 | + if (s->processes[i].pid == pid) { | ||
47 | + return &s->processes[i]; | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
51 | + return NULL; | ||
52 | +} | ||
53 | + | ||
54 | +static GDBProcess *gdb_get_cpu_process(const GDBState *s, CPUState *cpu) | ||
55 | +{ | ||
56 | + return gdb_get_process(s, gdb_get_cpu_pid(s, cpu)); | ||
57 | +} | ||
58 | + | ||
59 | +static CPUState *find_cpu(uint32_t thread_id) | ||
60 | +{ | ||
61 | + CPUState *cpu; | ||
62 | + | ||
63 | + CPU_FOREACH(cpu) { | ||
64 | + if (cpu_gdb_index(cpu) == thread_id) { | ||
65 | + return cpu; | ||
66 | + } | ||
67 | + } | ||
68 | + | ||
69 | + return NULL; | ||
70 | +} | ||
71 | + | ||
72 | +static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid) | ||
73 | +{ | ||
74 | + GDBProcess *process; | ||
75 | + CPUState *cpu; | ||
76 | + | ||
77 | + if (!tid) { | ||
78 | + /* 0 means any thread, we take the first one */ | ||
79 | + tid = 1; | ||
80 | + } | ||
81 | + | ||
82 | + cpu = find_cpu(tid); | ||
83 | + | ||
84 | + if (cpu == NULL) { | ||
85 | + return NULL; | ||
86 | + } | ||
87 | + | ||
88 | + process = gdb_get_cpu_process(s, cpu); | ||
89 | + | ||
90 | + if (process->pid != pid) { | ||
91 | + return NULL; | ||
92 | + } | ||
93 | + | ||
94 | + if (!process->attached) { | ||
95 | + return NULL; | ||
96 | + } | ||
97 | + | ||
98 | + return cpu; | ||
99 | +} | ||
100 | + | ||
101 | static const char *get_feature_xml(const char *p, const char **newp, | ||
102 | CPUClass *cc) | ||
103 | { | ||
104 | @@ -XXX,XX +XXX,XX @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) | ||
105 | cpu_set_pc(cpu, pc); | ||
106 | } | ||
107 | |||
108 | -static CPUState *find_cpu(uint32_t thread_id) | ||
109 | -{ | ||
110 | - CPUState *cpu; | ||
111 | - | ||
112 | - CPU_FOREACH(cpu) { | ||
113 | - if (cpu_gdb_index(cpu) == thread_id) { | ||
114 | - return cpu; | ||
115 | - } | ||
116 | - } | ||
117 | - | ||
118 | - return NULL; | ||
119 | -} | ||
120 | - | ||
121 | static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu, | ||
122 | char *buf, size_t buf_size) | ||
123 | { | ||
124 | @@ -XXX,XX +XXX,XX @@ static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu, | ||
125 | return buf; | ||
126 | } | ||
127 | |||
128 | +typedef enum GDBThreadIdKind { | ||
129 | + GDB_ONE_THREAD = 0, | ||
130 | + GDB_ALL_THREADS, /* One process, all threads */ | ||
131 | + GDB_ALL_PROCESSES, | ||
132 | + GDB_READ_THREAD_ERR | ||
133 | +} GDBThreadIdKind; | ||
134 | + | ||
135 | +static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf, | ||
136 | + uint32_t *pid, uint32_t *tid) | ||
137 | +{ | ||
138 | + unsigned long p, t; | ||
139 | + int ret; | ||
140 | + | ||
141 | + if (*buf == 'p') { | ||
142 | + buf++; | ||
143 | + ret = qemu_strtoul(buf, &buf, 16, &p); | ||
144 | + | ||
145 | + if (ret) { | ||
146 | + return GDB_READ_THREAD_ERR; | ||
147 | + } | ||
148 | + | ||
149 | + /* Skip '.' */ | ||
150 | + buf++; | ||
151 | + } else { | ||
152 | + p = 1; | ||
153 | + } | ||
154 | + | ||
155 | + ret = qemu_strtoul(buf, &buf, 16, &t); | ||
156 | + | ||
157 | + if (ret) { | ||
158 | + return GDB_READ_THREAD_ERR; | ||
159 | + } | ||
160 | + | ||
161 | + *end_buf = buf; | ||
162 | + | ||
163 | + if (p == -1) { | ||
164 | + return GDB_ALL_PROCESSES; | ||
165 | + } | ||
166 | + | ||
167 | + if (pid) { | ||
168 | + *pid = p; | ||
169 | + } | ||
170 | + | ||
171 | + if (t == -1) { | ||
172 | + return GDB_ALL_THREADS; | ||
173 | + } | ||
174 | + | ||
175 | + if (tid) { | ||
176 | + *tid = t; | ||
177 | + } | ||
178 | + | ||
179 | + return GDB_ONE_THREAD; | ||
180 | +} | ||
181 | + | ||
182 | static int is_query_packet(const char *p, const char *query, char separator) | ||
183 | { | ||
184 | unsigned int query_len = strlen(query); | ||
185 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
186 | CPUClass *cc; | ||
187 | const char *p; | ||
188 | uint32_t thread; | ||
189 | + uint32_t pid, tid; | ||
190 | int ch, reg_size, type, res; | ||
191 | uint8_t mem_buf[MAX_PACKET_LENGTH]; | ||
192 | char buf[sizeof(mem_buf) + 1 /* trailing NUL */]; | ||
193 | char thread_id[16]; | ||
194 | uint8_t *registers; | ||
195 | target_ulong addr, len; | ||
196 | + GDBThreadIdKind thread_kind; | ||
197 | |||
198 | trace_gdbstub_io_command(line_buf); | ||
199 | |||
200 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
201 | break; | ||
202 | case 'H': | ||
203 | type = *p++; | ||
204 | - thread = strtoull(p, (char **)&p, 16); | ||
205 | - if (thread == -1 || thread == 0) { | ||
206 | + | ||
207 | + thread_kind = read_thread_id(p, &p, &pid, &tid); | ||
208 | + if (thread_kind == GDB_READ_THREAD_ERR) { | ||
209 | + put_packet(s, "E22"); | ||
210 | + break; | ||
211 | + } | ||
212 | + | ||
213 | + if (thread_kind != GDB_ONE_THREAD) { | ||
214 | put_packet(s, "OK"); | ||
215 | break; | ||
216 | } | ||
217 | - cpu = find_cpu(thread); | ||
218 | + cpu = gdb_get_cpu(s, pid, tid); | ||
219 | if (cpu == NULL) { | ||
220 | put_packet(s, "E22"); | ||
221 | break; | ||
222 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
223 | } | ||
224 | break; | ||
225 | case 'T': | ||
226 | - thread = strtoull(p, (char **)&p, 16); | ||
227 | - cpu = find_cpu(thread); | ||
228 | + thread_kind = read_thread_id(p, &p, &pid, &tid); | ||
229 | + if (thread_kind == GDB_READ_THREAD_ERR) { | ||
230 | + put_packet(s, "E22"); | ||
231 | + break; | ||
232 | + } | ||
233 | + cpu = gdb_get_cpu(s, pid, tid); | ||
234 | |||
235 | if (cpu != NULL) { | ||
236 | put_packet(s, "OK"); | ||
237 | -- | ||
238 | 2.19.2 | ||
239 | |||
240 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Luc Michel <luc.michel@greensocs.com> |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Add the gdb_first_attached_cpu() and gdb_next_attached_cpu() to iterate |
4 | Message-id: 20180119045438.28582-14-richard.henderson@linaro.org | 4 | over all the CPUs in currently attached processes. |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 5 | |
6 | Add the gdb_first_cpu_in_process() and gdb_next_cpu_in_process() to | ||
7 | iterate over CPUs of a given process. | ||
8 | |||
9 | Use them to add multiprocess extension support to vCont packets. | ||
10 | |||
11 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
14 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
15 | Message-id: 20181207090135.7651-6-luc.michel@greensocs.com | ||
16 | [PMM: corrected checkpatch comment style nit] | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
7 | --- | 18 | --- |
8 | target/arm/cpu.h | 127 +--------------------------------------------------- | 19 | gdbstub.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++------- |
9 | target/arm/helper.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ | 20 | 1 file changed, 100 insertions(+), 15 deletions(-) |
10 | 2 files changed, 128 insertions(+), 125 deletions(-) | ||
11 | 21 | ||
12 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 22 | diff --git a/gdbstub.c b/gdbstub.c |
13 | index XXXXXXX..XXXXXXX 100644 | 23 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/target/arm/cpu.h | 24 | --- a/gdbstub.c |
15 | +++ b/target/arm/cpu.h | 25 | +++ b/gdbstub.c |
16 | @@ -XXX,XX +XXX,XX @@ static inline bool bswap_code(bool sctlr_b) | 26 | @@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id) |
17 | #endif | 27 | return NULL; |
18 | } | 28 | } |
19 | 29 | ||
20 | -/* Return the exception level to which FP-disabled exceptions should | 30 | +static CPUState *get_first_cpu_in_process(const GDBState *s, |
21 | - * be taken, or 0 if FP is enabled. | 31 | + GDBProcess *process) |
22 | - */ | 32 | +{ |
23 | -static inline int fp_exception_el(CPUARMState *env) | 33 | + CPUState *cpu; |
24 | -{ | ||
25 | - int fpen; | ||
26 | - int cur_el = arm_current_el(env); | ||
27 | - | ||
28 | - /* CPACR and the CPTR registers don't exist before v6, so FP is | ||
29 | - * always accessible | ||
30 | - */ | ||
31 | - if (!arm_feature(env, ARM_FEATURE_V6)) { | ||
32 | - return 0; | ||
33 | - } | ||
34 | - | ||
35 | - /* The CPACR controls traps to EL1, or PL1 if we're 32 bit: | ||
36 | - * 0, 2 : trap EL0 and EL1/PL1 accesses | ||
37 | - * 1 : trap only EL0 accesses | ||
38 | - * 3 : trap no accesses | ||
39 | - */ | ||
40 | - fpen = extract32(env->cp15.cpacr_el1, 20, 2); | ||
41 | - switch (fpen) { | ||
42 | - case 0: | ||
43 | - case 2: | ||
44 | - if (cur_el == 0 || cur_el == 1) { | ||
45 | - /* Trap to PL1, which might be EL1 or EL3 */ | ||
46 | - if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) { | ||
47 | - return 3; | ||
48 | - } | ||
49 | - return 1; | ||
50 | - } | ||
51 | - if (cur_el == 3 && !is_a64(env)) { | ||
52 | - /* Secure PL1 running at EL3 */ | ||
53 | - return 3; | ||
54 | - } | ||
55 | - break; | ||
56 | - case 1: | ||
57 | - if (cur_el == 0) { | ||
58 | - return 1; | ||
59 | - } | ||
60 | - break; | ||
61 | - case 3: | ||
62 | - break; | ||
63 | - } | ||
64 | - | ||
65 | - /* For the CPTR registers we don't need to guard with an ARM_FEATURE | ||
66 | - * check because zero bits in the registers mean "don't trap". | ||
67 | - */ | ||
68 | - | ||
69 | - /* CPTR_EL2 : present in v7VE or v8 */ | ||
70 | - if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1) | ||
71 | - && !arm_is_secure_below_el3(env)) { | ||
72 | - /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */ | ||
73 | - return 2; | ||
74 | - } | ||
75 | - | ||
76 | - /* CPTR_EL3 : present in v8 */ | ||
77 | - if (extract32(env->cp15.cptr_el[3], 10, 1)) { | ||
78 | - /* Trap all FP ops to EL3 */ | ||
79 | - return 3; | ||
80 | - } | ||
81 | - | ||
82 | - return 0; | ||
83 | -} | ||
84 | - | ||
85 | #ifdef CONFIG_USER_ONLY | ||
86 | static inline bool arm_cpu_bswap_data(CPUARMState *env) | ||
87 | { | ||
88 | @@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx) | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | -static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | ||
93 | - target_ulong *cs_base, uint32_t *flags) | ||
94 | -{ | ||
95 | - ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false)); | ||
96 | - if (is_a64(env)) { | ||
97 | - *pc = env->pc; | ||
98 | - *flags = ARM_TBFLAG_AARCH64_STATE_MASK; | ||
99 | - /* Get control bits for tagged addresses */ | ||
100 | - *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); | ||
101 | - *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); | ||
102 | - } else { | ||
103 | - *pc = env->regs[15]; | ||
104 | - *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | ||
105 | - | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) | ||
106 | - | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) | ||
107 | - | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) | ||
108 | - | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT); | ||
109 | - if (!(access_secure_reg(env))) { | ||
110 | - *flags |= ARM_TBFLAG_NS_MASK; | ||
111 | - } | ||
112 | - if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) | ||
113 | - || arm_el_is_aa64(env, 1)) { | ||
114 | - *flags |= ARM_TBFLAG_VFPEN_MASK; | ||
115 | - } | ||
116 | - *flags |= (extract32(env->cp15.c15_cpar, 0, 2) | ||
117 | - << ARM_TBFLAG_XSCALE_CPAR_SHIFT); | ||
118 | - } | ||
119 | - | ||
120 | - *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT); | ||
121 | - | ||
122 | - /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine | ||
123 | - * states defined in the ARM ARM for software singlestep: | ||
124 | - * SS_ACTIVE PSTATE.SS State | ||
125 | - * 0 x Inactive (the TB flag for SS is always 0) | ||
126 | - * 1 0 Active-pending | ||
127 | - * 1 1 Active-not-pending | ||
128 | - */ | ||
129 | - if (arm_singlestep_active(env)) { | ||
130 | - *flags |= ARM_TBFLAG_SS_ACTIVE_MASK; | ||
131 | - if (is_a64(env)) { | ||
132 | - if (env->pstate & PSTATE_SS) { | ||
133 | - *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | ||
134 | - } | ||
135 | - } else { | ||
136 | - if (env->uncached_cpsr & PSTATE_SS) { | ||
137 | - *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | ||
138 | - } | ||
139 | - } | ||
140 | - } | ||
141 | - if (arm_cpu_data_is_big_endian(env)) { | ||
142 | - *flags |= ARM_TBFLAG_BE_DATA_MASK; | ||
143 | - } | ||
144 | - *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT; | ||
145 | - | ||
146 | - if (arm_v7m_is_handler_mode(env)) { | ||
147 | - *flags |= ARM_TBFLAG_HANDLER_MASK; | ||
148 | - } | ||
149 | - | ||
150 | - *cs_base = 0; | ||
151 | -} | ||
152 | +void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | ||
153 | + target_ulong *cs_base, uint32_t *flags); | ||
154 | |||
155 | enum { | ||
156 | QEMU_PSCI_CONDUIT_DISABLED = 0, | ||
157 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
158 | index XXXXXXX..XXXXXXX 100644 | ||
159 | --- a/target/arm/helper.c | ||
160 | +++ b/target/arm/helper.c | ||
161 | @@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes) | ||
162 | /* Linux crc32c converts the output to one's complement. */ | ||
163 | return crc32c(acc, buf, bytes) ^ 0xffffffff; | ||
164 | } | ||
165 | + | 34 | + |
166 | +/* Return the exception level to which FP-disabled exceptions should | 35 | + CPU_FOREACH(cpu) { |
167 | + * be taken, or 0 if FP is enabled. | 36 | + if (gdb_get_cpu_pid(s, cpu) == process->pid) { |
168 | + */ | 37 | + return cpu; |
169 | +static inline int fp_exception_el(CPUARMState *env) | 38 | + } |
170 | +{ | ||
171 | + int fpen; | ||
172 | + int cur_el = arm_current_el(env); | ||
173 | + | ||
174 | + /* CPACR and the CPTR registers don't exist before v6, so FP is | ||
175 | + * always accessible | ||
176 | + */ | ||
177 | + if (!arm_feature(env, ARM_FEATURE_V6)) { | ||
178 | + return 0; | ||
179 | + } | 39 | + } |
180 | + | 40 | + |
181 | + /* The CPACR controls traps to EL1, or PL1 if we're 32 bit: | 41 | + return NULL; |
182 | + * 0, 2 : trap EL0 and EL1/PL1 accesses | 42 | +} |
183 | + * 1 : trap only EL0 accesses | 43 | + |
184 | + * 3 : trap no accesses | 44 | +static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu) |
185 | + */ | 45 | +{ |
186 | + fpen = extract32(env->cp15.cpacr_el1, 20, 2); | 46 | + uint32_t pid = gdb_get_cpu_pid(s, cpu); |
187 | + switch (fpen) { | 47 | + cpu = CPU_NEXT(cpu); |
188 | + case 0: | 48 | + |
189 | + case 2: | 49 | + while (cpu) { |
190 | + if (cur_el == 0 || cur_el == 1) { | 50 | + if (gdb_get_cpu_pid(s, cpu) == pid) { |
191 | + /* Trap to PL1, which might be EL1 or EL3 */ | 51 | + break; |
192 | + if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) { | ||
193 | + return 3; | ||
194 | + } | ||
195 | + return 1; | ||
196 | + } | 52 | + } |
197 | + if (cur_el == 3 && !is_a64(env)) { | 53 | + |
198 | + /* Secure PL1 running at EL3 */ | 54 | + cpu = CPU_NEXT(cpu); |
199 | + return 3; | ||
200 | + } | ||
201 | + break; | ||
202 | + case 1: | ||
203 | + if (cur_el == 0) { | ||
204 | + return 1; | ||
205 | + } | ||
206 | + break; | ||
207 | + case 3: | ||
208 | + break; | ||
209 | + } | 55 | + } |
210 | + | 56 | + |
211 | + /* For the CPTR registers we don't need to guard with an ARM_FEATURE | 57 | + return cpu; |
212 | + * check because zero bits in the registers mean "don't trap". | 58 | +} |
213 | + */ | ||
214 | + | 59 | + |
215 | + /* CPTR_EL2 : present in v7VE or v8 */ | 60 | static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid) |
216 | + if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1) | 61 | { |
217 | + && !arm_is_secure_below_el3(env)) { | 62 | GDBProcess *process; |
218 | + /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */ | 63 | @@ -XXX,XX +XXX,XX @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid) |
219 | + return 2; | 64 | return cpu; |
65 | } | ||
66 | |||
67 | +/* Return the cpu following @cpu, while ignoring unattached processes. */ | ||
68 | +static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu) | ||
69 | +{ | ||
70 | + cpu = CPU_NEXT(cpu); | ||
71 | + | ||
72 | + while (cpu) { | ||
73 | + if (gdb_get_cpu_process(s, cpu)->attached) { | ||
74 | + break; | ||
75 | + } | ||
76 | + | ||
77 | + cpu = CPU_NEXT(cpu); | ||
220 | + } | 78 | + } |
221 | + | 79 | + |
222 | + /* CPTR_EL3 : present in v8 */ | 80 | + return cpu; |
223 | + if (extract32(env->cp15.cptr_el[3], 10, 1)) { | 81 | +} |
224 | + /* Trap all FP ops to EL3 */ | 82 | + |
225 | + return 3; | 83 | +/* Return the first attached cpu */ |
84 | +static CPUState *gdb_first_attached_cpu(const GDBState *s) | ||
85 | +{ | ||
86 | + CPUState *cpu = first_cpu; | ||
87 | + GDBProcess *process = gdb_get_cpu_process(s, cpu); | ||
88 | + | ||
89 | + if (!process->attached) { | ||
90 | + return gdb_next_attached_cpu(s, cpu); | ||
226 | + } | 91 | + } |
227 | + | 92 | + |
228 | + return 0; | 93 | + return cpu; |
229 | +} | 94 | +} |
230 | + | 95 | + |
231 | +void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, | 96 | static const char *get_feature_xml(const char *p, const char **newp, |
232 | + target_ulong *cs_base, uint32_t *flags) | 97 | CPUClass *cc) |
233 | +{ | 98 | { |
234 | + ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false)); | 99 | @@ -XXX,XX +XXX,XX @@ static int is_query_packet(const char *p, const char *query, char separator) |
235 | + if (is_a64(env)) { | 100 | */ |
236 | + *pc = env->pc; | 101 | static int gdb_handle_vcont(GDBState *s, const char *p) |
237 | + *flags = ARM_TBFLAG_AARCH64_STATE_MASK; | 102 | { |
238 | + /* Get control bits for tagged addresses */ | 103 | - int res, idx, signal = 0; |
239 | + *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); | 104 | + int res, signal = 0; |
240 | + *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); | 105 | char cur_action; |
241 | + } else { | 106 | char *newstates; |
242 | + *pc = env->regs[15]; | 107 | unsigned long tmp; |
243 | + *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | 108 | + uint32_t pid, tid; |
244 | + | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) | 109 | + GDBProcess *process; |
245 | + | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) | 110 | CPUState *cpu; |
246 | + | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) | 111 | #ifdef CONFIG_USER_ONLY |
247 | + | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT); | 112 | int max_cpus = 1; /* global variable max_cpus exists only in system mode */ |
248 | + if (!(access_secure_reg(env))) { | 113 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_vcont(GDBState *s, const char *p) |
249 | + *flags |= ARM_TBFLAG_NS_MASK; | 114 | res = -ENOTSUP; |
115 | goto out; | ||
116 | } | ||
117 | - /* thread specification. special values: (none), -1 = all; 0 = any */ | ||
118 | - if ((p[0] == ':' && p[1] == '-' && p[2] == '1') || (p[0] != ':')) { | ||
119 | - if (*p == ':') { | ||
120 | - p += 3; | ||
121 | - } | ||
122 | - for (idx = 0; idx < max_cpus; idx++) { | ||
123 | - if (newstates[idx] == 1) { | ||
124 | - newstates[idx] = cur_action; | ||
125 | + | ||
126 | + if (*p++ != ':') { | ||
127 | + res = -ENOTSUP; | ||
128 | + goto out; | ||
250 | + } | 129 | + } |
251 | + if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30) | ||
252 | + || arm_el_is_aa64(env, 1)) { | ||
253 | + *flags |= ARM_TBFLAG_VFPEN_MASK; | ||
254 | + } | ||
255 | + *flags |= (extract32(env->cp15.c15_cpar, 0, 2) | ||
256 | + << ARM_TBFLAG_XSCALE_CPAR_SHIFT); | ||
257 | + } | ||
258 | + | 130 | + |
259 | + *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT); | 131 | + switch (read_thread_id(p, &p, &pid, &tid)) { |
132 | + case GDB_READ_THREAD_ERR: | ||
133 | + res = -EINVAL; | ||
134 | + goto out; | ||
260 | + | 135 | + |
261 | + /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine | 136 | + case GDB_ALL_PROCESSES: |
262 | + * states defined in the ARM ARM for software singlestep: | 137 | + cpu = gdb_first_attached_cpu(s); |
263 | + * SS_ACTIVE PSTATE.SS State | 138 | + while (cpu) { |
264 | + * 0 x Inactive (the TB flag for SS is always 0) | 139 | + if (newstates[cpu->cpu_index] == 1) { |
265 | + * 1 0 Active-pending | 140 | + newstates[cpu->cpu_index] = cur_action; |
266 | + * 1 1 Active-not-pending | 141 | } |
267 | + */ | 142 | + |
268 | + if (arm_singlestep_active(env)) { | 143 | + cpu = gdb_next_attached_cpu(s, cpu); |
269 | + *flags |= ARM_TBFLAG_SS_ACTIVE_MASK; | 144 | } |
270 | + if (is_a64(env)) { | 145 | - } else if (*p == ':') { |
271 | + if (env->pstate & PSTATE_SS) { | 146 | - p++; |
272 | + *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | 147 | - res = qemu_strtoul(p, &p, 16, &tmp); |
148 | - if (res) { | ||
149 | + break; | ||
150 | + | ||
151 | + case GDB_ALL_THREADS: | ||
152 | + process = gdb_get_process(s, pid); | ||
153 | + | ||
154 | + if (!process->attached) { | ||
155 | + res = -EINVAL; | ||
156 | goto out; | ||
157 | } | ||
158 | |||
159 | - /* 0 means any thread, so we pick the first valid CPU */ | ||
160 | - cpu = tmp ? find_cpu(tmp) : first_cpu; | ||
161 | + cpu = get_first_cpu_in_process(s, process); | ||
162 | + while (cpu) { | ||
163 | + if (newstates[cpu->cpu_index] == 1) { | ||
164 | + newstates[cpu->cpu_index] = cur_action; | ||
165 | + } | ||
166 | + | ||
167 | + cpu = gdb_next_cpu_in_process(s, cpu); | ||
273 | + } | 168 | + } |
274 | + } else { | 169 | + break; |
275 | + if (env->uncached_cpsr & PSTATE_SS) { | ||
276 | + *flags |= ARM_TBFLAG_PSTATE_SS_MASK; | ||
277 | + } | ||
278 | + } | ||
279 | + } | ||
280 | + if (arm_cpu_data_is_big_endian(env)) { | ||
281 | + *flags |= ARM_TBFLAG_BE_DATA_MASK; | ||
282 | + } | ||
283 | + *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT; | ||
284 | + | 170 | + |
285 | + if (arm_v7m_is_handler_mode(env)) { | 171 | + case GDB_ONE_THREAD: |
286 | + *flags |= ARM_TBFLAG_HANDLER_MASK; | 172 | + cpu = gdb_get_cpu(s, pid, tid); |
287 | + } | 173 | |
288 | + | 174 | /* invalid CPU/thread specified */ |
289 | + *cs_base = 0; | 175 | if (!cpu) { |
290 | +} | 176 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_vcont(GDBState *s, const char *p) |
177 | if (newstates[cpu->cpu_index] == 1) { | ||
178 | newstates[cpu->cpu_index] = cur_action; | ||
179 | } | ||
180 | + break; | ||
181 | } | ||
182 | } | ||
183 | s->signal = signal; | ||
291 | -- | 184 | -- |
292 | 2.7.4 | 185 | 2.19.2 |
293 | 186 | ||
294 | 187 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Change the sC packet handling to support the multiprocess extension. | ||
4 | Instead of returning the first thread, we return the first thread of the | ||
5 | current process. | ||
6 | |||
7 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
11 | Message-id: 20181207090135.7651-7-luc.michel@greensocs.com | ||
12 | [PMM: corrected checkpatch comment style nit] | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | --- | ||
15 | gdbstub.c | 12 +++++++++--- | ||
16 | 1 file changed, 9 insertions(+), 3 deletions(-) | ||
17 | |||
18 | diff --git a/gdbstub.c b/gdbstub.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/gdbstub.c | ||
21 | +++ b/gdbstub.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
23 | put_packet(s, "OK"); | ||
24 | break; | ||
25 | } else if (strcmp(p,"C") == 0) { | ||
26 | - /* "Current thread" remains vague in the spec, so always return | ||
27 | - * the first CPU (gdb returns the first thread). */ | ||
28 | - put_packet(s, "QC1"); | ||
29 | + /* | ||
30 | + * "Current thread" remains vague in the spec, so always return | ||
31 | + * the first thread of the current process (gdb returns the | ||
32 | + * first thread). | ||
33 | + */ | ||
34 | + cpu = get_first_cpu_in_process(s, gdb_get_cpu_process(s, s->g_cpu)); | ||
35 | + snprintf(buf, sizeof(buf), "QC%s", | ||
36 | + gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id))); | ||
37 | + put_packet(s, buf); | ||
38 | break; | ||
39 | } else if (strcmp(p,"fThreadInfo") == 0) { | ||
40 | s->query_cpu = first_cpu; | ||
41 | -- | ||
42 | 2.19.2 | ||
43 | |||
44 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Change the thread info related packets handling to support multiprocess | ||
4 | extension. | ||
5 | |||
6 | Add the CPUs class name in the extra info to help differentiate | ||
7 | them in multiprocess mode. | ||
8 | |||
9 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
11 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
12 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
13 | Message-id: 20181207090135.7651-8-luc.michel@greensocs.com | ||
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
15 | --- | ||
16 | gdbstub.c | 37 +++++++++++++++++++++++++++---------- | ||
17 | 1 file changed, 27 insertions(+), 10 deletions(-) | ||
18 | |||
19 | diff --git a/gdbstub.c b/gdbstub.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/gdbstub.c | ||
22 | +++ b/gdbstub.c | ||
23 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
24 | CPUState *cpu; | ||
25 | CPUClass *cc; | ||
26 | const char *p; | ||
27 | - uint32_t thread; | ||
28 | uint32_t pid, tid; | ||
29 | int ch, reg_size, type, res; | ||
30 | uint8_t mem_buf[MAX_PACKET_LENGTH]; | ||
31 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
32 | put_packet(s, buf); | ||
33 | break; | ||
34 | } else if (strcmp(p,"fThreadInfo") == 0) { | ||
35 | - s->query_cpu = first_cpu; | ||
36 | + s->query_cpu = gdb_first_attached_cpu(s); | ||
37 | goto report_cpuinfo; | ||
38 | } else if (strcmp(p,"sThreadInfo") == 0) { | ||
39 | report_cpuinfo: | ||
40 | if (s->query_cpu) { | ||
41 | - snprintf(buf, sizeof(buf), "m%x", cpu_gdb_index(s->query_cpu)); | ||
42 | + snprintf(buf, sizeof(buf), "m%s", | ||
43 | + gdb_fmt_thread_id(s, s->query_cpu, | ||
44 | + thread_id, sizeof(thread_id))); | ||
45 | put_packet(s, buf); | ||
46 | - s->query_cpu = CPU_NEXT(s->query_cpu); | ||
47 | + s->query_cpu = gdb_next_attached_cpu(s, s->query_cpu); | ||
48 | } else | ||
49 | put_packet(s, "l"); | ||
50 | break; | ||
51 | } else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) { | ||
52 | - thread = strtoull(p+16, (char **)&p, 16); | ||
53 | - cpu = find_cpu(thread); | ||
54 | + if (read_thread_id(p + 16, &p, &pid, &tid) == GDB_READ_THREAD_ERR) { | ||
55 | + put_packet(s, "E22"); | ||
56 | + break; | ||
57 | + } | ||
58 | + cpu = gdb_get_cpu(s, pid, tid); | ||
59 | if (cpu != NULL) { | ||
60 | cpu_synchronize_state(cpu); | ||
61 | - /* memtohex() doubles the required space */ | ||
62 | - len = snprintf((char *)mem_buf, sizeof(buf) / 2, | ||
63 | - "CPU#%d [%s]", cpu->cpu_index, | ||
64 | - cpu->halted ? "halted " : "running"); | ||
65 | + | ||
66 | + if (s->multiprocess && (s->process_num > 1)) { | ||
67 | + /* Print the CPU model and name in multiprocess mode */ | ||
68 | + ObjectClass *oc = object_get_class(OBJECT(cpu)); | ||
69 | + const char *cpu_model = object_class_get_name(oc); | ||
70 | + char *cpu_name = | ||
71 | + object_get_canonical_path_component(OBJECT(cpu)); | ||
72 | + len = snprintf((char *)mem_buf, sizeof(buf) / 2, | ||
73 | + "%s %s [%s]", cpu_model, cpu_name, | ||
74 | + cpu->halted ? "halted " : "running"); | ||
75 | + g_free(cpu_name); | ||
76 | + } else { | ||
77 | + /* memtohex() doubles the required space */ | ||
78 | + len = snprintf((char *)mem_buf, sizeof(buf) / 2, | ||
79 | + "CPU#%d [%s]", cpu->cpu_index, | ||
80 | + cpu->halted ? "halted " : "running"); | ||
81 | + } | ||
82 | trace_gdbstub_op_extra_info((char *)mem_buf); | ||
83 | memtohex(buf, mem_buf, len); | ||
84 | put_packet(s, buf); | ||
85 | -- | ||
86 | 2.19.2 | ||
87 | |||
88 | diff view generated by jsdifflib |
1 | From: Luc MICHEL <luc.michel@git.antfield.fr> | 1 | From: Luc Michel <luc.michel@greensocs.com> |
---|---|---|---|
2 | 2 | ||
3 | When determining the group priority of a group 1 IRQ, if C_CTRL.CBPR is | 3 | Change the Xfer:features:read: packet handling to support the |
4 | 0, the non-secure BPR value is used. However, this value must be | 4 | multiprocess extension. This packet is used to request the XML |
5 | incremented by one so that it matches the secure world number of | 5 | description of the CPU. In multiprocess mode, different descriptions can |
6 | implemented priority bits (NS world has one less priority bit compared | 6 | be sent for different processes. |
7 | to the Secure world). | ||
8 | 7 | ||
9 | Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr> | 8 | This function now takes the process to send the description for as a |
10 | Message-id: 20180119145756.7629-5-luc.michel@greensocs.com | 9 | parameter, and use a buffer in the process structure to store the |
11 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 10 | generated description. |
12 | [PMM: add assert, as the gicv3 code has] | 11 | |
12 | It takes the first CPU of the process to generate the description. | ||
13 | |||
14 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
15 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
16 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
17 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
18 | Message-id: 20181207090135.7651-9-luc.michel@greensocs.com | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | --- | 20 | --- |
15 | hw/intc/arm_gic.c | 3 ++- | 21 | gdbstub.c | 52 ++++++++++++++++++++++++++++++---------------------- |
16 | 1 file changed, 2 insertions(+), 1 deletion(-) | 22 | 1 file changed, 30 insertions(+), 22 deletions(-) |
17 | 23 | ||
18 | diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c | 24 | diff --git a/gdbstub.c b/gdbstub.c |
19 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/hw/intc/arm_gic.c | 26 | --- a/gdbstub.c |
21 | +++ b/hw/intc/arm_gic.c | 27 | +++ b/gdbstub.c |
22 | @@ -XXX,XX +XXX,XX @@ static int gic_get_group_priority(GICState *s, int cpu, int irq) | 28 | @@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState { |
23 | if (gic_has_groups(s) && | 29 | typedef struct GDBProcess { |
24 | !(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) && | 30 | uint32_t pid; |
25 | GIC_TEST_GROUP(irq, (1 << cpu))) { | 31 | bool attached; |
26 | - bpr = s->abpr[cpu]; | 32 | + |
27 | + bpr = s->abpr[cpu] - 1; | 33 | + char target_xml[1024]; |
28 | + assert(bpr >= 0); | 34 | } GDBProcess; |
29 | } else { | 35 | |
30 | bpr = s->bpr[cpu]; | 36 | enum RSState { |
37 | @@ -XXX,XX +XXX,XX @@ static CPUState *gdb_first_attached_cpu(const GDBState *s) | ||
38 | return cpu; | ||
39 | } | ||
40 | |||
41 | -static const char *get_feature_xml(const char *p, const char **newp, | ||
42 | - CPUClass *cc) | ||
43 | +static const char *get_feature_xml(const GDBState *s, const char *p, | ||
44 | + const char **newp, GDBProcess *process) | ||
45 | { | ||
46 | size_t len; | ||
47 | int i; | ||
48 | const char *name; | ||
49 | - static char target_xml[1024]; | ||
50 | + CPUState *cpu = get_first_cpu_in_process(s, process); | ||
51 | + CPUClass *cc = CPU_GET_CLASS(cpu); | ||
52 | |||
53 | len = 0; | ||
54 | while (p[len] && p[len] != ':') | ||
55 | @@ -XXX,XX +XXX,XX @@ static const char *get_feature_xml(const char *p, const char **newp, | ||
56 | |||
57 | name = NULL; | ||
58 | if (strncmp(p, "target.xml", len) == 0) { | ||
59 | - /* Generate the XML description for this CPU. */ | ||
60 | - if (!target_xml[0]) { | ||
61 | - GDBRegisterState *r; | ||
62 | - CPUState *cpu = first_cpu; | ||
63 | + char *buf = process->target_xml; | ||
64 | + const size_t buf_sz = sizeof(process->target_xml); | ||
65 | |||
66 | - pstrcat(target_xml, sizeof(target_xml), | ||
67 | + /* Generate the XML description for this CPU. */ | ||
68 | + if (!buf[0]) { | ||
69 | + GDBRegisterState *r; | ||
70 | + | ||
71 | + pstrcat(buf, buf_sz, | ||
72 | "<?xml version=\"1.0\"?>" | ||
73 | "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">" | ||
74 | "<target>"); | ||
75 | if (cc->gdb_arch_name) { | ||
76 | gchar *arch = cc->gdb_arch_name(cpu); | ||
77 | - pstrcat(target_xml, sizeof(target_xml), "<architecture>"); | ||
78 | - pstrcat(target_xml, sizeof(target_xml), arch); | ||
79 | - pstrcat(target_xml, sizeof(target_xml), "</architecture>"); | ||
80 | + pstrcat(buf, buf_sz, "<architecture>"); | ||
81 | + pstrcat(buf, buf_sz, arch); | ||
82 | + pstrcat(buf, buf_sz, "</architecture>"); | ||
83 | g_free(arch); | ||
84 | } | ||
85 | - pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\""); | ||
86 | - pstrcat(target_xml, sizeof(target_xml), cc->gdb_core_xml_file); | ||
87 | - pstrcat(target_xml, sizeof(target_xml), "\"/>"); | ||
88 | + pstrcat(buf, buf_sz, "<xi:include href=\""); | ||
89 | + pstrcat(buf, buf_sz, cc->gdb_core_xml_file); | ||
90 | + pstrcat(buf, buf_sz, "\"/>"); | ||
91 | for (r = cpu->gdb_regs; r; r = r->next) { | ||
92 | - pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\""); | ||
93 | - pstrcat(target_xml, sizeof(target_xml), r->xml); | ||
94 | - pstrcat(target_xml, sizeof(target_xml), "\"/>"); | ||
95 | + pstrcat(buf, buf_sz, "<xi:include href=\""); | ||
96 | + pstrcat(buf, buf_sz, r->xml); | ||
97 | + pstrcat(buf, buf_sz, "\"/>"); | ||
98 | } | ||
99 | - pstrcat(target_xml, sizeof(target_xml), "</target>"); | ||
100 | + pstrcat(buf, buf_sz, "</target>"); | ||
101 | } | ||
102 | - return target_xml; | ||
103 | + return buf; | ||
104 | } | ||
105 | if (cc->gdb_get_dynamic_xml) { | ||
106 | - CPUState *cpu = first_cpu; | ||
107 | char *xmlname = g_strndup(p, len); | ||
108 | const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname); | ||
109 | |||
110 | @@ -XXX,XX +XXX,XX @@ out: | ||
111 | static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
112 | { | ||
113 | CPUState *cpu; | ||
114 | + GDBProcess *process; | ||
115 | CPUClass *cc; | ||
116 | const char *p; | ||
117 | uint32_t pid, tid; | ||
118 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
119 | const char *xml; | ||
120 | target_ulong total_len; | ||
121 | |||
122 | - cc = CPU_GET_CLASS(first_cpu); | ||
123 | + process = gdb_get_cpu_process(s, s->g_cpu); | ||
124 | + cc = CPU_GET_CLASS(s->g_cpu); | ||
125 | if (cc->gdb_core_xml_file == NULL) { | ||
126 | goto unknown_command; | ||
127 | } | ||
128 | |||
129 | gdb_has_xml = true; | ||
130 | p += 19; | ||
131 | - xml = get_feature_xml(p, &p, cc); | ||
132 | + xml = get_feature_xml(s, p, &p, process); | ||
133 | if (!xml) { | ||
134 | snprintf(buf, sizeof(buf), "E00"); | ||
135 | put_packet(s, buf); | ||
136 | @@ -XXX,XX +XXX,XX @@ static void create_default_process(GDBState *s) | ||
137 | |||
138 | process->pid = max_pid + 1; | ||
139 | process->attached = false; | ||
140 | + process->target_xml[0] = '\0'; | ||
141 | } | ||
142 | |||
143 | #ifdef CONFIG_USER_ONLY | ||
144 | @@ -XXX,XX +XXX,XX @@ static int find_cpu_clusters(Object *child, void *opaque) | ||
145 | assert(cluster->cluster_id != UINT32_MAX); | ||
146 | process->pid = cluster->cluster_id + 1; | ||
147 | process->attached = false; | ||
148 | + process->target_xml[0] = '\0'; | ||
149 | |||
150 | return 0; | ||
31 | } | 151 | } |
32 | -- | 152 | -- |
33 | 2.7.4 | 153 | 2.19.2 |
34 | 154 | ||
35 | 155 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Add support for multiprocess extension in gdb_vm_state_change() | ||
4 | function. | ||
5 | |||
6 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
8 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
9 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Message-id: 20181207090135.7651-10-luc.michel@greensocs.com | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | gdbstub.c | 15 ++++++++++++--- | ||
14 | 1 file changed, 12 insertions(+), 3 deletions(-) | ||
15 | |||
16 | diff --git a/gdbstub.c b/gdbstub.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/gdbstub.c | ||
19 | +++ b/gdbstub.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | ||
21 | GDBState *s = gdbserver_state; | ||
22 | CPUState *cpu = s->c_cpu; | ||
23 | char buf[256]; | ||
24 | + char thread_id[16]; | ||
25 | const char *type; | ||
26 | int ret; | ||
27 | |||
28 | @@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | ||
29 | put_packet(s, s->syscall_buf); | ||
30 | return; | ||
31 | } | ||
32 | + | ||
33 | + if (cpu == NULL) { | ||
34 | + /* No process attached */ | ||
35 | + return; | ||
36 | + } | ||
37 | + | ||
38 | + gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)); | ||
39 | + | ||
40 | switch (state) { | ||
41 | case RUN_STATE_DEBUG: | ||
42 | if (cpu->watchpoint_hit) { | ||
43 | @@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | ||
44 | trace_gdbstub_hit_watchpoint(type, cpu_gdb_index(cpu), | ||
45 | (target_ulong)cpu->watchpoint_hit->vaddr); | ||
46 | snprintf(buf, sizeof(buf), | ||
47 | - "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", | ||
48 | - GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type, | ||
49 | + "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";", | ||
50 | + GDB_SIGNAL_TRAP, thread_id, type, | ||
51 | (target_ulong)cpu->watchpoint_hit->vaddr); | ||
52 | cpu->watchpoint_hit = NULL; | ||
53 | goto send_packet; | ||
54 | @@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | ||
55 | break; | ||
56 | } | ||
57 | gdb_set_stop_cpu(cpu); | ||
58 | - snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_gdb_index(cpu)); | ||
59 | + snprintf(buf, sizeof(buf), "T%02xthread:%s;", ret, thread_id); | ||
60 | |||
61 | send_packet: | ||
62 | put_packet(s, buf); | ||
63 | -- | ||
64 | 2.19.2 | ||
65 | |||
66 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Luc Michel <luc.michel@greensocs.com> |
---|---|---|---|
2 | 2 | ||
3 | Helpers that return a pointer into env->vfp.regs so that we isolate | 3 | 'D' packets are used by GDB to detach from a process. In multiprocess |
4 | the logic of how to index the regs array for different cpu modes. | 4 | mode, the PID to detach from is sent in the request. |
5 | 5 | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> |
7 | Message-id: 20180119045438.28582-7-richard.henderson@linaro.org | 7 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
8 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 8 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> |
9 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Message-id: 20181207090135.7651-11-luc.michel@greensocs.com | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 12 | --- |
11 | target/arm/cpu.h | 27 +++++++++++++++++++++++++++ | 13 | gdbstub.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- |
12 | linux-user/signal.c | 22 ++++++++++++---------- | 14 | 1 file changed, 53 insertions(+), 7 deletions(-) |
13 | target/arm/arch_dump.c | 8 +++++--- | ||
14 | target/arm/helper-a64.c | 5 +++-- | ||
15 | target/arm/helper.c | 32 ++++++++++++++++++++------------ | ||
16 | target/arm/kvm32.c | 4 ++-- | ||
17 | target/arm/kvm64.c | 31 ++++++++++--------------------- | ||
18 | target/arm/translate-a64.c | 25 ++++++++----------------- | ||
19 | target/arm/translate.c | 16 +++++++++------- | ||
20 | 9 files changed, 96 insertions(+), 74 deletions(-) | ||
21 | 15 | ||
22 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 16 | diff --git a/gdbstub.c b/gdbstub.c |
23 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/target/arm/cpu.h | 18 | --- a/gdbstub.c |
25 | +++ b/target/arm/cpu.h | 19 | +++ b/gdbstub.c |
26 | @@ -XXX,XX +XXX,XX @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu) | 20 | @@ -XXX,XX +XXX,XX @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) |
27 | return cpu->el_change_hook_opaque; | 21 | } |
28 | } | 22 | } |
29 | 23 | ||
30 | +/** | 24 | +static inline void gdb_cpu_breakpoint_remove_all(CPUState *cpu) |
31 | + * aa32_vfp_dreg: | ||
32 | + * Return a pointer to the Dn register within env in 32-bit mode. | ||
33 | + */ | ||
34 | +static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno) | ||
35 | +{ | 25 | +{ |
36 | + return &env->vfp.regs[regno]; | 26 | + cpu_breakpoint_remove_all(cpu, BP_GDB); |
27 | +#ifndef CONFIG_USER_ONLY | ||
28 | + cpu_watchpoint_remove_all(cpu, BP_GDB); | ||
29 | +#endif | ||
37 | +} | 30 | +} |
38 | + | 31 | + |
39 | +/** | 32 | +static void gdb_process_breakpoint_remove_all(const GDBState *s, GDBProcess *p) |
40 | + * aa32_vfp_qreg: | ||
41 | + * Return a pointer to the Qn register within env in 32-bit mode. | ||
42 | + */ | ||
43 | +static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno) | ||
44 | +{ | 33 | +{ |
45 | + return &env->vfp.regs[2 * regno]; | 34 | + CPUState *cpu = get_first_cpu_in_process(s, p); |
35 | + | ||
36 | + while (cpu) { | ||
37 | + gdb_cpu_breakpoint_remove_all(cpu); | ||
38 | + cpu = gdb_next_cpu_in_process(s, cpu); | ||
39 | + } | ||
46 | +} | 40 | +} |
47 | + | 41 | + |
48 | +/** | 42 | static void gdb_breakpoint_remove_all(void) |
49 | + * aa64_vfp_qreg: | 43 | { |
50 | + * Return a pointer to the Qn register within env in 64-bit mode. | 44 | CPUState *cpu; |
51 | + */ | 45 | @@ -XXX,XX +XXX,XX @@ static void gdb_breakpoint_remove_all(void) |
52 | +static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno) | ||
53 | +{ | ||
54 | + return &env->vfp.regs[2 * regno]; | ||
55 | +} | ||
56 | + | ||
57 | #endif | ||
58 | diff --git a/linux-user/signal.c b/linux-user/signal.c | ||
59 | index XXXXXXX..XXXXXXX 100644 | ||
60 | --- a/linux-user/signal.c | ||
61 | +++ b/linux-user/signal.c | ||
62 | @@ -XXX,XX +XXX,XX @@ static int target_setup_sigframe(struct target_rt_sigframe *sf, | ||
63 | } | 46 | } |
64 | 47 | ||
65 | for (i = 0; i < 32; i++) { | 48 | CPU_FOREACH(cpu) { |
66 | + uint64_t *q = aa64_vfp_qreg(env, i); | 49 | - cpu_breakpoint_remove_all(cpu, BP_GDB); |
67 | #ifdef TARGET_WORDS_BIGENDIAN | 50 | -#ifndef CONFIG_USER_ONLY |
68 | - __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]); | 51 | - cpu_watchpoint_remove_all(cpu, BP_GDB); |
69 | - __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]); | ||
70 | + __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]); | ||
71 | + __put_user(q[1], &aux->fpsimd.vregs[i * 2]); | ||
72 | #else | ||
73 | - __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]); | ||
74 | - __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]); | ||
75 | + __put_user(q[0], &aux->fpsimd.vregs[i * 2]); | ||
76 | + __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]); | ||
77 | #endif | ||
78 | } | ||
79 | __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr); | ||
80 | @@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env, | ||
81 | } | ||
82 | |||
83 | for (i = 0; i < 32; i++) { | ||
84 | + uint64_t *q = aa64_vfp_qreg(env, i); | ||
85 | #ifdef TARGET_WORDS_BIGENDIAN | ||
86 | - __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]); | ||
87 | - __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]); | ||
88 | + __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]); | ||
89 | + __get_user(q[1], &aux->fpsimd.vregs[i * 2]); | ||
90 | #else | ||
91 | - __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]); | ||
92 | - __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]); | ||
93 | + __get_user(q[0], &aux->fpsimd.vregs[i * 2]); | ||
94 | + __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]); | ||
95 | #endif | ||
96 | } | ||
97 | __get_user(fpsr, &aux->fpsimd.fpsr); | ||
98 | @@ -XXX,XX +XXX,XX @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env) | ||
99 | __put_user(TARGET_VFP_MAGIC, &vfpframe->magic); | ||
100 | __put_user(sizeof(*vfpframe), &vfpframe->size); | ||
101 | for (i = 0; i < 32; i++) { | ||
102 | - __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]); | ||
103 | + __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]); | ||
104 | } | ||
105 | __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr); | ||
106 | __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc); | ||
107 | @@ -XXX,XX +XXX,XX @@ static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace) | ||
108 | return 0; | ||
109 | } | ||
110 | for (i = 0; i < 32; i++) { | ||
111 | - __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]); | ||
112 | + __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]); | ||
113 | } | ||
114 | __get_user(fpscr, &vfpframe->ufp.fpscr); | ||
115 | vfp_set_fpscr(env, fpscr); | ||
116 | diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c | ||
117 | index XXXXXXX..XXXXXXX 100644 | ||
118 | --- a/target/arm/arch_dump.c | ||
119 | +++ b/target/arm/arch_dump.c | ||
120 | @@ -XXX,XX +XXX,XX @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f, | ||
121 | |||
122 | aarch64_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp)); | ||
123 | |||
124 | - for (i = 0; i < 64; ++i) { | ||
125 | - note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]); | ||
126 | + for (i = 0; i < 32; ++i) { | ||
127 | + uint64_t *q = aa64_vfp_qreg(env, i); | ||
128 | + note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]); | ||
129 | + note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]); | ||
130 | } | ||
131 | |||
132 | if (s->dump_info.d_endian == ELFDATA2MSB) { | ||
133 | @@ -XXX,XX +XXX,XX @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env, | ||
134 | arm_note_init(¬e, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp)); | ||
135 | |||
136 | for (i = 0; i < 32; ++i) { | ||
137 | - note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]); | ||
138 | + note.vfp.vregs[i] = cpu_to_dump64(s, *aa32_vfp_dreg(env, i)); | ||
139 | } | ||
140 | |||
141 | note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env)); | ||
142 | diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c | ||
143 | index XXXXXXX..XXXXXXX 100644 | ||
144 | --- a/target/arm/helper-a64.c | ||
145 | +++ b/target/arm/helper-a64.c | ||
146 | @@ -XXX,XX +XXX,XX @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices, | ||
147 | if (index < 16 * numregs) { | ||
148 | /* Convert index (a byte offset into the virtual table | ||
149 | * which is a series of 128-bit vectors concatenated) | ||
150 | - * into the correct vfp.regs[] element plus a bit offset | ||
151 | + * into the correct register element plus a bit offset | ||
152 | * into that element, bearing in mind that the table | ||
153 | * can wrap around from V31 to V0. | ||
154 | */ | ||
155 | int elt = (rn * 2 + (index >> 3)) % 64; | ||
156 | int bitidx = (index & 7) * 8; | ||
157 | - uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8); | ||
158 | + uint64_t *q = aa64_vfp_qreg(env, elt >> 1); | ||
159 | + uint64_t val = extract64(q[elt & 1], bitidx, 8); | ||
160 | |||
161 | result = deposit64(result, shift, 8, val); | ||
162 | } | ||
163 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
164 | index XXXXXXX..XXXXXXX 100644 | ||
165 | --- a/target/arm/helper.c | ||
166 | +++ b/target/arm/helper.c | ||
167 | @@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
168 | /* VFP data registers are always little-endian. */ | ||
169 | nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16; | ||
170 | if (reg < nregs) { | ||
171 | - stq_le_p(buf, env->vfp.regs[reg]); | ||
172 | + stq_le_p(buf, *aa32_vfp_dreg(env, reg)); | ||
173 | return 8; | ||
174 | } | ||
175 | if (arm_feature(env, ARM_FEATURE_NEON)) { | ||
176 | /* Aliases for Q regs. */ | ||
177 | nregs += 16; | ||
178 | if (reg < nregs) { | ||
179 | - stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]); | ||
180 | - stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]); | ||
181 | + uint64_t *q = aa32_vfp_qreg(env, reg - 32); | ||
182 | + stq_le_p(buf, q[0]); | ||
183 | + stq_le_p(buf + 8, q[1]); | ||
184 | return 16; | ||
185 | } | ||
186 | } | ||
187 | @@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
188 | |||
189 | nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16; | ||
190 | if (reg < nregs) { | ||
191 | - env->vfp.regs[reg] = ldq_le_p(buf); | ||
192 | + *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); | ||
193 | return 8; | ||
194 | } | ||
195 | if (arm_feature(env, ARM_FEATURE_NEON)) { | ||
196 | nregs += 16; | ||
197 | if (reg < nregs) { | ||
198 | - env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf); | ||
199 | - env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8); | ||
200 | + uint64_t *q = aa32_vfp_qreg(env, reg - 32); | ||
201 | + q[0] = ldq_le_p(buf); | ||
202 | + q[1] = ldq_le_p(buf + 8); | ||
203 | return 16; | ||
204 | } | ||
205 | } | ||
206 | @@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
207 | switch (reg) { | ||
208 | case 0 ... 31: | ||
209 | /* 128 bit FP register */ | ||
210 | - stq_le_p(buf, env->vfp.regs[reg * 2]); | ||
211 | - stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]); | ||
212 | - return 16; | ||
213 | + { | ||
214 | + uint64_t *q = aa64_vfp_qreg(env, reg); | ||
215 | + stq_le_p(buf, q[0]); | ||
216 | + stq_le_p(buf + 8, q[1]); | ||
217 | + return 16; | ||
218 | + } | ||
219 | case 32: | ||
220 | /* FPSR */ | ||
221 | stl_p(buf, vfp_get_fpsr(env)); | ||
222 | @@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
223 | switch (reg) { | ||
224 | case 0 ... 31: | ||
225 | /* 128 bit FP register */ | ||
226 | - env->vfp.regs[reg * 2] = ldq_le_p(buf); | ||
227 | - env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8); | ||
228 | - return 16; | ||
229 | + { | ||
230 | + uint64_t *q = aa64_vfp_qreg(env, reg); | ||
231 | + q[0] = ldq_le_p(buf); | ||
232 | + q[1] = ldq_le_p(buf + 8); | ||
233 | + return 16; | ||
234 | + } | ||
235 | case 32: | ||
236 | /* FPSR */ | ||
237 | vfp_set_fpsr(env, ldl_p(buf)); | ||
238 | diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c | ||
239 | index XXXXXXX..XXXXXXX 100644 | ||
240 | --- a/target/arm/kvm32.c | ||
241 | +++ b/target/arm/kvm32.c | ||
242 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level) | ||
243 | /* VFP registers */ | ||
244 | r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP; | ||
245 | for (i = 0; i < 32; i++) { | ||
246 | - r.addr = (uintptr_t)(&env->vfp.regs[i]); | ||
247 | + r.addr = (uintptr_t)aa32_vfp_dreg(env, i); | ||
248 | ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); | ||
249 | if (ret) { | ||
250 | return ret; | ||
251 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs) | ||
252 | /* VFP registers */ | ||
253 | r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP; | ||
254 | for (i = 0; i < 32; i++) { | ||
255 | - r.addr = (uintptr_t)(&env->vfp.regs[i]); | ||
256 | + r.addr = (uintptr_t)aa32_vfp_dreg(env, i); | ||
257 | ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); | ||
258 | if (ret) { | ||
259 | return ret; | ||
260 | diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c | ||
261 | index XXXXXXX..XXXXXXX 100644 | ||
262 | --- a/target/arm/kvm64.c | ||
263 | +++ b/target/arm/kvm64.c | ||
264 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level) | ||
265 | } | ||
266 | } | ||
267 | |||
268 | - /* Advanced SIMD and FP registers | ||
269 | - * We map Qn = regs[2n+1]:regs[2n] | ||
270 | - */ | ||
271 | + /* Advanced SIMD and FP registers. */ | ||
272 | for (i = 0; i < 32; i++) { | ||
273 | - int rd = i << 1; | ||
274 | - uint64_t fp_val[2]; | ||
275 | + uint64_t *q = aa64_vfp_qreg(env, i); | ||
276 | #ifdef HOST_WORDS_BIGENDIAN | ||
277 | - fp_val[0] = env->vfp.regs[rd + 1]; | ||
278 | - fp_val[1] = env->vfp.regs[rd]; | ||
279 | + uint64_t fp_val[2] = { q[1], q[0] }; | ||
280 | + reg.addr = (uintptr_t)fp_val; | ||
281 | #else | ||
282 | - fp_val[1] = env->vfp.regs[rd + 1]; | ||
283 | - fp_val[0] = env->vfp.regs[rd]; | ||
284 | + reg.addr = (uintptr_t)q; | ||
285 | #endif | ||
286 | reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]); | ||
287 | - reg.addr = (uintptr_t)(&fp_val); | ||
288 | ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); | ||
289 | if (ret) { | ||
290 | return ret; | ||
291 | @@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs) | ||
292 | env->spsr = env->banked_spsr[i]; | ||
293 | } | ||
294 | |||
295 | - /* Advanced SIMD and FP registers | ||
296 | - * We map Qn = regs[2n+1]:regs[2n] | ||
297 | - */ | ||
298 | + /* Advanced SIMD and FP registers */ | ||
299 | for (i = 0; i < 32; i++) { | ||
300 | - uint64_t fp_val[2]; | ||
301 | + uint64_t *q = aa64_vfp_qreg(env, i); | ||
302 | reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]); | ||
303 | - reg.addr = (uintptr_t)(&fp_val); | ||
304 | + reg.addr = (uintptr_t)q; | ||
305 | ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); | ||
306 | if (ret) { | ||
307 | return ret; | ||
308 | } else { | ||
309 | - int rd = i << 1; | ||
310 | #ifdef HOST_WORDS_BIGENDIAN | ||
311 | - env->vfp.regs[rd + 1] = fp_val[0]; | ||
312 | - env->vfp.regs[rd] = fp_val[1]; | ||
313 | -#else | ||
314 | - env->vfp.regs[rd + 1] = fp_val[1]; | ||
315 | - env->vfp.regs[rd] = fp_val[0]; | ||
316 | + uint64_t t; | ||
317 | + t = q[0], q[0] = q[1], q[1] = t; | ||
318 | #endif | ||
319 | } | ||
320 | } | ||
321 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
322 | index XXXXXXX..XXXXXXX 100644 | ||
323 | --- a/target/arm/translate-a64.c | ||
324 | +++ b/target/arm/translate-a64.c | ||
325 | @@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, | ||
326 | |||
327 | if (flags & CPU_DUMP_FPU) { | ||
328 | int numvfpregs = 32; | ||
329 | - for (i = 0; i < numvfpregs; i += 2) { | ||
330 | - uint64_t vlo = env->vfp.regs[i * 2]; | ||
331 | - uint64_t vhi = env->vfp.regs[(i * 2) + 1]; | ||
332 | - cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ", | ||
333 | - i, vhi, vlo); | ||
334 | - vlo = env->vfp.regs[(i + 1) * 2]; | ||
335 | - vhi = env->vfp.regs[((i + 1) * 2) + 1]; | ||
336 | - cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n", | ||
337 | - i + 1, vhi, vlo); | ||
338 | + for (i = 0; i < numvfpregs; i++) { | ||
339 | + uint64_t *q = aa64_vfp_qreg(env, i); | ||
340 | + uint64_t vlo = q[0]; | ||
341 | + uint64_t vhi = q[1]; | ||
342 | + cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c", | ||
343 | + i, vhi, vlo, (i & 1 ? '\n' : ' ')); | ||
344 | } | ||
345 | cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n", | ||
346 | vfp_get_fpcr(env), vfp_get_fpsr(env)); | ||
347 | @@ -XXX,XX +XXX,XX @@ static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno) | ||
348 | */ | ||
349 | static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size) | ||
350 | { | ||
351 | - int offs = offsetof(CPUARMState, vfp.regs[regno * 2]); | ||
352 | -#ifdef HOST_WORDS_BIGENDIAN | ||
353 | - offs += (8 - (1 << size)); | ||
354 | -#endif | 52 | -#endif |
355 | - assert_fp_access_checked(s); | 53 | + gdb_cpu_breakpoint_remove_all(cpu); |
356 | - return offs; | ||
357 | + return vec_reg_offset(s, regno, 0, size); | ||
358 | } | ||
359 | |||
360 | /* Offset of the high half of the 128 bit vector Qn */ | ||
361 | static inline int fp_reg_hi_offset(DisasContext *s, int regno) | ||
362 | { | ||
363 | - assert_fp_access_checked(s); | ||
364 | - return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]); | ||
365 | + return vec_reg_offset(s, regno, 1, MO_64); | ||
366 | } | ||
367 | |||
368 | /* Convenience accessors for reading and writing single and double | ||
369 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
370 | index XXXXXXX..XXXXXXX 100644 | ||
371 | --- a/target/arm/translate.c | ||
372 | +++ b/target/arm/translate.c | ||
373 | @@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr) | ||
374 | static inline long | ||
375 | vfp_reg_offset (int dp, int reg) | ||
376 | { | ||
377 | - if (dp) | ||
378 | + if (dp) { | ||
379 | return offsetof(CPUARMState, vfp.regs[reg]); | ||
380 | - else if (reg & 1) { | ||
381 | - return offsetof(CPUARMState, vfp.regs[reg >> 1]) | ||
382 | - + offsetof(CPU_DoubleU, l.upper); | ||
383 | } else { | ||
384 | - return offsetof(CPUARMState, vfp.regs[reg >> 1]) | ||
385 | - + offsetof(CPU_DoubleU, l.lower); | ||
386 | + long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]); | ||
387 | + if (reg & 1) { | ||
388 | + ofs += offsetof(CPU_DoubleU, l.upper); | ||
389 | + } else { | ||
390 | + ofs += offsetof(CPU_DoubleU, l.lower); | ||
391 | + } | ||
392 | + return ofs; | ||
393 | } | 54 | } |
394 | } | 55 | } |
395 | 56 | ||
396 | @@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, | 57 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) |
397 | numvfpregs += 16; | 58 | exit(0); |
398 | } | 59 | case 'D': |
399 | for (i = 0; i < numvfpregs; i++) { | 60 | /* Detach packet */ |
400 | - uint64_t v = env->vfp.regs[i]; | 61 | - gdb_breakpoint_remove_all(); |
401 | + uint64_t v = *aa32_vfp_dreg(env, i); | 62 | - gdb_syscall_mode = GDB_SYS_DISABLED; |
402 | cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n", | 63 | - gdb_continue(s); |
403 | i * 2, (uint32_t)v, | 64 | + pid = 1; |
404 | i * 2 + 1, (uint32_t)(v >> 32), | 65 | + |
66 | + if (s->multiprocess) { | ||
67 | + unsigned long lpid; | ||
68 | + if (*p != ';') { | ||
69 | + put_packet(s, "E22"); | ||
70 | + break; | ||
71 | + } | ||
72 | + | ||
73 | + if (qemu_strtoul(p + 1, &p, 16, &lpid)) { | ||
74 | + put_packet(s, "E22"); | ||
75 | + break; | ||
76 | + } | ||
77 | + | ||
78 | + pid = lpid; | ||
79 | + } | ||
80 | + | ||
81 | + process = gdb_get_process(s, pid); | ||
82 | + gdb_process_breakpoint_remove_all(s, process); | ||
83 | + process->attached = false; | ||
84 | + | ||
85 | + if (pid == gdb_get_cpu_pid(s, s->c_cpu)) { | ||
86 | + s->c_cpu = gdb_first_attached_cpu(s); | ||
87 | + } | ||
88 | + | ||
89 | + if (pid == gdb_get_cpu_pid(s, s->g_cpu)) { | ||
90 | + s->g_cpu = gdb_first_attached_cpu(s); | ||
91 | + } | ||
92 | + | ||
93 | + if (s->c_cpu == NULL) { | ||
94 | + /* No more process attached */ | ||
95 | + gdb_syscall_mode = GDB_SYS_DISABLED; | ||
96 | + gdb_continue(s); | ||
97 | + } | ||
98 | put_packet(s, "OK"); | ||
99 | break; | ||
100 | case 's': | ||
405 | -- | 101 | -- |
406 | 2.7.4 | 102 | 2.19.2 |
407 | 103 | ||
408 | 104 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Add support for the '!' extended mode packet. This is required for the | ||
4 | multiprocess extension. | ||
5 | |||
6 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
7 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
8 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
9 | Message-id: 20181207090135.7651-12-luc.michel@greensocs.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | gdbstub.c | 3 +++ | ||
13 | 1 file changed, 3 insertions(+) | ||
14 | |||
15 | diff --git a/gdbstub.c b/gdbstub.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/gdbstub.c | ||
18 | +++ b/gdbstub.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
20 | p = line_buf; | ||
21 | ch = *p++; | ||
22 | switch(ch) { | ||
23 | + case '!': | ||
24 | + put_packet(s, "OK"); | ||
25 | + break; | ||
26 | case '?': | ||
27 | /* TODO: Make this return the correct value for user-mode. */ | ||
28 | snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP, | ||
29 | -- | ||
30 | 2.19.2 | ||
31 | |||
32 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Add support for the vAttach packets. In multiprocess mode, GDB sends | ||
4 | them to attach to additional processes. | ||
5 | |||
6 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
7 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
8 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
9 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
10 | Message-id: 20181207090135.7651-13-luc.michel@greensocs.com | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | gdbstub.c | 35 +++++++++++++++++++++++++++++++++++ | ||
14 | 1 file changed, 35 insertions(+) | ||
15 | |||
16 | diff --git a/gdbstub.c b/gdbstub.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/gdbstub.c | ||
19 | +++ b/gdbstub.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
21 | goto unknown_command; | ||
22 | } | ||
23 | break; | ||
24 | + } else if (strncmp(p, "Attach;", 7) == 0) { | ||
25 | + unsigned long pid; | ||
26 | + | ||
27 | + p += 7; | ||
28 | + | ||
29 | + if (qemu_strtoul(p, &p, 16, &pid)) { | ||
30 | + put_packet(s, "E22"); | ||
31 | + break; | ||
32 | + } | ||
33 | + | ||
34 | + process = gdb_get_process(s, pid); | ||
35 | + | ||
36 | + if (process == NULL) { | ||
37 | + put_packet(s, "E22"); | ||
38 | + break; | ||
39 | + } | ||
40 | + | ||
41 | + cpu = get_first_cpu_in_process(s, process); | ||
42 | + | ||
43 | + if (cpu == NULL) { | ||
44 | + /* Refuse to attach an empty process */ | ||
45 | + put_packet(s, "E22"); | ||
46 | + break; | ||
47 | + } | ||
48 | + | ||
49 | + process->attached = true; | ||
50 | + | ||
51 | + s->g_cpu = cpu; | ||
52 | + s->c_cpu = cpu; | ||
53 | + | ||
54 | + snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP, | ||
55 | + gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id))); | ||
56 | + | ||
57 | + put_packet(s, buf); | ||
58 | + break; | ||
59 | } else { | ||
60 | goto unknown_command; | ||
61 | } | ||
62 | -- | ||
63 | 2.19.2 | ||
64 | |||
65 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | When a new connection is established, we set the first process to be | ||
4 | attached, and the others detached. The first CPU of the first process | ||
5 | is selected as the current CPU. | ||
6 | |||
7 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
8 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
9 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
11 | Message-id: 20181207090135.7651-14-luc.michel@greensocs.com | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
13 | --- | ||
14 | gdbstub.c | 20 +++++++++++++++----- | ||
15 | 1 file changed, 15 insertions(+), 5 deletions(-) | ||
16 | |||
17 | diff --git a/gdbstub.c b/gdbstub.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/gdbstub.c | ||
20 | +++ b/gdbstub.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void) | ||
22 | } | ||
23 | |||
24 | s = g_malloc0(sizeof(GDBState)); | ||
25 | - s->c_cpu = first_cpu; | ||
26 | - s->g_cpu = first_cpu; | ||
27 | create_default_process(s); | ||
28 | + s->processes[0].attached = true; | ||
29 | + s->c_cpu = gdb_first_attached_cpu(s); | ||
30 | + s->g_cpu = s->c_cpu; | ||
31 | s->fd = fd; | ||
32 | gdb_has_xml = false; | ||
33 | |||
34 | @@ -XXX,XX +XXX,XX @@ static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size) | ||
35 | |||
36 | static void gdb_chr_event(void *opaque, int event) | ||
37 | { | ||
38 | + int i; | ||
39 | + GDBState *s = (GDBState *) opaque; | ||
40 | + | ||
41 | switch (event) { | ||
42 | case CHR_EVENT_OPENED: | ||
43 | + /* Start with first process attached, others detached */ | ||
44 | + for (i = 0; i < s->process_num; i++) { | ||
45 | + s->processes[i].attached = !i; | ||
46 | + } | ||
47 | + | ||
48 | + s->c_cpu = gdb_first_attached_cpu(s); | ||
49 | + s->g_cpu = s->c_cpu; | ||
50 | + | ||
51 | vm_stop(RUN_STATE_PAUSED); | ||
52 | gdb_has_xml = false; | ||
53 | break; | ||
54 | @@ -XXX,XX +XXX,XX @@ int gdbserver_start(const char *device) | ||
55 | memset(s, 0, sizeof(GDBState)); | ||
56 | s->mon_chr = mon_chr; | ||
57 | } | ||
58 | - s->c_cpu = first_cpu; | ||
59 | - s->g_cpu = first_cpu; | ||
60 | |||
61 | create_processes(s); | ||
62 | |||
63 | if (chr) { | ||
64 | qemu_chr_fe_init(&s->chr, chr, &error_abort); | ||
65 | qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive, | ||
66 | - gdb_chr_event, NULL, NULL, NULL, true); | ||
67 | + gdb_chr_event, NULL, s, NULL, true); | ||
68 | } | ||
69 | s->state = chr ? RS_IDLE : RS_INACTIVE; | ||
70 | s->mon_chr = mon_chr; | ||
71 | -- | ||
72 | 2.19.2 | ||
73 | |||
74 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | When gdb_set_stop_cpu() is called with a CPU associated to a process | ||
4 | currently not attached by the GDB client, return without modifying the | ||
5 | stop CPU. Otherwise, GDB gets confused if it receives packets with a | ||
6 | thread-id it does not know about. | ||
7 | |||
8 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
9 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
10 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
11 | Message-id: 20181207090135.7651-15-luc.michel@greensocs.com | ||
12 | [PMM: fix checkpatch comment style nit] | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | --- | ||
15 | gdbstub.c | 10 ++++++++++ | ||
16 | 1 file changed, 10 insertions(+) | ||
17 | |||
18 | diff --git a/gdbstub.c b/gdbstub.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/gdbstub.c | ||
21 | +++ b/gdbstub.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | ||
23 | |||
24 | void gdb_set_stop_cpu(CPUState *cpu) | ||
25 | { | ||
26 | + GDBProcess *p = gdb_get_cpu_process(gdbserver_state, cpu); | ||
27 | + | ||
28 | + if (!p->attached) { | ||
29 | + /* | ||
30 | + * Having a stop CPU corresponding to a process that is not attached | ||
31 | + * confuses GDB. So we ignore the request. | ||
32 | + */ | ||
33 | + return; | ||
34 | + } | ||
35 | + | ||
36 | gdbserver_state->c_cpu = cpu; | ||
37 | gdbserver_state->g_cpu = cpu; | ||
38 | } | ||
39 | -- | ||
40 | 2.19.2 | ||
41 | |||
42 | diff view generated by jsdifflib |
1 | From: Luc MICHEL <luc.michel@git.antfield.fr> | 1 | From: Luc Michel <luc.michel@greensocs.com> |
---|---|---|---|
2 | 2 | ||
3 | When C_CTRL.CBPR is 1, the Non-Secure view of C_BPR is altered: | 3 | Add multiprocess extension support by enabling multiprocess mode when |
4 | - A Non-Secure read of C_BPR should return the BPR value plus 1, | 4 | the peer requests it, and by replying that we actually support it in the |
5 | saturated to 7, | 5 | qSupported reply packet. |
6 | - A Non-Secure write should be ignored. | ||
7 | 6 | ||
8 | Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr> | 7 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> |
9 | Message-id: 20180119145756.7629-6-luc.michel@greensocs.com | 8 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
11 | [PMM: fixed comment typo] | 10 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> |
11 | Message-id: 20181207090135.7651-16-luc.michel@greensocs.com | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
13 | --- | 13 | --- |
14 | hw/intc/arm_gic.c | 16 +++++++++++++--- | 14 | gdbstub.c | 6 ++++++ |
15 | 1 file changed, 13 insertions(+), 3 deletions(-) | 15 | 1 file changed, 6 insertions(+) |
16 | 16 | ||
17 | diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c | 17 | diff --git a/gdbstub.c b/gdbstub.c |
18 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/hw/intc/arm_gic.c | 19 | --- a/gdbstub.c |
20 | +++ b/hw/intc/arm_gic.c | 20 | +++ b/gdbstub.c |
21 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, | 21 | @@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) |
22 | break; | 22 | if (cc->gdb_core_xml_file != NULL) { |
23 | case 0x08: /* Binary Point */ | 23 | pstrcat(buf, sizeof(buf), ";qXfer:features:read+"); |
24 | if (s->security_extn && !attrs.secure) { | 24 | } |
25 | - /* BPR is banked. Non-secure copy stored in ABPR. */ | 25 | + |
26 | - *data = s->abpr[cpu]; | 26 | + if (strstr(p, "multiprocess+")) { |
27 | + if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) { | 27 | + s->multiprocess = true; |
28 | + /* NS view of BPR when CBPR is 1 */ | ||
29 | + *data = MIN(s->bpr[cpu] + 1, 7); | ||
30 | + } else { | ||
31 | + /* BPR is banked. Non-secure copy stored in ABPR. */ | ||
32 | + *data = s->abpr[cpu]; | ||
33 | + } | 28 | + } |
34 | } else { | 29 | + pstrcat(buf, sizeof(buf), ";multiprocess+"); |
35 | *data = s->bpr[cpu]; | 30 | + |
36 | } | 31 | put_packet(s, buf); |
37 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, | 32 | break; |
38 | break; | ||
39 | case 0x08: /* Binary Point */ | ||
40 | if (s->security_extn && !attrs.secure) { | ||
41 | - s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR); | ||
42 | + if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) { | ||
43 | + /* WI when CBPR is 1 */ | ||
44 | + return MEMTX_OK; | ||
45 | + } else { | ||
46 | + s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR); | ||
47 | + } | ||
48 | } else { | ||
49 | s->bpr[cpu] = MAX(value & 0x7, GIC_MIN_BPR); | ||
50 | } | 33 | } |
51 | -- | 34 | -- |
52 | 2.7.4 | 35 | 2.19.2 |
53 | 36 | ||
54 | 37 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Luc Michel <luc.michel@greensocs.com> | ||
1 | 2 | ||
3 | Create two separate CPU clusters for APUs and RPUs. | ||
4 | |||
5 | Signed-off-by: Luc Michel <luc.michel@greensocs.com> | ||
6 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
8 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
9 | Message-id: 20181207090135.7651-17-luc.michel@greensocs.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | include/hw/arm/xlnx-zynqmp.h | 3 +++ | ||
13 | hw/arm/xlnx-zynqmp.c | 23 +++++++++++++++++++---- | ||
14 | 2 files changed, 22 insertions(+), 4 deletions(-) | ||
15 | |||
16 | diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/include/hw/arm/xlnx-zynqmp.h | ||
19 | +++ b/include/hw/arm/xlnx-zynqmp.h | ||
20 | @@ -XXX,XX +XXX,XX @@ | ||
21 | #include "hw/display/xlnx_dp.h" | ||
22 | #include "hw/intc/xlnx-zynqmp-ipi.h" | ||
23 | #include "hw/timer/xlnx-zynqmp-rtc.h" | ||
24 | +#include "hw/cpu/cluster.h" | ||
25 | |||
26 | #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" | ||
27 | #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ | ||
28 | @@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState { | ||
29 | DeviceState parent_obj; | ||
30 | |||
31 | /*< public >*/ | ||
32 | + CPUClusterState apu_cluster; | ||
33 | + CPUClusterState rpu_cluster; | ||
34 | ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS]; | ||
35 | ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS]; | ||
36 | GICState gic; | ||
37 | diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/hw/arm/xlnx-zynqmp.c | ||
40 | +++ b/hw/arm/xlnx-zynqmp.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu, | ||
42 | int i; | ||
43 | int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS); | ||
44 | |||
45 | + object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster, | ||
46 | + sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER, | ||
47 | + &error_abort, NULL); | ||
48 | + qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1); | ||
49 | + | ||
50 | + qdev_init_nofail(DEVICE(&s->rpu_cluster)); | ||
51 | + | ||
52 | for (i = 0; i < num_rpus; i++) { | ||
53 | char *name; | ||
54 | |||
55 | object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), | ||
56 | "cortex-r5f-" TYPE_ARM_CPU); | ||
57 | - object_property_add_child(OBJECT(s), "rpu-cpu[*]", | ||
58 | + object_property_add_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]", | ||
59 | OBJECT(&s->rpu_cpu[i]), &error_abort); | ||
60 | |||
61 | name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i])); | ||
62 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj) | ||
63 | int i; | ||
64 | int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS); | ||
65 | |||
66 | + object_initialize_child(obj, "apu-cluster", &s->apu_cluster, | ||
67 | + sizeof(s->apu_cluster), TYPE_CPU_CLUSTER, | ||
68 | + &error_abort, NULL); | ||
69 | + qdev_prop_set_uint32(DEVICE(&s->apu_cluster), "cluster-id", 0); | ||
70 | + | ||
71 | for (i = 0; i < num_apus; i++) { | ||
72 | - object_initialize_child(obj, "apu-cpu[*]", &s->apu_cpu[i], | ||
73 | - sizeof(s->apu_cpu[i]), | ||
74 | - "cortex-a53-" TYPE_ARM_CPU, &error_abort, NULL); | ||
75 | + object_initialize_child(OBJECT(&s->apu_cluster), "apu-cpu[*]", | ||
76 | + &s->apu_cpu[i], sizeof(s->apu_cpu[i]), | ||
77 | + "cortex-a53-" TYPE_ARM_CPU, &error_abort, | ||
78 | + NULL); | ||
79 | } | ||
80 | |||
81 | sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic), | ||
82 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) | ||
83 | qdev_prop_set_bit(DEVICE(&s->gic), | ||
84 | "has-virtualization-extensions", s->virt); | ||
85 | |||
86 | + qdev_init_nofail(DEVICE(&s->apu_cluster)); | ||
87 | + | ||
88 | /* Realize APUs before realizing the GIC. KVM requires this. */ | ||
89 | for (i = 0; i < num_apus; i++) { | ||
90 | char *name; | ||
91 | -- | ||
92 | 2.19.2 | ||
93 | |||
94 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Stefan Hajnoczi <stefanha@redhat.com> | ||
1 | 2 | ||
3 | This reverts commit 01fd41ab3fb69971c24a69ed49cde96086d81278. | ||
4 | |||
5 | The generic loader device (-device loader,file=kernel.bin) can be used | ||
6 | to load a kernel instead of the -kernel option. Some boards have flash | ||
7 | memory (pflash) that is set via the -pflash or -drive options. | ||
8 | |||
9 | Allow starting QEMU without the -kernel option to accommodate these | ||
10 | scenarios. | ||
11 | |||
12 | Suggested-by: Peter Maydell <peter.maydell@linaro.org> | ||
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Message-id: 20190103144124.18917-1-stefanha@redhat.com | ||
15 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
17 | --- | ||
18 | hw/arm/armv7m.c | 5 ----- | ||
19 | 1 file changed, 5 deletions(-) | ||
20 | |||
21 | diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/hw/arm/armv7m.c | ||
24 | +++ b/hw/arm/armv7m.c | ||
25 | @@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) | ||
26 | big_endian = 0; | ||
27 | #endif | ||
28 | |||
29 | - if (!kernel_filename && !qtest_enabled()) { | ||
30 | - error_report("Guest image must be specified (using -kernel)"); | ||
31 | - exit(1); | ||
32 | - } | ||
33 | - | ||
34 | if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) { | ||
35 | asidx = ARMASIdx_S; | ||
36 | } else { | ||
37 | -- | ||
38 | 2.19.2 | ||
39 | |||
40 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Plug a couple of "board creation time" memory leaks. | ||
4 | |||
5 | Fixes: 6f16da53ffe4567 ("hw/arm: versal: Add a virtual Xilinx Versal board") | ||
6 | Reported-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
9 | Message-id: 20190104104749.5314-2-edgar.iglesias@gmail.com | ||
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | hw/arm/xlnx-versal-virt.c | 2 ++ | ||
14 | 1 file changed, 2 insertions(+) | ||
15 | |||
16 | diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/arm/xlnx-versal-virt.c | ||
19 | +++ b/hw/arm/xlnx-versal-virt.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_nodes(VersalVirt *s) | ||
21 | 2, MM_GIC_APU_REDIST_0_SIZE); | ||
22 | qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3); | ||
23 | qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3"); | ||
24 | + g_free(nodename); | ||
25 | } | ||
26 | |||
27 | static void fdt_add_timer_nodes(VersalVirt *s) | ||
28 | @@ -XXX,XX +XXX,XX @@ static void create_virtio_regions(VersalVirt *s) | ||
29 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq); | ||
30 | mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); | ||
31 | memory_region_add_subregion(&s->soc.mr_ps, base, mr); | ||
32 | + g_free(name); | ||
33 | } | ||
34 | |||
35 | for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) { | ||
36 | -- | ||
37 | 2.19.2 | ||
38 | |||
39 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Rather than passing regnos to the helpers, pass pointers to the | 3 | Some of the files in hw/input/, hw/misc/ and hw/timer/ are only |
4 | vector registers directly. This eliminates the need to pass in | 4 | used by one of the ARM machines, so we can assign these files to |
5 | the environment pointer and reduces the number of places that | 5 | the corresponding boards. |
6 | directly access env->vfp.regs[]. | ||
7 | 6 | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Thomas Huth <thuth@redhat.com> |
9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 8 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 9 | Message-id: 1546433583-18397-1-git-send-email-thuth@redhat.com |
11 | Message-id: 20180119045438.28582-4-richard.henderson@linaro.org | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
13 | --- | 11 | --- |
14 | target/arm/helper.h | 20 +++--- | 12 | MAINTAINERS | 16 ++++++++++++++-- |
15 | target/arm/neon_helper.c | 162 +++++++++++++++++++++++++---------------------- | 13 | 1 file changed, 14 insertions(+), 2 deletions(-) |
16 | target/arm/translate.c | 42 ++++++------ | ||
17 | 3 files changed, 120 insertions(+), 104 deletions(-) | ||
18 | 14 | ||
19 | diff --git a/target/arm/helper.h b/target/arm/helper.h | 15 | diff --git a/MAINTAINERS b/MAINTAINERS |
20 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/helper.h | 17 | --- a/MAINTAINERS |
22 | +++ b/target/arm/helper.h | 18 | +++ b/MAINTAINERS |
23 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32) | 19 | @@ -XXX,XX +XXX,XX @@ F: hw/intc/arm* |
24 | DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32) | 20 | F: hw/intc/gic_internal.h |
25 | DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32) | 21 | F: hw/misc/a9scu.c |
26 | 22 | F: hw/misc/arm11scu.c | |
27 | -DEF_HELPER_3(neon_unzip8, void, env, i32, i32) | 23 | +F: hw/misc/arm_l2x0.c |
28 | -DEF_HELPER_3(neon_unzip16, void, env, i32, i32) | 24 | F: hw/timer/a9gtimer* |
29 | -DEF_HELPER_3(neon_qunzip8, void, env, i32, i32) | 25 | F: hw/timer/arm* |
30 | -DEF_HELPER_3(neon_qunzip16, void, env, i32, i32) | 26 | F: include/hw/arm/arm*.h |
31 | -DEF_HELPER_3(neon_qunzip32, void, env, i32, i32) | 27 | @@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org |
32 | -DEF_HELPER_3(neon_zip8, void, env, i32, i32) | 28 | S: Maintained |
33 | -DEF_HELPER_3(neon_zip16, void, env, i32, i32) | 29 | F: hw/arm/integratorcp.c |
34 | -DEF_HELPER_3(neon_qzip8, void, env, i32, i32) | 30 | F: hw/misc/arm_integrator_debug.c |
35 | -DEF_HELPER_3(neon_qzip16, void, env, i32, i32) | 31 | +F: include/hw/misc/arm_integrator_debug.h |
36 | -DEF_HELPER_3(neon_qzip32, void, env, i32, i32) | 32 | |
37 | +DEF_HELPER_FLAGS_2(neon_unzip8, TCG_CALL_NO_RWG, void, ptr, ptr) | 33 | MCIMX6UL EVK / i.MX6ul |
38 | +DEF_HELPER_FLAGS_2(neon_unzip16, TCG_CALL_NO_RWG, void, ptr, ptr) | 34 | M: Peter Maydell <peter.maydell@linaro.org> |
39 | +DEF_HELPER_FLAGS_2(neon_qunzip8, TCG_CALL_NO_RWG, void, ptr, ptr) | 35 | @@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org |
40 | +DEF_HELPER_FLAGS_2(neon_qunzip16, TCG_CALL_NO_RWG, void, ptr, ptr) | 36 | S: Odd Fixes |
41 | +DEF_HELPER_FLAGS_2(neon_qunzip32, TCG_CALL_NO_RWG, void, ptr, ptr) | 37 | F: hw/arm/mcimx7d-sabre.c |
42 | +DEF_HELPER_FLAGS_2(neon_zip8, TCG_CALL_NO_RWG, void, ptr, ptr) | 38 | F: hw/arm/fsl-imx7.c |
43 | +DEF_HELPER_FLAGS_2(neon_zip16, TCG_CALL_NO_RWG, void, ptr, ptr) | 39 | +F: hw/misc/imx7_*.c |
44 | +DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr) | 40 | F: include/hw/arm/fsl-imx7.h |
45 | +DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr) | 41 | +F: include/hw/misc/imx7_*.h |
46 | +DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr) | 42 | F: hw/pci-host/designware.c |
47 | 43 | F: include/hw/pci-host/designware.h | |
48 | DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32) | 44 | |
49 | DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32) | 45 | @@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org> |
50 | diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c | 46 | L: qemu-arm@nongnu.org |
51 | index XXXXXXX..XXXXXXX 100644 | 47 | S: Odd Fixes |
52 | --- a/target/arm/neon_helper.c | 48 | F: hw/arm/nseries.c |
53 | +++ b/target/arm/neon_helper.c | 49 | +F: hw/input/lm832x.c |
54 | @@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp) | 50 | +F: hw/input/tsc2005.c |
55 | 51 | +F: hw/misc/cbus.c | |
56 | #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1)) | 52 | +F: hw/timer/twl92230.c |
57 | 53 | ||
58 | -void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | 54 | Palm |
59 | +void HELPER(neon_qunzip8)(void *vd, void *vm) | 55 | M: Andrzej Zaborowski <balrogg@gmail.com> |
60 | { | 56 | @@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org> |
61 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | 57 | L: qemu-arm@nongnu.org |
62 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | 58 | S: Odd Fixes |
63 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | 59 | F: hw/arm/palm.c |
64 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | 60 | +F: hw/input/tsc210x.c |
65 | + uint64_t *rd = vd, *rm = vm; | 61 | |
66 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | 62 | Raspberry Pi |
67 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | 63 | M: Peter Maydell <peter.maydell@linaro.org> |
68 | + | 64 | @@ -XXX,XX +XXX,XX @@ F: hw/display/tc6393xb.c |
69 | uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8) | 65 | F: hw/gpio/max7310.c |
70 | | (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24) | 66 | F: hw/gpio/zaurus.c |
71 | | (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40) | 67 | F: hw/misc/mst_fpga.c |
72 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | 68 | +F: hw/misc/max111x.c |
73 | | (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24) | 69 | F: include/hw/arm/pxa.h |
74 | | (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40) | 70 | F: include/hw/arm/sharpsl.h |
75 | | (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56); | 71 | |
76 | - env->vfp.regs[rm] = make_float64(m0); | 72 | @@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org |
77 | - env->vfp.regs[rm + 1] = make_float64(m1); | 73 | S: Odd Fixes |
78 | - env->vfp.regs[rd] = make_float64(d0); | 74 | F: hw/arm/sabrelite.c |
79 | - env->vfp.regs[rd + 1] = make_float64(d1); | 75 | F: hw/arm/fsl-imx6.c |
80 | + | 76 | -F: hw/misc/imx6_src.c |
81 | + rm[0] = m0; | 77 | +F: hw/misc/imx6_*.c |
82 | + rm[1] = m1; | 78 | F: hw/ssi/imx_spi.c |
83 | + rd[0] = d0; | 79 | F: include/hw/arm/fsl-imx6.h |
84 | + rd[1] = d1; | 80 | -F: include/hw/misc/imx6_src.h |
85 | } | 81 | +F: include/hw/misc/imx6_*.h |
86 | 82 | F: include/hw/ssi/imx_spi.h | |
87 | -void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | 83 | |
88 | +void HELPER(neon_qunzip16)(void *vd, void *vm) | 84 | Sharp SL-5500 (Collie) PDA |
89 | { | 85 | @@ -XXX,XX +XXX,XX @@ R: Joel Stanley <joel@jms.id.au> |
90 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | 86 | L: qemu-arm@nongnu.org |
91 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | 87 | S: Maintained |
92 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | 88 | F: hw/*/*aspeed* |
93 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | 89 | +F: hw/misc/pca9552.c |
94 | + uint64_t *rd = vd, *rm = vm; | 90 | F: include/hw/*/*aspeed* |
95 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | 91 | +F: include/hw/misc/pca9552*.h |
96 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | 92 | F: hw/net/ftgmac100.c |
97 | + | 93 | F: include/hw/net/ftgmac100.h |
98 | uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16) | ||
99 | | (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48); | ||
100 | uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16) | ||
101 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
102 | | (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48); | ||
103 | uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16) | ||
104 | | (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48); | ||
105 | - env->vfp.regs[rm] = make_float64(m0); | ||
106 | - env->vfp.regs[rm + 1] = make_float64(m1); | ||
107 | - env->vfp.regs[rd] = make_float64(d0); | ||
108 | - env->vfp.regs[rd + 1] = make_float64(d1); | ||
109 | + | ||
110 | + rm[0] = m0; | ||
111 | + rm[1] = m1; | ||
112 | + rd[0] = d0; | ||
113 | + rd[1] = d1; | ||
114 | } | ||
115 | |||
116 | -void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
117 | +void HELPER(neon_qunzip32)(void *vd, void *vm) | ||
118 | { | ||
119 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | ||
120 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | ||
121 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | ||
122 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | ||
123 | + uint64_t *rd = vd, *rm = vm; | ||
124 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | ||
125 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | ||
126 | + | ||
127 | uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32); | ||
128 | uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32); | ||
129 | uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32); | ||
130 | uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32); | ||
131 | - env->vfp.regs[rm] = make_float64(m0); | ||
132 | - env->vfp.regs[rm + 1] = make_float64(m1); | ||
133 | - env->vfp.regs[rd] = make_float64(d0); | ||
134 | - env->vfp.regs[rd + 1] = make_float64(d1); | ||
135 | + | ||
136 | + rm[0] = m0; | ||
137 | + rm[1] = m1; | ||
138 | + rd[0] = d0; | ||
139 | + rd[1] = d1; | ||
140 | } | ||
141 | |||
142 | -void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
143 | +void HELPER(neon_unzip8)(void *vd, void *vm) | ||
144 | { | ||
145 | - uint64_t zm = float64_val(env->vfp.regs[rm]); | ||
146 | - uint64_t zd = float64_val(env->vfp.regs[rd]); | ||
147 | + uint64_t *rd = vd, *rm = vm; | ||
148 | + uint64_t zd = rd[0], zm = rm[0]; | ||
149 | + | ||
150 | uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8) | ||
151 | | (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24) | ||
152 | | (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40) | ||
153 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
154 | | (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24) | ||
155 | | (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40) | ||
156 | | (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56); | ||
157 | - env->vfp.regs[rm] = make_float64(m0); | ||
158 | - env->vfp.regs[rd] = make_float64(d0); | ||
159 | + | ||
160 | + rm[0] = m0; | ||
161 | + rd[0] = d0; | ||
162 | } | ||
163 | |||
164 | -void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
165 | +void HELPER(neon_unzip16)(void *vd, void *vm) | ||
166 | { | ||
167 | - uint64_t zm = float64_val(env->vfp.regs[rm]); | ||
168 | - uint64_t zd = float64_val(env->vfp.regs[rd]); | ||
169 | + uint64_t *rd = vd, *rm = vm; | ||
170 | + uint64_t zd = rd[0], zm = rm[0]; | ||
171 | + | ||
172 | uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16) | ||
173 | | (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48); | ||
174 | uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16) | ||
175 | | (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48); | ||
176 | - env->vfp.regs[rm] = make_float64(m0); | ||
177 | - env->vfp.regs[rd] = make_float64(d0); | ||
178 | + | ||
179 | + rm[0] = m0; | ||
180 | + rd[0] = d0; | ||
181 | } | ||
182 | |||
183 | -void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
184 | +void HELPER(neon_qzip8)(void *vd, void *vm) | ||
185 | { | ||
186 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | ||
187 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | ||
188 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | ||
189 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | ||
190 | + uint64_t *rd = vd, *rm = vm; | ||
191 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | ||
192 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | ||
193 | + | ||
194 | uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8) | ||
195 | | (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24) | ||
196 | | (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40) | ||
197 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
198 | | (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24) | ||
199 | | (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40) | ||
200 | | (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56); | ||
201 | - env->vfp.regs[rm] = make_float64(m0); | ||
202 | - env->vfp.regs[rm + 1] = make_float64(m1); | ||
203 | - env->vfp.regs[rd] = make_float64(d0); | ||
204 | - env->vfp.regs[rd + 1] = make_float64(d1); | ||
205 | + | ||
206 | + rm[0] = m0; | ||
207 | + rm[1] = m1; | ||
208 | + rd[0] = d0; | ||
209 | + rd[1] = d1; | ||
210 | } | ||
211 | |||
212 | -void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
213 | +void HELPER(neon_qzip16)(void *vd, void *vm) | ||
214 | { | ||
215 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | ||
216 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | ||
217 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | ||
218 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | ||
219 | + uint64_t *rd = vd, *rm = vm; | ||
220 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | ||
221 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | ||
222 | + | ||
223 | uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16) | ||
224 | | (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48); | ||
225 | uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16) | ||
226 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
227 | | (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48); | ||
228 | uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16) | ||
229 | | (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48); | ||
230 | - env->vfp.regs[rm] = make_float64(m0); | ||
231 | - env->vfp.regs[rm + 1] = make_float64(m1); | ||
232 | - env->vfp.regs[rd] = make_float64(d0); | ||
233 | - env->vfp.regs[rd + 1] = make_float64(d1); | ||
234 | + | ||
235 | + rm[0] = m0; | ||
236 | + rm[1] = m1; | ||
237 | + rd[0] = d0; | ||
238 | + rd[1] = d1; | ||
239 | } | ||
240 | |||
241 | -void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
242 | +void HELPER(neon_qzip32)(void *vd, void *vm) | ||
243 | { | ||
244 | - uint64_t zm0 = float64_val(env->vfp.regs[rm]); | ||
245 | - uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); | ||
246 | - uint64_t zd0 = float64_val(env->vfp.regs[rd]); | ||
247 | - uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]); | ||
248 | + uint64_t *rd = vd, *rm = vm; | ||
249 | + uint64_t zd0 = rd[0], zd1 = rd[1]; | ||
250 | + uint64_t zm0 = rm[0], zm1 = rm[1]; | ||
251 | + | ||
252 | uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32); | ||
253 | uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32); | ||
254 | uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32); | ||
255 | uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32); | ||
256 | - env->vfp.regs[rm] = make_float64(m0); | ||
257 | - env->vfp.regs[rm + 1] = make_float64(m1); | ||
258 | - env->vfp.regs[rd] = make_float64(d0); | ||
259 | - env->vfp.regs[rd + 1] = make_float64(d1); | ||
260 | + | ||
261 | + rm[0] = m0; | ||
262 | + rm[1] = m1; | ||
263 | + rd[0] = d0; | ||
264 | + rd[1] = d1; | ||
265 | } | ||
266 | |||
267 | -void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
268 | +void HELPER(neon_zip8)(void *vd, void *vm) | ||
269 | { | ||
270 | - uint64_t zm = float64_val(env->vfp.regs[rm]); | ||
271 | - uint64_t zd = float64_val(env->vfp.regs[rd]); | ||
272 | + uint64_t *rd = vd, *rm = vm; | ||
273 | + uint64_t zd = rd[0], zm = rm[0]; | ||
274 | + | ||
275 | uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8) | ||
276 | | (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24) | ||
277 | | (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40) | ||
278 | @@ -XXX,XX +XXX,XX @@ void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
279 | | (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24) | ||
280 | | (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40) | ||
281 | | (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56); | ||
282 | - env->vfp.regs[rm] = make_float64(m0); | ||
283 | - env->vfp.regs[rd] = make_float64(d0); | ||
284 | + | ||
285 | + rm[0] = m0; | ||
286 | + rd[0] = d0; | ||
287 | } | ||
288 | |||
289 | -void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm) | ||
290 | +void HELPER(neon_zip16)(void *vd, void *vm) | ||
291 | { | ||
292 | - uint64_t zm = float64_val(env->vfp.regs[rm]); | ||
293 | - uint64_t zd = float64_val(env->vfp.regs[rd]); | ||
294 | + uint64_t *rd = vd, *rm = vm; | ||
295 | + uint64_t zd = rd[0], zm = rm[0]; | ||
296 | + | ||
297 | uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16) | ||
298 | | (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48); | ||
299 | uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16) | ||
300 | | (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48); | ||
301 | - env->vfp.regs[rm] = make_float64(m0); | ||
302 | - env->vfp.regs[rd] = make_float64(d0); | ||
303 | + | ||
304 | + rm[0] = m0; | ||
305 | + rd[0] = d0; | ||
306 | } | ||
307 | |||
308 | /* Helper function for 64 bit polynomial multiply case: | ||
309 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
310 | index XXXXXXX..XXXXXXX 100644 | ||
311 | --- a/target/arm/translate.c | ||
312 | +++ b/target/arm/translate.c | ||
313 | @@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 neon_get_scalar(int size, int reg) | ||
314 | |||
315 | static int gen_neon_unzip(int rd, int rm, int size, int q) | ||
316 | { | ||
317 | - TCGv_i32 tmp, tmp2; | ||
318 | + TCGv_ptr pd, pm; | ||
319 | + | ||
320 | if (!q && size == 2) { | ||
321 | return 1; | ||
322 | } | ||
323 | - tmp = tcg_const_i32(rd); | ||
324 | - tmp2 = tcg_const_i32(rm); | ||
325 | + pd = vfp_reg_ptr(true, rd); | ||
326 | + pm = vfp_reg_ptr(true, rm); | ||
327 | if (q) { | ||
328 | switch (size) { | ||
329 | case 0: | ||
330 | - gen_helper_neon_qunzip8(cpu_env, tmp, tmp2); | ||
331 | + gen_helper_neon_qunzip8(pd, pm); | ||
332 | break; | ||
333 | case 1: | ||
334 | - gen_helper_neon_qunzip16(cpu_env, tmp, tmp2); | ||
335 | + gen_helper_neon_qunzip16(pd, pm); | ||
336 | break; | ||
337 | case 2: | ||
338 | - gen_helper_neon_qunzip32(cpu_env, tmp, tmp2); | ||
339 | + gen_helper_neon_qunzip32(pd, pm); | ||
340 | break; | ||
341 | default: | ||
342 | abort(); | ||
343 | @@ -XXX,XX +XXX,XX @@ static int gen_neon_unzip(int rd, int rm, int size, int q) | ||
344 | } else { | ||
345 | switch (size) { | ||
346 | case 0: | ||
347 | - gen_helper_neon_unzip8(cpu_env, tmp, tmp2); | ||
348 | + gen_helper_neon_unzip8(pd, pm); | ||
349 | break; | ||
350 | case 1: | ||
351 | - gen_helper_neon_unzip16(cpu_env, tmp, tmp2); | ||
352 | + gen_helper_neon_unzip16(pd, pm); | ||
353 | break; | ||
354 | default: | ||
355 | abort(); | ||
356 | } | ||
357 | } | ||
358 | - tcg_temp_free_i32(tmp); | ||
359 | - tcg_temp_free_i32(tmp2); | ||
360 | + tcg_temp_free_ptr(pd); | ||
361 | + tcg_temp_free_ptr(pm); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int gen_neon_zip(int rd, int rm, int size, int q) | ||
366 | { | ||
367 | - TCGv_i32 tmp, tmp2; | ||
368 | + TCGv_ptr pd, pm; | ||
369 | + | ||
370 | if (!q && size == 2) { | ||
371 | return 1; | ||
372 | } | ||
373 | - tmp = tcg_const_i32(rd); | ||
374 | - tmp2 = tcg_const_i32(rm); | ||
375 | + pd = vfp_reg_ptr(true, rd); | ||
376 | + pm = vfp_reg_ptr(true, rm); | ||
377 | if (q) { | ||
378 | switch (size) { | ||
379 | case 0: | ||
380 | - gen_helper_neon_qzip8(cpu_env, tmp, tmp2); | ||
381 | + gen_helper_neon_qzip8(pd, pm); | ||
382 | break; | ||
383 | case 1: | ||
384 | - gen_helper_neon_qzip16(cpu_env, tmp, tmp2); | ||
385 | + gen_helper_neon_qzip16(pd, pm); | ||
386 | break; | ||
387 | case 2: | ||
388 | - gen_helper_neon_qzip32(cpu_env, tmp, tmp2); | ||
389 | + gen_helper_neon_qzip32(pd, pm); | ||
390 | break; | ||
391 | default: | ||
392 | abort(); | ||
393 | @@ -XXX,XX +XXX,XX @@ static int gen_neon_zip(int rd, int rm, int size, int q) | ||
394 | } else { | ||
395 | switch (size) { | ||
396 | case 0: | ||
397 | - gen_helper_neon_zip8(cpu_env, tmp, tmp2); | ||
398 | + gen_helper_neon_zip8(pd, pm); | ||
399 | break; | ||
400 | case 1: | ||
401 | - gen_helper_neon_zip16(cpu_env, tmp, tmp2); | ||
402 | + gen_helper_neon_zip16(pd, pm); | ||
403 | break; | ||
404 | default: | ||
405 | abort(); | ||
406 | } | ||
407 | } | ||
408 | - tcg_temp_free_i32(tmp); | ||
409 | - tcg_temp_free_i32(tmp2); | ||
410 | + tcg_temp_free_ptr(pd); | ||
411 | + tcg_temp_free_ptr(pm); | ||
412 | return 0; | ||
413 | } | ||
414 | 94 | ||
415 | -- | 95 | -- |
416 | 2.7.4 | 96 | 2.19.2 |
417 | 97 | ||
418 | 98 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | We use cpu_stop_current() to ensure the current CPU has stopped |
---|---|---|---|
2 | from places like qemu_system_reset_request(). Unfortunately its | ||
3 | current implementation has a race. It calls qemu_cpu_stop(), | ||
4 | which sets cpu->stopped to true even though the CPU hasn't | ||
5 | actually stopped yet. The main thread will look at the flags | ||
6 | set by qemu_system_reset_request() and call pause_all_vcpus(). | ||
7 | pause_all_vcpus() waits for every cpu to have cpu->stopped true, | ||
8 | so it can continue (and we will start the system reset operation) | ||
9 | before the vcpu thread has got back to its top level loop. | ||
2 | 10 | ||
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 11 | Instead, just set cpu->stop and call cpu_exit(). This will |
4 | Message-id: 20180119045438.28582-16-richard.henderson@linaro.org | 12 | cause the vcpu to exit back to the top level loop, and there |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 13 | (as part of the wait_io_event code) it will call qemu_cpu_stop(). |
6 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 14 | |
15 | This fixes bugs where the reset request appeared to be ignored | ||
16 | or the CPU misbehaved because the reset operation started | ||
17 | to change vcpu state while the vcpu thread was still using it. | ||
18 | |||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
20 | Reviewed-by: Emilio G. Cota <cota@braap.org> | ||
21 | Tested-by: Jaap Crezee <jaap@jcz.nl> | ||
22 | Message-id: 20181207155911.12710-1-peter.maydell@linaro.org | ||
8 | --- | 23 | --- |
9 | target/arm/helper.c | 3 ++- | 24 | cpus.c | 3 ++- |
10 | 1 file changed, 2 insertions(+), 1 deletion(-) | 25 | 1 file changed, 2 insertions(+), 1 deletion(-) |
11 | 26 | ||
12 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 27 | diff --git a/cpus.c b/cpus.c |
13 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/target/arm/helper.c | 29 | --- a/cpus.c |
15 | +++ b/target/arm/helper.c | 30 | +++ b/cpus.c |
16 | @@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes) | 31 | @@ -XXX,XX +XXX,XX @@ void qemu_init_vcpu(CPUState *cpu) |
17 | */ | 32 | void cpu_stop_current(void) |
18 | static inline int fp_exception_el(CPUARMState *env) | ||
19 | { | 33 | { |
20 | +#ifndef CONFIG_USER_ONLY | 34 | if (current_cpu) { |
21 | int fpen; | 35 | - qemu_cpu_stop(current_cpu, true); |
22 | int cur_el = arm_current_el(env); | 36 | + current_cpu->stop = true; |
23 | 37 | + cpu_exit(current_cpu); | |
24 | @@ -XXX,XX +XXX,XX @@ static inline int fp_exception_el(CPUARMState *env) | ||
25 | /* Trap all FP ops to EL3 */ | ||
26 | return 3; | ||
27 | } | 38 | } |
28 | - | ||
29 | +#endif | ||
30 | return 0; | ||
31 | } | 39 | } |
32 | 40 | ||
33 | -- | 41 | -- |
34 | 2.7.4 | 42 | 2.19.2 |
35 | 43 | ||
36 | 44 | diff view generated by jsdifflib |
1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> | 1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> |
---|---|---|---|
2 | 2 | ||
3 | missed in 60765b6ceeb4. | 3 | From the "A10 User Manual V1.20" p.29: "3.2. Memory Mapping" and: |
4 | 4 | ||
5 | Thread 1 "qemu-system-aarch64" received signal SIGSEGV, Segmentation fault. | 5 | 7. System Control |
6 | address_space_init (as=0x0, root=0x55555726e410, name=name@entry=0x555555e3f0a7 "sdhci-dma") at memory.c:3050 | 6 | 7.1. Overview |
7 | 3050 as->root = root; | ||
8 | (gdb) bt | ||
9 | #0 address_space_init (as=0x0, root=0x55555726e410, name=name@entry=0x555555e3f0a7 "sdhci-dma") at memory.c:3050 | ||
10 | #1 0x0000555555af62c3 in sdhci_sysbus_realize (dev=<optimized out>, errp=0x7fff7f931150) at hw/sd/sdhci.c:1564 | ||
11 | #2 0x00005555558b25e5 in zynqmp_sdhci_realize (dev=0x555557051520, errp=0x7fff7f931150) at hw/sd/zynqmp-sdhci.c:151 | ||
12 | #3 0x0000555555a2e7f3 in device_set_realized (obj=0x555557051520, value=<optimized out>, errp=0x7fff7f931270) at hw/core/qdev.c:966 | ||
13 | #4 0x0000555555ba3f74 in property_set_bool (obj=0x555557051520, v=<optimized out>, name=<optimized out>, opaque=0x555556e04a20, | ||
14 | errp=0x7fff7f931270) at qom/object.c:1906 | ||
15 | #5 0x0000555555ba51f4 in object_property_set (obj=obj@entry=0x555557051520, v=v@entry=0x5555576dbd60, | ||
16 | name=name@entry=0x555555dd6306 "realized", errp=errp@entry=0x7fff7f931270) at qom/object.c:1102 | ||
17 | 7 | ||
18 | Suggested-by: Peter Maydell <peter.maydell@linaro.org> | 8 | A10 embeds a high-speed SRAM which has been split into five segments. |
9 | See detailed memory mapping in following table: | ||
10 | |||
11 | Area Address Size (Bytes) | ||
12 | A1 0x00000000-0x00003FFF 16K | ||
13 | A2 0x00004000-0x00007FFF 16K | ||
14 | A3 0x00008000-0x0000B3FF 13K | ||
15 | A4 0x0000B400-0x0000BFFF 3K | ||
16 | |||
17 | Since for emulation purpose we don't need the segmentations, we simply define | ||
18 | the 'A' area as a single 48KB SRAM. | ||
19 | |||
20 | We don't implement the following others areas: | ||
21 | - 'B': 'Secure RAM' (64K), | ||
22 | - 'C': Debug/ISP SRAM | ||
23 | - 'D': USB SRAM | ||
24 | |||
25 | (qemu) info mtree | ||
26 | address-space: memory | ||
27 | 0000000000000000-ffffffffffffffff (prio 0, i/o): system | ||
28 | 0000000000000000-000000000000bfff (prio 0, ram): sram A | ||
29 | 0000000001c00000-0000000001c00fff (prio -1000, i/o): a10-sram-ctrl | ||
30 | 0000000001c0b000-0000000001c0bfff (prio 0, i/o): aw_emac | ||
31 | 0000000001c18000-0000000001c18fff (prio 0, i/o): ahci | ||
32 | 0000000001c18080-0000000001c180ff (prio 0, i/o): allwinner-ahci | ||
33 | 0000000001c20400-0000000001c207ff (prio 0, i/o): allwinner-a10-pic | ||
34 | 0000000001c20c00-0000000001c20fff (prio 0, i/o): allwinner-A10-timer | ||
35 | 0000000001c28000-0000000001c2801f (prio 0, i/o): serial | ||
36 | 0000000040000000-0000000047ffffff (prio 0, ram): cubieboard.ram | ||
37 | |||
38 | Reported-by: Charlie Smurthwaite <charlie@atech.media> | ||
39 | Tested-by: Charlie Smurthwaite <charlie@atech.media> | ||
19 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 40 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
20 | Message-id: 20180123132051.24448-1-f4bug@amsat.org | 41 | Message-id: 20190104142921.878-1-f4bug@amsat.org |
21 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 42 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
22 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 43 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
23 | --- | 44 | --- |
24 | include/hw/sd/sdhci.h | 1 + | 45 | include/hw/arm/allwinner-a10.h | 1 + |
25 | hw/sd/sdhci.c | 1 + | 46 | hw/arm/allwinner-a10.c | 6 ++++++ |
26 | 2 files changed, 2 insertions(+) | 47 | 2 files changed, 7 insertions(+) |
27 | 48 | ||
28 | diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h | 49 | diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h |
29 | index XXXXXXX..XXXXXXX 100644 | 50 | index XXXXXXX..XXXXXXX 100644 |
30 | --- a/include/hw/sd/sdhci.h | 51 | --- a/include/hw/arm/allwinner-a10.h |
31 | +++ b/include/hw/sd/sdhci.h | 52 | +++ b/include/hw/arm/allwinner-a10.h |
32 | @@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState { | 53 | @@ -XXX,XX +XXX,XX @@ typedef struct AwA10State { |
33 | /*< public >*/ | 54 | AwA10PICState intc; |
34 | SDBus sdbus; | 55 | AwEmacState emac; |
35 | MemoryRegion iomem; | 56 | AllwinnerAHCIState sata; |
36 | + AddressSpace sysbus_dma_as; | 57 | + MemoryRegion sram_a; |
37 | AddressSpace *dma_as; | 58 | } AwA10State; |
38 | MemoryRegion *dma_mr; | 59 | |
39 | 60 | #define ALLWINNER_H_ | |
40 | diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c | 61 | diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c |
41 | index XXXXXXX..XXXXXXX 100644 | 62 | index XXXXXXX..XXXXXXX 100644 |
42 | --- a/hw/sd/sdhci.c | 63 | --- a/hw/arm/allwinner-a10.c |
43 | +++ b/hw/sd/sdhci.c | 64 | +++ b/hw/arm/allwinner-a10.c |
44 | @@ -XXX,XX +XXX,XX @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp) | 65 | @@ -XXX,XX +XXX,XX @@ |
45 | } | 66 | #include "hw/sysbus.h" |
46 | 67 | #include "hw/devices.h" | |
47 | if (s->dma_mr) { | 68 | #include "hw/arm/allwinner-a10.h" |
48 | + s->dma_as = &s->sysbus_dma_as; | 69 | +#include "hw/misc/unimp.h" |
49 | address_space_init(s->dma_as, s->dma_mr, "sdhci-dma"); | 70 | |
50 | } else { | 71 | static void aw_a10_init(Object *obj) |
51 | /* use system_memory() if property "dma" not set */ | 72 | { |
73 | @@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp) | ||
74 | sysbus_connect_irq(sysbusdev, 4, s->irq[67]); | ||
75 | sysbus_connect_irq(sysbusdev, 5, s->irq[68]); | ||
76 | |||
77 | + memory_region_init_ram(&s->sram_a, OBJECT(dev), "sram A", 48 * KiB, | ||
78 | + &error_fatal); | ||
79 | + memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a); | ||
80 | + create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB); | ||
81 | + | ||
82 | /* FIXME use qdev NIC properties instead of nd_table[] */ | ||
83 | if (nd_table[0].used) { | ||
84 | qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC); | ||
52 | -- | 85 | -- |
53 | 2.7.4 | 86 | 2.19.2 |
54 | 87 | ||
55 | 88 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | Rather than passing a regno to the helper, pass pointers to the | 3 | Adds a new qtest command "set_irq_in" which allows |
4 | vector register directly. This eliminates the need to pass in | 4 | to set qemu gpio lines to a given level. |
5 | the environment pointer and reduces the number of places that | ||
6 | directly access env->vfp.regs[]. | ||
7 | 5 | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 6 | Based on https://lists.gnu.org/archive/html/qemu-devel/2012-12/msg02363.html |
9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 7 | which never got merged. |
10 | Message-id: 20180119045438.28582-5-richard.henderson@linaro.org | 8 | |
11 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 9 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
10 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
12 | Reviewed-by: Laurent Vivier <lvivier@redhat.com> | ||
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Message-id: 20190103091119.9367-2-stefanha@redhat.com | ||
15 | Originally-by: Matthew Ogilvie <mmogilvi_qemu@miniinfo.net> | ||
16 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
17 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
18 | Reviewed-by: Laurent Vivier <lvivier@redhat.com> | ||
19 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
13 | --- | 21 | --- |
14 | target/arm/helper.h | 2 +- | 22 | tests/libqtest.h | 13 +++++++++++++ |
15 | target/arm/op_helper.c | 17 +++++++---------- | 23 | qtest.c | 43 +++++++++++++++++++++++++++++++++++++++++++ |
16 | target/arm/translate.c | 8 ++++---- | 24 | tests/libqtest.c | 10 ++++++++++ |
17 | 3 files changed, 12 insertions(+), 15 deletions(-) | 25 | 3 files changed, 66 insertions(+) |
18 | 26 | ||
19 | diff --git a/target/arm/helper.h b/target/arm/helper.h | 27 | diff --git a/tests/libqtest.h b/tests/libqtest.h |
20 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/helper.h | 29 | --- a/tests/libqtest.h |
22 | +++ b/target/arm/helper.h | 30 | +++ b/tests/libqtest.h |
23 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr) | 31 | @@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *string); |
24 | DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr) | 32 | */ |
25 | DEF_HELPER_2(recpe_u32, i32, i32, ptr) | 33 | void qtest_irq_intercept_out(QTestState *s, const char *string); |
26 | DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr) | 34 | |
27 | -DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) | 35 | +/** |
28 | +DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32) | 36 | + * qtest_set_irq_in: |
29 | 37 | + * @s: QTestState instance to operate on. | |
30 | DEF_HELPER_3(shl_cc, i32, env, i32, i32) | 38 | + * @string: QOM path of a device |
31 | DEF_HELPER_3(shr_cc, i32, env, i32, i32) | 39 | + * @name: IRQ name |
32 | diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c | 40 | + * @irq: IRQ number |
41 | + * @level: IRQ level | ||
42 | + * | ||
43 | + * Force given device/irq GPIO-in pin to the given level. | ||
44 | + */ | ||
45 | +void qtest_set_irq_in(QTestState *s, const char *string, const char *name, | ||
46 | + int irq, int level); | ||
47 | + | ||
48 | /** | ||
49 | * qtest_outb: | ||
50 | * @s: #QTestState instance to operate on. | ||
51 | diff --git a/qtest.c b/qtest.c | ||
33 | index XXXXXXX..XXXXXXX 100644 | 52 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/target/arm/op_helper.c | 53 | --- a/qtest.c |
35 | +++ b/target/arm/op_helper.c | 54 | +++ b/qtest.c |
36 | @@ -XXX,XX +XXX,XX @@ static int exception_target_el(CPUARMState *env) | 55 | @@ -XXX,XX +XXX,XX @@ static bool qtest_opened; |
37 | return target_el; | 56 | * where NUM is an IRQ number. For the PC, interrupts can be intercepted |
57 | * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with | ||
58 | * NUM=0 even though it is remapped to GSI 2). | ||
59 | + * | ||
60 | + * Setting interrupt level: | ||
61 | + * | ||
62 | + * > set_irq_in QOM-PATH NAME NUM LEVEL | ||
63 | + * < OK | ||
64 | + * | ||
65 | + * where NAME is the name of the irq/gpio list, NUM is an IRQ number and | ||
66 | + * LEVEL is an signed integer IRQ level. | ||
67 | + * | ||
68 | + * Forcibly set the given interrupt pin to the given level. | ||
69 | + * | ||
70 | */ | ||
71 | |||
72 | static int hex2nib(char ch) | ||
73 | @@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words) | ||
74 | irq_intercept_dev = dev; | ||
75 | qtest_send_prefix(chr); | ||
76 | qtest_send(chr, "OK\n"); | ||
77 | + } else if (strcmp(words[0], "set_irq_in") == 0) { | ||
78 | + DeviceState *dev; | ||
79 | + qemu_irq irq; | ||
80 | + char *name; | ||
81 | + int ret; | ||
82 | + int num; | ||
83 | + int level; | ||
84 | |||
85 | + g_assert(words[1] && words[2] && words[3] && words[4]); | ||
86 | + | ||
87 | + dev = DEVICE(object_resolve_path(words[1], NULL)); | ||
88 | + if (!dev) { | ||
89 | + qtest_send_prefix(chr); | ||
90 | + qtest_send(chr, "FAIL Unknown device\n"); | ||
91 | + return; | ||
92 | + } | ||
93 | + | ||
94 | + if (strcmp(words[2], "unnamed-gpio-in") == 0) { | ||
95 | + name = NULL; | ||
96 | + } else { | ||
97 | + name = words[2]; | ||
98 | + } | ||
99 | + | ||
100 | + ret = qemu_strtoi(words[3], NULL, 0, &num); | ||
101 | + g_assert(!ret); | ||
102 | + ret = qemu_strtoi(words[4], NULL, 0, &level); | ||
103 | + g_assert(!ret); | ||
104 | + | ||
105 | + irq = qdev_get_gpio_in_named(dev, name, num); | ||
106 | + | ||
107 | + qemu_set_irq(irq, level); | ||
108 | + qtest_send_prefix(chr); | ||
109 | + qtest_send(chr, "OK\n"); | ||
110 | } else if (strcmp(words[0], "outb") == 0 || | ||
111 | strcmp(words[0], "outw") == 0 || | ||
112 | strcmp(words[0], "outl") == 0) { | ||
113 | diff --git a/tests/libqtest.c b/tests/libqtest.c | ||
114 | index XXXXXXX..XXXXXXX 100644 | ||
115 | --- a/tests/libqtest.c | ||
116 | +++ b/tests/libqtest.c | ||
117 | @@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *qom_path) | ||
118 | qtest_rsp(s, 0); | ||
38 | } | 119 | } |
39 | 120 | ||
40 | -uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, | 121 | +void qtest_set_irq_in(QTestState *s, const char *qom_path, const char *name, |
41 | - uint32_t rn, uint32_t maxindex) | 122 | + int num, int level) |
42 | +uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn, | 123 | +{ |
43 | + uint32_t maxindex) | 124 | + if (!name) { |
125 | + name = "unnamed-gpio-in"; | ||
126 | + } | ||
127 | + qtest_sendf(s, "set_irq_in %s %s %d %d\n", qom_path, name, num, level); | ||
128 | + qtest_rsp(s, 0); | ||
129 | +} | ||
130 | + | ||
131 | static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value) | ||
44 | { | 132 | { |
45 | - uint32_t val; | 133 | qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value); |
46 | - uint32_t tmp; | ||
47 | - int index; | ||
48 | - int shift; | ||
49 | - uint64_t *table; | ||
50 | - table = (uint64_t *)&env->vfp.regs[rn]; | ||
51 | + uint32_t val, shift; | ||
52 | + uint64_t *table = vn; | ||
53 | + | ||
54 | val = 0; | ||
55 | for (shift = 0; shift < 32; shift += 8) { | ||
56 | - index = (ireg >> shift) & 0xff; | ||
57 | + uint32_t index = (ireg >> shift) & 0xff; | ||
58 | if (index < maxindex) { | ||
59 | - tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff; | ||
60 | + uint32_t tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff; | ||
61 | val |= tmp << shift; | ||
62 | } else { | ||
63 | val |= def & (0xff << shift); | ||
64 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
65 | index XXXXXXX..XXXXXXX 100644 | ||
66 | --- a/target/arm/translate.c | ||
67 | +++ b/target/arm/translate.c | ||
68 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
69 | tcg_gen_movi_i32(tmp, 0); | ||
70 | } | ||
71 | tmp2 = neon_load_reg(rm, 0); | ||
72 | - tmp4 = tcg_const_i32(rn); | ||
73 | + ptr1 = vfp_reg_ptr(true, rn); | ||
74 | tmp5 = tcg_const_i32(n); | ||
75 | - gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5); | ||
76 | + gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5); | ||
77 | tcg_temp_free_i32(tmp); | ||
78 | if (insn & (1 << 6)) { | ||
79 | tmp = neon_load_reg(rd, 1); | ||
80 | @@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) | ||
81 | tcg_gen_movi_i32(tmp, 0); | ||
82 | } | ||
83 | tmp3 = neon_load_reg(rm, 1); | ||
84 | - gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5); | ||
85 | + gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5); | ||
86 | tcg_temp_free_i32(tmp5); | ||
87 | - tcg_temp_free_i32(tmp4); | ||
88 | + tcg_temp_free_ptr(ptr1); | ||
89 | neon_store_reg(rd, 0, tmp2); | ||
90 | neon_store_reg(rd, 1, tmp3); | ||
91 | tcg_temp_free_i32(tmp); | ||
92 | -- | 134 | -- |
93 | 2.7.4 | 135 | 2.19.2 |
94 | 136 | ||
95 | 137 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | If it isn't used when translate.h is included, | 3 | Adds a header that provides definitions that are used |
4 | we'll get a compiler Werror. | 4 | across nRF51 peripherals |
5 | 5 | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 6 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
7 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
7 | Reviewed-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: Stefan Hajnoczi <stefanha@redhat.com> |
9 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 10 | Message-id: 20190103091119.9367-3-stefanha@redhat.com |
10 | Message-id: 20180119045438.28582-2-richard.henderson@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.h | 2 +- | 13 | include/hw/arm/nrf51.h | 45 ++++++++++++++++++++++++++++++++++++ |
14 | 1 file changed, 1 insertion(+), 1 deletion(-) | 14 | include/hw/char/nrf51_uart.h | 1 - |
15 | hw/arm/nrf51_soc.c | 33 ++++++++++---------------- | ||
16 | 3 files changed, 57 insertions(+), 22 deletions(-) | ||
17 | create mode 100644 include/hw/arm/nrf51.h | ||
15 | 18 | ||
16 | diff --git a/target/arm/translate.h b/target/arm/translate.h | 19 | diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h |
20 | new file mode 100644 | ||
21 | index XXXXXXX..XXXXXXX | ||
22 | --- /dev/null | ||
23 | +++ b/include/hw/arm/nrf51.h | ||
24 | @@ -XXX,XX +XXX,XX @@ | ||
25 | +/* | ||
26 | + * Nordic Semiconductor nRF51 Series SOC Common Defines | ||
27 | + * | ||
28 | + * This file hosts generic defines used in various nRF51 peripheral devices. | ||
29 | + * | ||
30 | + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
31 | + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf | ||
32 | + * | ||
33 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
34 | + * | ||
35 | + * This code is licensed under the GPL version 2 or later. See | ||
36 | + * the COPYING file in the top-level directory. | ||
37 | + */ | ||
38 | + | ||
39 | +#ifndef NRF51_H | ||
40 | +#define NRF51_H | ||
41 | + | ||
42 | +#define NRF51_FLASH_BASE 0x00000000 | ||
43 | +#define NRF51_FICR_BASE 0x10000000 | ||
44 | +#define NRF51_FICR_SIZE 0x00000100 | ||
45 | +#define NRF51_UICR_BASE 0x10001000 | ||
46 | +#define NRF51_SRAM_BASE 0x20000000 | ||
47 | + | ||
48 | +#define NRF51_IOMEM_BASE 0x40000000 | ||
49 | +#define NRF51_IOMEM_SIZE 0x20000000 | ||
50 | + | ||
51 | +#define NRF51_UART_BASE 0x40002000 | ||
52 | +#define NRF51_TIMER_BASE 0x40008000 | ||
53 | +#define NRF51_TIMER_SIZE 0x00001000 | ||
54 | +#define NRF51_RNG_BASE 0x4000D000 | ||
55 | +#define NRF51_NVMC_BASE 0x4001E000 | ||
56 | +#define NRF51_GPIO_BASE 0x50000000 | ||
57 | + | ||
58 | +#define NRF51_PRIVATE_BASE 0xF0000000 | ||
59 | +#define NRF51_PRIVATE_SIZE 0x10000000 | ||
60 | + | ||
61 | +#define NRF51_PAGE_SIZE 1024 | ||
62 | + | ||
63 | +/* Trigger */ | ||
64 | +#define NRF51_TRIGGER_TASK 0x01 | ||
65 | + | ||
66 | +/* Events */ | ||
67 | +#define NRF51_EVENT_CLEAR 0x00 | ||
68 | + | ||
69 | +#endif | ||
70 | diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | 71 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/target/arm/translate.h | 72 | --- a/include/hw/char/nrf51_uart.h |
19 | +++ b/target/arm/translate.h | 73 | +++ b/include/hw/char/nrf51_uart.h |
20 | @@ -XXX,XX +XXX,XX @@ static inline int default_exception_el(DisasContext *s) | 74 | @@ -XXX,XX +XXX,XX @@ |
21 | ? 3 : MAX(1, s->current_el); | 75 | #include "hw/registerfields.h" |
76 | |||
77 | #define UART_FIFO_LENGTH 6 | ||
78 | -#define UART_BASE 0x40002000 | ||
79 | #define UART_SIZE 0x1000 | ||
80 | |||
81 | #define TYPE_NRF51_UART "nrf51_soc.uart" | ||
82 | diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c | ||
83 | index XXXXXXX..XXXXXXX 100644 | ||
84 | --- a/hw/arm/nrf51_soc.c | ||
85 | +++ b/hw/arm/nrf51_soc.c | ||
86 | @@ -XXX,XX +XXX,XX @@ | ||
87 | #include "qemu/log.h" | ||
88 | #include "cpu.h" | ||
89 | |||
90 | +#include "hw/arm/nrf51.h" | ||
91 | #include "hw/arm/nrf51_soc.h" | ||
92 | |||
93 | -#define IOMEM_BASE 0x40000000 | ||
94 | -#define IOMEM_SIZE 0x20000000 | ||
95 | - | ||
96 | -#define FICR_BASE 0x10000000 | ||
97 | -#define FICR_SIZE 0x000000fc | ||
98 | - | ||
99 | -#define FLASH_BASE 0x00000000 | ||
100 | -#define SRAM_BASE 0x20000000 | ||
101 | - | ||
102 | -#define PRIVATE_BASE 0xF0000000 | ||
103 | -#define PRIVATE_SIZE 0x10000000 | ||
104 | - | ||
105 | /* | ||
106 | * The size and base is for the NRF51822 part. If other parts | ||
107 | * are supported in the future, add a sub-class of NRF51SoC for | ||
108 | * the specific variants | ||
109 | */ | ||
110 | -#define NRF51822_FLASH_SIZE (256 * 1024) | ||
111 | -#define NRF51822_SRAM_SIZE (16 * 1024) | ||
112 | +#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE) | ||
113 | +#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE) | ||
114 | |||
115 | #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F) | ||
116 | |||
117 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
118 | error_propagate(errp, err); | ||
119 | return; | ||
120 | } | ||
121 | - memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash); | ||
122 | + memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash); | ||
123 | |||
124 | memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err); | ||
125 | if (err) { | ||
126 | error_propagate(errp, err); | ||
127 | return; | ||
128 | } | ||
129 | - memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram); | ||
130 | + memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram); | ||
131 | |||
132 | /* UART */ | ||
133 | object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); | ||
134 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
135 | return; | ||
136 | } | ||
137 | mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); | ||
138 | - memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0); | ||
139 | + memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0); | ||
140 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0, | ||
141 | qdev_get_gpio_in(DEVICE(&s->cpu), | ||
142 | - BASE_TO_IRQ(UART_BASE))); | ||
143 | + BASE_TO_IRQ(NRF51_UART_BASE))); | ||
144 | |||
145 | - create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE); | ||
146 | - create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE); | ||
147 | + create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE, | ||
148 | + NRF51_IOMEM_SIZE); | ||
149 | + create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE, | ||
150 | + NRF51_FICR_SIZE); | ||
151 | create_unimplemented_device("nrf51_soc.private", | ||
152 | - PRIVATE_BASE, PRIVATE_SIZE); | ||
153 | + NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE); | ||
22 | } | 154 | } |
23 | 155 | ||
24 | -static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) | 156 | static void nrf51_soc_init(Object *obj) |
25 | +static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) | ||
26 | { | ||
27 | /* We don't need to save all of the syndrome so we mask and shift | ||
28 | * out unneeded bits to help the sleb128 encoder do a better job. | ||
29 | -- | 157 | -- |
30 | 2.7.4 | 158 | 2.19.2 |
31 | 159 | ||
32 | 160 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> | |
2 | |||
3 | Add a model of the NRF51 random number generator peripheral. | ||
4 | This is a simple random generator that continuously generates | ||
5 | new random values after startup. | ||
6 | |||
7 | Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
8 | |||
9 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> | ||
10 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
13 | Message-id: 20190103091119.9367-4-stefanha@redhat.com | ||
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
15 | --- | ||
16 | hw/misc/Makefile.objs | 1 + | ||
17 | include/hw/misc/nrf51_rng.h | 83 ++++++++++++ | ||
18 | hw/misc/nrf51_rng.c | 262 ++++++++++++++++++++++++++++++++++++ | ||
19 | 3 files changed, 346 insertions(+) | ||
20 | create mode 100644 include/hw/misc/nrf51_rng.h | ||
21 | create mode 100644 hw/misc/nrf51_rng.c | ||
22 | |||
23 | diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/hw/misc/Makefile.objs | ||
26 | +++ b/hw/misc/Makefile.objs | ||
27 | @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_PVPANIC) += pvpanic.o | ||
28 | obj-$(CONFIG_AUX) += auxbus.o | ||
29 | obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o | ||
30 | obj-$(CONFIG_MSF2) += msf2-sysreg.o | ||
31 | +obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o | ||
32 | diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h | ||
33 | new file mode 100644 | ||
34 | index XXXXXXX..XXXXXXX | ||
35 | --- /dev/null | ||
36 | +++ b/include/hw/misc/nrf51_rng.h | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | +/* | ||
39 | + * nRF51 Random Number Generator | ||
40 | + * | ||
41 | + * QEMU interface: | ||
42 | + * + Property "period_unfiltered_us": Time between two biased values in | ||
43 | + * microseconds. | ||
44 | + * + Property "period_filtered_us": Time between two unbiased values in | ||
45 | + * microseconds. | ||
46 | + * + sysbus MMIO regions 0: Memory Region with tasks, events and registers | ||
47 | + * to be mapped to the peripherals instance address by the SOC. | ||
48 | + * + Named GPIO output "irq": Interrupt line of the peripheral. Must be | ||
49 | + * connected to the associated peripheral interrupt line of the NVIC. | ||
50 | + * + Named GPIO output "eep_valrdy": Event set when new random value is ready | ||
51 | + * to be read. | ||
52 | + * + Named GPIO input "tep_start": Task that triggers start of continuous | ||
53 | + * generation of random values. | ||
54 | + * + Named GPIO input "tep_stop": Task that ends continuous generation of | ||
55 | + * random values. | ||
56 | + * | ||
57 | + * Accuracy of the peripheral model: | ||
58 | + * + Stochastic properties of different configurations of the random source | ||
59 | + * are not modeled. | ||
60 | + * + Generation of unfiltered and filtered random values take at least the | ||
61 | + * average generation time stated in the production specification; | ||
62 | + * non-deterministic generation times are not modeled. | ||
63 | + * | ||
64 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
65 | + * | ||
66 | + * This code is licensed under the GPL version 2 or later. See | ||
67 | + * the COPYING file in the top-level directory. | ||
68 | + * | ||
69 | + */ | ||
70 | +#ifndef NRF51_RNG_H | ||
71 | +#define NRF51_RNG_H | ||
72 | + | ||
73 | +#include "hw/sysbus.h" | ||
74 | +#include "qemu/timer.h" | ||
75 | +#define TYPE_NRF51_RNG "nrf51_soc.rng" | ||
76 | +#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG) | ||
77 | + | ||
78 | +#define NRF51_RNG_SIZE 0x1000 | ||
79 | + | ||
80 | +#define NRF51_RNG_TASK_START 0x000 | ||
81 | +#define NRF51_RNG_TASK_STOP 0x004 | ||
82 | +#define NRF51_RNG_EVENT_VALRDY 0x100 | ||
83 | +#define NRF51_RNG_REG_SHORTS 0x200 | ||
84 | +#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0 | ||
85 | +#define NRF51_RNG_REG_INTEN 0x300 | ||
86 | +#define NRF51_RNG_REG_INTEN_VALRDY 0 | ||
87 | +#define NRF51_RNG_REG_INTENSET 0x304 | ||
88 | +#define NRF51_RNG_REG_INTENCLR 0x308 | ||
89 | +#define NRF51_RNG_REG_CONFIG 0x504 | ||
90 | +#define NRF51_RNG_REG_CONFIG_DECEN 0 | ||
91 | +#define NRF51_RNG_REG_VALUE 0x508 | ||
92 | + | ||
93 | +typedef struct { | ||
94 | + SysBusDevice parent_obj; | ||
95 | + | ||
96 | + MemoryRegion mmio; | ||
97 | + qemu_irq irq; | ||
98 | + | ||
99 | + /* Event End Points */ | ||
100 | + qemu_irq eep_valrdy; | ||
101 | + | ||
102 | + QEMUTimer timer; | ||
103 | + | ||
104 | + /* Time between generation of successive unfiltered values in us */ | ||
105 | + uint16_t period_unfiltered_us; | ||
106 | + /* Time between generation of successive filtered values in us */ | ||
107 | + uint16_t period_filtered_us; | ||
108 | + | ||
109 | + uint8_t value; | ||
110 | + | ||
111 | + uint32_t active; | ||
112 | + uint32_t event_valrdy; | ||
113 | + uint32_t shortcut_stop_on_valrdy; | ||
114 | + uint32_t interrupt_enabled; | ||
115 | + uint32_t filter_enabled; | ||
116 | + | ||
117 | +} NRF51RNGState; | ||
118 | + | ||
119 | + | ||
120 | +#endif /* NRF51_RNG_H_ */ | ||
121 | diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c | ||
122 | new file mode 100644 | ||
123 | index XXXXXXX..XXXXXXX | ||
124 | --- /dev/null | ||
125 | +++ b/hw/misc/nrf51_rng.c | ||
126 | @@ -XXX,XX +XXX,XX @@ | ||
127 | +/* | ||
128 | + * nRF51 Random Number Generator | ||
129 | + * | ||
130 | + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf | ||
131 | + * | ||
132 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
133 | + * | ||
134 | + * This code is licensed under the GPL version 2 or later. See | ||
135 | + * the COPYING file in the top-level directory. | ||
136 | + */ | ||
137 | + | ||
138 | +#include "qemu/osdep.h" | ||
139 | +#include "qemu/log.h" | ||
140 | +#include "qapi/error.h" | ||
141 | +#include "hw/arm/nrf51.h" | ||
142 | +#include "hw/misc/nrf51_rng.h" | ||
143 | +#include "crypto/random.h" | ||
144 | + | ||
145 | +static void update_irq(NRF51RNGState *s) | ||
146 | +{ | ||
147 | + bool irq = s->interrupt_enabled && s->event_valrdy; | ||
148 | + qemu_set_irq(s->irq, irq); | ||
149 | +} | ||
150 | + | ||
151 | +static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size) | ||
152 | +{ | ||
153 | + NRF51RNGState *s = NRF51_RNG(opaque); | ||
154 | + uint64_t r = 0; | ||
155 | + | ||
156 | + switch (offset) { | ||
157 | + case NRF51_RNG_EVENT_VALRDY: | ||
158 | + r = s->event_valrdy; | ||
159 | + break; | ||
160 | + case NRF51_RNG_REG_SHORTS: | ||
161 | + r = s->shortcut_stop_on_valrdy; | ||
162 | + break; | ||
163 | + case NRF51_RNG_REG_INTEN: | ||
164 | + case NRF51_RNG_REG_INTENSET: | ||
165 | + case NRF51_RNG_REG_INTENCLR: | ||
166 | + r = s->interrupt_enabled; | ||
167 | + break; | ||
168 | + case NRF51_RNG_REG_CONFIG: | ||
169 | + r = s->filter_enabled; | ||
170 | + break; | ||
171 | + case NRF51_RNG_REG_VALUE: | ||
172 | + r = s->value; | ||
173 | + break; | ||
174 | + | ||
175 | + default: | ||
176 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
177 | + "%s: bad read offset 0x%" HWADDR_PRIx "\n", | ||
178 | + __func__, offset); | ||
179 | + } | ||
180 | + | ||
181 | + return r; | ||
182 | +} | ||
183 | + | ||
184 | +static int64_t calc_next_timeout(NRF51RNGState *s) | ||
185 | +{ | ||
186 | + int64_t timeout = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL); | ||
187 | + if (s->filter_enabled) { | ||
188 | + timeout += s->period_filtered_us; | ||
189 | + } else { | ||
190 | + timeout += s->period_unfiltered_us; | ||
191 | + } | ||
192 | + | ||
193 | + return timeout; | ||
194 | +} | ||
195 | + | ||
196 | + | ||
197 | +static void rng_update_timer(NRF51RNGState *s) | ||
198 | +{ | ||
199 | + if (s->active) { | ||
200 | + timer_mod(&s->timer, calc_next_timeout(s)); | ||
201 | + } else { | ||
202 | + timer_del(&s->timer); | ||
203 | + } | ||
204 | +} | ||
205 | + | ||
206 | + | ||
207 | +static void rng_write(void *opaque, hwaddr offset, | ||
208 | + uint64_t value, unsigned int size) | ||
209 | +{ | ||
210 | + NRF51RNGState *s = NRF51_RNG(opaque); | ||
211 | + | ||
212 | + switch (offset) { | ||
213 | + case NRF51_RNG_TASK_START: | ||
214 | + if (value == NRF51_TRIGGER_TASK) { | ||
215 | + s->active = 1; | ||
216 | + rng_update_timer(s); | ||
217 | + } | ||
218 | + break; | ||
219 | + case NRF51_RNG_TASK_STOP: | ||
220 | + if (value == NRF51_TRIGGER_TASK) { | ||
221 | + s->active = 0; | ||
222 | + rng_update_timer(s); | ||
223 | + } | ||
224 | + break; | ||
225 | + case NRF51_RNG_EVENT_VALRDY: | ||
226 | + if (value == NRF51_EVENT_CLEAR) { | ||
227 | + s->event_valrdy = 0; | ||
228 | + } | ||
229 | + break; | ||
230 | + case NRF51_RNG_REG_SHORTS: | ||
231 | + s->shortcut_stop_on_valrdy = | ||
232 | + (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0; | ||
233 | + break; | ||
234 | + case NRF51_RNG_REG_INTEN: | ||
235 | + s->interrupt_enabled = | ||
236 | + (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0; | ||
237 | + break; | ||
238 | + case NRF51_RNG_REG_INTENSET: | ||
239 | + if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { | ||
240 | + s->interrupt_enabled = 1; | ||
241 | + } | ||
242 | + break; | ||
243 | + case NRF51_RNG_REG_INTENCLR: | ||
244 | + if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { | ||
245 | + s->interrupt_enabled = 0; | ||
246 | + } | ||
247 | + break; | ||
248 | + case NRF51_RNG_REG_CONFIG: | ||
249 | + s->filter_enabled = | ||
250 | + (value & BIT_MASK(NRF51_RNG_REG_CONFIG_DECEN)) ? 1 : 0; | ||
251 | + break; | ||
252 | + | ||
253 | + default: | ||
254 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
255 | + "%s: bad write offset 0x%" HWADDR_PRIx "\n", | ||
256 | + __func__, offset); | ||
257 | + } | ||
258 | + | ||
259 | + update_irq(s); | ||
260 | +} | ||
261 | + | ||
262 | +static const MemoryRegionOps rng_ops = { | ||
263 | + .read = rng_read, | ||
264 | + .write = rng_write, | ||
265 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
266 | + .impl.min_access_size = 4, | ||
267 | + .impl.max_access_size = 4 | ||
268 | +}; | ||
269 | + | ||
270 | +static void nrf51_rng_timer_expire(void *opaque) | ||
271 | +{ | ||
272 | + NRF51RNGState *s = NRF51_RNG(opaque); | ||
273 | + | ||
274 | + qcrypto_random_bytes(&s->value, 1, &error_abort); | ||
275 | + | ||
276 | + s->event_valrdy = 1; | ||
277 | + qemu_set_irq(s->eep_valrdy, 1); | ||
278 | + | ||
279 | + if (s->shortcut_stop_on_valrdy) { | ||
280 | + s->active = 0; | ||
281 | + } | ||
282 | + | ||
283 | + rng_update_timer(s); | ||
284 | + update_irq(s); | ||
285 | +} | ||
286 | + | ||
287 | +static void nrf51_rng_tep_start(void *opaque, int n, int level) | ||
288 | +{ | ||
289 | + NRF51RNGState *s = NRF51_RNG(opaque); | ||
290 | + | ||
291 | + if (level) { | ||
292 | + s->active = 1; | ||
293 | + rng_update_timer(s); | ||
294 | + } | ||
295 | +} | ||
296 | + | ||
297 | +static void nrf51_rng_tep_stop(void *opaque, int n, int level) | ||
298 | +{ | ||
299 | + NRF51RNGState *s = NRF51_RNG(opaque); | ||
300 | + | ||
301 | + if (level) { | ||
302 | + s->active = 0; | ||
303 | + rng_update_timer(s); | ||
304 | + } | ||
305 | +} | ||
306 | + | ||
307 | + | ||
308 | +static void nrf51_rng_init(Object *obj) | ||
309 | +{ | ||
310 | + NRF51RNGState *s = NRF51_RNG(obj); | ||
311 | + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
312 | + | ||
313 | + memory_region_init_io(&s->mmio, obj, &rng_ops, s, | ||
314 | + TYPE_NRF51_RNG, NRF51_RNG_SIZE); | ||
315 | + sysbus_init_mmio(sbd, &s->mmio); | ||
316 | + | ||
317 | + timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s); | ||
318 | + | ||
319 | + sysbus_init_irq(sbd, &s->irq); | ||
320 | + | ||
321 | + /* Tasks */ | ||
322 | + qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1); | ||
323 | + qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1); | ||
324 | + | ||
325 | + /* Events */ | ||
326 | + qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1); | ||
327 | +} | ||
328 | + | ||
329 | +static void nrf51_rng_reset(DeviceState *dev) | ||
330 | +{ | ||
331 | + NRF51RNGState *s = NRF51_RNG(dev); | ||
332 | + | ||
333 | + s->value = 0; | ||
334 | + s->active = 0; | ||
335 | + s->event_valrdy = 0; | ||
336 | + s->shortcut_stop_on_valrdy = 0; | ||
337 | + s->interrupt_enabled = 0; | ||
338 | + s->filter_enabled = 0; | ||
339 | + | ||
340 | + rng_update_timer(s); | ||
341 | +} | ||
342 | + | ||
343 | + | ||
344 | +static Property nrf51_rng_properties[] = { | ||
345 | + DEFINE_PROP_UINT16("period_unfiltered_us", NRF51RNGState, | ||
346 | + period_unfiltered_us, 167), | ||
347 | + DEFINE_PROP_UINT16("period_filtered_us", NRF51RNGState, | ||
348 | + period_filtered_us, 660), | ||
349 | + DEFINE_PROP_END_OF_LIST(), | ||
350 | +}; | ||
351 | + | ||
352 | +static const VMStateDescription vmstate_rng = { | ||
353 | + .name = "nrf51_soc.rng", | ||
354 | + .version_id = 1, | ||
355 | + .minimum_version_id = 1, | ||
356 | + .fields = (VMStateField[]) { | ||
357 | + VMSTATE_UINT32(active, NRF51RNGState), | ||
358 | + VMSTATE_UINT32(event_valrdy, NRF51RNGState), | ||
359 | + VMSTATE_UINT32(shortcut_stop_on_valrdy, NRF51RNGState), | ||
360 | + VMSTATE_UINT32(interrupt_enabled, NRF51RNGState), | ||
361 | + VMSTATE_UINT32(filter_enabled, NRF51RNGState), | ||
362 | + VMSTATE_END_OF_LIST() | ||
363 | + } | ||
364 | +}; | ||
365 | + | ||
366 | +static void nrf51_rng_class_init(ObjectClass *klass, void *data) | ||
367 | +{ | ||
368 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
369 | + | ||
370 | + dc->props = nrf51_rng_properties; | ||
371 | + dc->vmsd = &vmstate_rng; | ||
372 | + dc->reset = nrf51_rng_reset; | ||
373 | +} | ||
374 | + | ||
375 | +static const TypeInfo nrf51_rng_info = { | ||
376 | + .name = TYPE_NRF51_RNG, | ||
377 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
378 | + .instance_size = sizeof(NRF51RNGState), | ||
379 | + .instance_init = nrf51_rng_init, | ||
380 | + .class_init = nrf51_rng_class_init | ||
381 | +}; | ||
382 | + | ||
383 | +static void nrf51_rng_register_types(void) | ||
384 | +{ | ||
385 | + type_register_static(&nrf51_rng_info); | ||
386 | +} | ||
387 | + | ||
388 | +type_init(nrf51_rng_register_types) | ||
389 | -- | ||
390 | 2.19.2 | ||
391 | |||
392 | diff view generated by jsdifflib |
1 | From: Francisco Iglesias <frasse.iglesias@gmail.com> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | Coverity found that the variable tx_rx in the function | 3 | Use RNG in SOC. |
4 | xilinx_spips_flush_txfifo was being used uninitialized (CID 1383841). This | ||
5 | patch corrects this by always initializing tx_rx to zeros. | ||
6 | 4 | ||
7 | Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com> | 5 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
8 | Message-id: 20180124215708.30400-1-frasse.iglesias@gmail.com | 6 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> |
9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
9 | Message-id: 20190103091119.9367-5-stefanha@redhat.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | --- | 11 | --- |
12 | hw/ssi/xilinx_spips.c | 18 +++++++++++++++++- | 12 | include/hw/arm/nrf51_soc.h | 2 ++ |
13 | 1 file changed, 17 insertions(+), 1 deletion(-) | 13 | hw/arm/nrf51_soc.c | 16 ++++++++++++++++ |
14 | 2 files changed, 18 insertions(+) | ||
14 | 15 | ||
15 | diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c | 16 | diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h |
16 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/hw/ssi/xilinx_spips.c | 18 | --- a/include/hw/arm/nrf51_soc.h |
18 | +++ b/hw/ssi/xilinx_spips.c | 19 | +++ b/include/hw/arm/nrf51_soc.h |
19 | @@ -XXX,XX +XXX,XX @@ | 20 | @@ -XXX,XX +XXX,XX @@ |
20 | #define SNOOP_NONE 0xEE | 21 | #include "hw/sysbus.h" |
21 | #define SNOOP_STRIPING 0 | 22 | #include "hw/arm/armv7m.h" |
22 | 23 | #include "hw/char/nrf51_uart.h" | |
23 | +#define MIN_NUM_BUSSES 1 | 24 | +#include "hw/misc/nrf51_rng.h" |
24 | +#define MAX_NUM_BUSSES 2 | 25 | |
25 | + | 26 | #define TYPE_NRF51_SOC "nrf51-soc" |
26 | static inline int num_effective_busses(XilinxSPIPS *s) | 27 | #define NRF51_SOC(obj) \ |
27 | { | 28 | @@ -XXX,XX +XXX,XX @@ typedef struct NRF51State { |
28 | return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS && | 29 | ARMv7MState cpu; |
29 | @@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) | 30 | |
30 | for (;;) { | 31 | NRF51UARTState uart; |
31 | int i; | 32 | + NRF51RNGState rng; |
32 | uint8_t tx = 0; | 33 | |
33 | - uint8_t tx_rx[num_effective_busses(s)]; | 34 | MemoryRegion iomem; |
34 | + uint8_t tx_rx[MAX_NUM_BUSSES] = { 0 }; | 35 | MemoryRegion sram; |
35 | uint8_t dummy_cycles = 0; | 36 | diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c |
36 | uint8_t addr_length; | 37 | index XXXXXXX..XXXXXXX 100644 |
37 | 38 | --- a/hw/arm/nrf51_soc.c | |
38 | @@ -XXX,XX +XXX,XX @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp) | 39 | +++ b/hw/arm/nrf51_soc.c |
39 | 40 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | |
40 | DB_PRINT_L(0, "realized spips\n"); | 41 | qdev_get_gpio_in(DEVICE(&s->cpu), |
41 | 42 | BASE_TO_IRQ(NRF51_UART_BASE))); | |
42 | + if (s->num_busses > MAX_NUM_BUSSES) { | 43 | |
43 | + error_setg(errp, | 44 | + /* RNG */ |
44 | + "requested number of SPI busses %u exceeds maximum %d", | 45 | + object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); |
45 | + s->num_busses, MAX_NUM_BUSSES); | 46 | + if (err) { |
46 | + return; | 47 | + error_propagate(errp, err); |
47 | + } | ||
48 | + if (s->num_busses < MIN_NUM_BUSSES) { | ||
49 | + error_setg(errp, | ||
50 | + "requested number of SPI busses %u is below minimum %d", | ||
51 | + s->num_busses, MIN_NUM_BUSSES); | ||
52 | + return; | 48 | + return; |
53 | + } | 49 | + } |
54 | + | 50 | + |
55 | s->spi = g_new(SSIBus *, s->num_busses); | 51 | + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0); |
56 | for (i = 0; i < s->num_busses; ++i) { | 52 | + memory_region_add_subregion_overlap(&s->container, NRF51_RNG_BASE, mr, 0); |
57 | char bus_name[16]; | 53 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0, |
54 | + qdev_get_gpio_in(DEVICE(&s->cpu), | ||
55 | + BASE_TO_IRQ(NRF51_RNG_BASE))); | ||
56 | + | ||
57 | create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE, | ||
58 | NRF51_IOMEM_SIZE); | ||
59 | create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE, | ||
60 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj) | ||
61 | TYPE_NRF51_UART); | ||
62 | object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev", | ||
63 | &error_abort); | ||
64 | + | ||
65 | + sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), | ||
66 | + TYPE_NRF51_RNG); | ||
67 | } | ||
68 | |||
69 | static Property nrf51_soc_properties[] = { | ||
58 | -- | 70 | -- |
59 | 2.7.4 | 71 | 2.19.2 |
60 | 72 | ||
61 | 73 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> | |
2 | |||
3 | This adds a model of the nRF51 GPIO peripheral. | ||
4 | |||
5 | Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
6 | |||
7 | The nRF51 series microcontrollers support up to 32 GPIO pins in various configurations. | ||
8 | The pins can be used as input pins with pull-ups or pull-down. | ||
9 | Furthermore, three different output driver modes per level are | ||
10 | available (disconnected, standard, high-current). | ||
11 | |||
12 | The GPIO-Peripheral has a mechanism for detecting level changes which is | ||
13 | not featured in this model. | ||
14 | |||
15 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> | ||
16 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
17 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
19 | Message-id: 20190103091119.9367-6-stefanha@redhat.com | ||
20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
21 | --- | ||
22 | Makefile.objs | 1 + | ||
23 | hw/gpio/Makefile.objs | 1 + | ||
24 | include/hw/gpio/nrf51_gpio.h | 69 ++++++++ | ||
25 | hw/gpio/nrf51_gpio.c | 300 +++++++++++++++++++++++++++++++++++ | ||
26 | hw/gpio/trace-events | 7 + | ||
27 | 5 files changed, 378 insertions(+) | ||
28 | create mode 100644 include/hw/gpio/nrf51_gpio.h | ||
29 | create mode 100644 hw/gpio/nrf51_gpio.c | ||
30 | create mode 100644 hw/gpio/trace-events | ||
31 | |||
32 | diff --git a/Makefile.objs b/Makefile.objs | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/Makefile.objs | ||
35 | +++ b/Makefile.objs | ||
36 | @@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/vfio | ||
37 | trace-events-subdirs += hw/virtio | ||
38 | trace-events-subdirs += hw/watchdog | ||
39 | trace-events-subdirs += hw/xen | ||
40 | +trace-events-subdirs += hw/gpio | ||
41 | trace-events-subdirs += io | ||
42 | trace-events-subdirs += linux-user | ||
43 | trace-events-subdirs += migration | ||
44 | diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs | ||
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/hw/gpio/Makefile.objs | ||
47 | +++ b/hw/gpio/Makefile.objs | ||
48 | @@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o | ||
49 | obj-$(CONFIG_OMAP) += omap_gpio.o | ||
50 | obj-$(CONFIG_IMX) += imx_gpio.o | ||
51 | obj-$(CONFIG_RASPI) += bcm2835_gpio.o | ||
52 | +obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o | ||
53 | diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h | ||
54 | new file mode 100644 | ||
55 | index XXXXXXX..XXXXXXX | ||
56 | --- /dev/null | ||
57 | +++ b/include/hw/gpio/nrf51_gpio.h | ||
58 | @@ -XXX,XX +XXX,XX @@ | ||
59 | +/* | ||
60 | + * nRF51 System-on-Chip general purpose input/output register definition | ||
61 | + * | ||
62 | + * QEMU interface: | ||
63 | + * + sysbus MMIO regions 0: GPIO registers | ||
64 | + * + Unnamed GPIO inputs 0-31: Set tri-state input level for GPIO pin. | ||
65 | + * Level -1: Externally Disconnected/Floating; Pull-up/down will be regarded | ||
66 | + * Level 0: Input externally driven LOW | ||
67 | + * Level 1: Input externally driven HIGH | ||
68 | + * + Unnamed GPIO outputs 0-31: | ||
69 | + * Level -1: Disconnected/Floating | ||
70 | + * Level 0: Driven LOW | ||
71 | + * Level 1: Driven HIGH | ||
72 | + * | ||
73 | + * Accuracy of the peripheral model: | ||
74 | + * + The nRF51 GPIO output driver supports two modes, standard and high-current | ||
75 | + * mode. These different drive modes are not modeled and handled the same. | ||
76 | + * + Pin SENSEing is not modeled/implemented. | ||
77 | + * | ||
78 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
79 | + * | ||
80 | + * This code is licensed under the GPL version 2 or later. See | ||
81 | + * the COPYING file in the top-level directory. | ||
82 | + * | ||
83 | + */ | ||
84 | +#ifndef NRF51_GPIO_H | ||
85 | +#define NRF51_GPIO_H | ||
86 | + | ||
87 | +#include "hw/sysbus.h" | ||
88 | +#define TYPE_NRF51_GPIO "nrf51_soc.gpio" | ||
89 | +#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO) | ||
90 | + | ||
91 | +#define NRF51_GPIO_PINS 32 | ||
92 | + | ||
93 | +#define NRF51_GPIO_SIZE 0x1000 | ||
94 | + | ||
95 | +#define NRF51_GPIO_REG_OUT 0x504 | ||
96 | +#define NRF51_GPIO_REG_OUTSET 0x508 | ||
97 | +#define NRF51_GPIO_REG_OUTCLR 0x50C | ||
98 | +#define NRF51_GPIO_REG_IN 0x510 | ||
99 | +#define NRF51_GPIO_REG_DIR 0x514 | ||
100 | +#define NRF51_GPIO_REG_DIRSET 0x518 | ||
101 | +#define NRF51_GPIO_REG_DIRCLR 0x51C | ||
102 | +#define NRF51_GPIO_REG_CNF_START 0x700 | ||
103 | +#define NRF51_GPIO_REG_CNF_END 0x77F | ||
104 | + | ||
105 | +#define NRF51_GPIO_PULLDOWN 1 | ||
106 | +#define NRF51_GPIO_PULLUP 3 | ||
107 | + | ||
108 | +typedef struct NRF51GPIOState { | ||
109 | + SysBusDevice parent_obj; | ||
110 | + | ||
111 | + MemoryRegion mmio; | ||
112 | + qemu_irq irq; | ||
113 | + | ||
114 | + uint32_t out; | ||
115 | + uint32_t in; | ||
116 | + uint32_t in_mask; | ||
117 | + uint32_t dir; | ||
118 | + uint32_t cnf[NRF51_GPIO_PINS]; | ||
119 | + | ||
120 | + uint32_t old_out; | ||
121 | + uint32_t old_out_connected; | ||
122 | + | ||
123 | + qemu_irq output[NRF51_GPIO_PINS]; | ||
124 | +} NRF51GPIOState; | ||
125 | + | ||
126 | + | ||
127 | +#endif | ||
128 | diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c | ||
129 | new file mode 100644 | ||
130 | index XXXXXXX..XXXXXXX | ||
131 | --- /dev/null | ||
132 | +++ b/hw/gpio/nrf51_gpio.c | ||
133 | @@ -XXX,XX +XXX,XX @@ | ||
134 | +/* | ||
135 | + * nRF51 System-on-Chip general purpose input/output register definition | ||
136 | + * | ||
137 | + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
138 | + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf | ||
139 | + * | ||
140 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
141 | + * | ||
142 | + * This code is licensed under the GPL version 2 or later. See | ||
143 | + * the COPYING file in the top-level directory. | ||
144 | + */ | ||
145 | + | ||
146 | +#include "qemu/osdep.h" | ||
147 | +#include "qemu/log.h" | ||
148 | +#include "hw/gpio/nrf51_gpio.h" | ||
149 | +#include "trace.h" | ||
150 | + | ||
151 | +/* | ||
152 | + * Check if the output driver is connected to the direction switch | ||
153 | + * given the current configuration and logic level. | ||
154 | + * It is not differentiated between standard and "high"(-power) drive modes. | ||
155 | + */ | ||
156 | +static bool is_connected(uint32_t config, uint32_t level) | ||
157 | +{ | ||
158 | + bool state; | ||
159 | + uint32_t drive_config = extract32(config, 8, 3); | ||
160 | + | ||
161 | + switch (drive_config) { | ||
162 | + case 0 ... 3: | ||
163 | + state = true; | ||
164 | + break; | ||
165 | + case 4 ... 5: | ||
166 | + state = level != 0; | ||
167 | + break; | ||
168 | + case 6 ... 7: | ||
169 | + state = level == 0; | ||
170 | + break; | ||
171 | + default: | ||
172 | + g_assert_not_reached(); | ||
173 | + break; | ||
174 | + } | ||
175 | + | ||
176 | + return state; | ||
177 | +} | ||
178 | + | ||
179 | +static void update_output_irq(NRF51GPIOState *s, size_t i, | ||
180 | + bool connected, bool level) | ||
181 | +{ | ||
182 | + int64_t irq_level = connected ? level : -1; | ||
183 | + bool old_connected = extract32(s->old_out_connected, i, 1); | ||
184 | + bool old_level = extract32(s->old_out, i, 1); | ||
185 | + | ||
186 | + if ((old_connected != connected) || (old_level != level)) { | ||
187 | + qemu_set_irq(s->output[i], irq_level); | ||
188 | + trace_nrf51_gpio_update_output_irq(i, irq_level); | ||
189 | + } | ||
190 | + | ||
191 | + s->old_out = deposit32(s->old_out, i, 1, level); | ||
192 | + s->old_out_connected = deposit32(s->old_out_connected, i, 1, connected); | ||
193 | +} | ||
194 | + | ||
195 | +static void update_state(NRF51GPIOState *s) | ||
196 | +{ | ||
197 | + uint32_t pull; | ||
198 | + size_t i; | ||
199 | + bool connected_out, dir, connected_in, out, input; | ||
200 | + | ||
201 | + for (i = 0; i < NRF51_GPIO_PINS; i++) { | ||
202 | + pull = extract32(s->cnf[i], 2, 2); | ||
203 | + dir = extract32(s->cnf[i], 0, 1); | ||
204 | + connected_in = extract32(s->in_mask, i, 1); | ||
205 | + out = extract32(s->out, i, 1); | ||
206 | + input = !extract32(s->cnf[i], 1, 1); | ||
207 | + connected_out = is_connected(s->cnf[i], out) && dir; | ||
208 | + | ||
209 | + update_output_irq(s, i, connected_out, out); | ||
210 | + | ||
211 | + /* Pin both driven externally and internally */ | ||
212 | + if (connected_out && connected_in) { | ||
213 | + qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i); | ||
214 | + } | ||
215 | + | ||
216 | + /* | ||
217 | + * Input buffer disconnected from internal/external drives, so | ||
218 | + * pull-up/pull-down becomes relevant | ||
219 | + */ | ||
220 | + if (!input || (input && !connected_in && !connected_out)) { | ||
221 | + if (pull == NRF51_GPIO_PULLDOWN) { | ||
222 | + s->in = deposit32(s->in, i, 1, 0); | ||
223 | + } else if (pull == NRF51_GPIO_PULLUP) { | ||
224 | + s->in = deposit32(s->in, i, 1, 1); | ||
225 | + } | ||
226 | + } | ||
227 | + | ||
228 | + /* Self stimulation through internal output driver */ | ||
229 | + if (connected_out && !connected_in && input) { | ||
230 | + s->in = deposit32(s->in, i, 1, out); | ||
231 | + } | ||
232 | + } | ||
233 | + | ||
234 | +} | ||
235 | + | ||
236 | +/* | ||
237 | + * Direction is exposed in both the DIR register and the DIR bit | ||
238 | + * of each PINs CNF configuration register. Reflect bits for pins in DIR | ||
239 | + * to individual pin configuration registers. | ||
240 | + */ | ||
241 | +static void reflect_dir_bit_in_cnf(NRF51GPIOState *s) | ||
242 | +{ | ||
243 | + size_t i; | ||
244 | + | ||
245 | + uint32_t value = s->dir; | ||
246 | + | ||
247 | + for (i = 0; i < NRF51_GPIO_PINS; i++) { | ||
248 | + s->cnf[i] = (s->cnf[i] & ~(1UL)) | ((value >> i) & 0x01); | ||
249 | + } | ||
250 | +} | ||
251 | + | ||
252 | +static uint64_t nrf51_gpio_read(void *opaque, hwaddr offset, unsigned int size) | ||
253 | +{ | ||
254 | + NRF51GPIOState *s = NRF51_GPIO(opaque); | ||
255 | + uint64_t r = 0; | ||
256 | + size_t idx; | ||
257 | + | ||
258 | + switch (offset) { | ||
259 | + case NRF51_GPIO_REG_OUT ... NRF51_GPIO_REG_OUTCLR: | ||
260 | + r = s->out; | ||
261 | + break; | ||
262 | + | ||
263 | + case NRF51_GPIO_REG_IN: | ||
264 | + r = s->in; | ||
265 | + break; | ||
266 | + | ||
267 | + case NRF51_GPIO_REG_DIR ... NRF51_GPIO_REG_DIRCLR: | ||
268 | + r = s->dir; | ||
269 | + break; | ||
270 | + | ||
271 | + case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END: | ||
272 | + idx = (offset - NRF51_GPIO_REG_CNF_START) / 4; | ||
273 | + r = s->cnf[idx]; | ||
274 | + break; | ||
275 | + | ||
276 | + default: | ||
277 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
278 | + "%s: bad read offset 0x%" HWADDR_PRIx "\n", | ||
279 | + __func__, offset); | ||
280 | + } | ||
281 | + | ||
282 | + trace_nrf51_gpio_read(offset, r); | ||
283 | + | ||
284 | + return r; | ||
285 | +} | ||
286 | + | ||
287 | +static void nrf51_gpio_write(void *opaque, hwaddr offset, | ||
288 | + uint64_t value, unsigned int size) | ||
289 | +{ | ||
290 | + NRF51GPIOState *s = NRF51_GPIO(opaque); | ||
291 | + size_t idx; | ||
292 | + | ||
293 | + trace_nrf51_gpio_write(offset, value); | ||
294 | + | ||
295 | + switch (offset) { | ||
296 | + case NRF51_GPIO_REG_OUT: | ||
297 | + s->out = value; | ||
298 | + break; | ||
299 | + | ||
300 | + case NRF51_GPIO_REG_OUTSET: | ||
301 | + s->out |= value; | ||
302 | + break; | ||
303 | + | ||
304 | + case NRF51_GPIO_REG_OUTCLR: | ||
305 | + s->out &= ~value; | ||
306 | + break; | ||
307 | + | ||
308 | + case NRF51_GPIO_REG_DIR: | ||
309 | + s->dir = value; | ||
310 | + reflect_dir_bit_in_cnf(s); | ||
311 | + break; | ||
312 | + | ||
313 | + case NRF51_GPIO_REG_DIRSET: | ||
314 | + s->dir |= value; | ||
315 | + reflect_dir_bit_in_cnf(s); | ||
316 | + break; | ||
317 | + | ||
318 | + case NRF51_GPIO_REG_DIRCLR: | ||
319 | + s->dir &= ~value; | ||
320 | + reflect_dir_bit_in_cnf(s); | ||
321 | + break; | ||
322 | + | ||
323 | + case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END: | ||
324 | + idx = (offset - NRF51_GPIO_REG_CNF_START) / 4; | ||
325 | + s->cnf[idx] = value; | ||
326 | + /* | ||
327 | + * direction is exposed in both the DIR register and the DIR bit | ||
328 | + * of each PINs CNF configuration register. | ||
329 | + */ | ||
330 | + s->dir = (s->dir & ~(1UL << idx)) | ((value & 0x01) << idx); | ||
331 | + break; | ||
332 | + | ||
333 | + default: | ||
334 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
335 | + "%s: bad write offset 0x%" HWADDR_PRIx "\n", | ||
336 | + __func__, offset); | ||
337 | + } | ||
338 | + | ||
339 | + update_state(s); | ||
340 | +} | ||
341 | + | ||
342 | +static const MemoryRegionOps gpio_ops = { | ||
343 | + .read = nrf51_gpio_read, | ||
344 | + .write = nrf51_gpio_write, | ||
345 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
346 | + .impl.min_access_size = 4, | ||
347 | + .impl.max_access_size = 4, | ||
348 | +}; | ||
349 | + | ||
350 | +static void nrf51_gpio_set(void *opaque, int line, int value) | ||
351 | +{ | ||
352 | + NRF51GPIOState *s = NRF51_GPIO(opaque); | ||
353 | + | ||
354 | + trace_nrf51_gpio_set(line, value); | ||
355 | + | ||
356 | + assert(line >= 0 && line < NRF51_GPIO_PINS); | ||
357 | + | ||
358 | + s->in_mask = deposit32(s->in_mask, line, 1, value >= 0); | ||
359 | + if (value >= 0) { | ||
360 | + s->in = deposit32(s->in, line, 1, value != 0); | ||
361 | + } | ||
362 | + | ||
363 | + update_state(s); | ||
364 | +} | ||
365 | + | ||
366 | +static void nrf51_gpio_reset(DeviceState *dev) | ||
367 | +{ | ||
368 | + NRF51GPIOState *s = NRF51_GPIO(dev); | ||
369 | + size_t i; | ||
370 | + | ||
371 | + s->out = 0; | ||
372 | + s->old_out = 0; | ||
373 | + s->old_out_connected = 0; | ||
374 | + s->in = 0; | ||
375 | + s->in_mask = 0; | ||
376 | + s->dir = 0; | ||
377 | + | ||
378 | + for (i = 0; i < NRF51_GPIO_PINS; i++) { | ||
379 | + s->cnf[i] = 0x00000002; | ||
380 | + } | ||
381 | +} | ||
382 | + | ||
383 | +static const VMStateDescription vmstate_nrf51_gpio = { | ||
384 | + .name = TYPE_NRF51_GPIO, | ||
385 | + .version_id = 1, | ||
386 | + .minimum_version_id = 1, | ||
387 | + .fields = (VMStateField[]) { | ||
388 | + VMSTATE_UINT32(out, NRF51GPIOState), | ||
389 | + VMSTATE_UINT32(in, NRF51GPIOState), | ||
390 | + VMSTATE_UINT32(in_mask, NRF51GPIOState), | ||
391 | + VMSTATE_UINT32(dir, NRF51GPIOState), | ||
392 | + VMSTATE_UINT32_ARRAY(cnf, NRF51GPIOState, NRF51_GPIO_PINS), | ||
393 | + VMSTATE_UINT32(old_out, NRF51GPIOState), | ||
394 | + VMSTATE_UINT32(old_out_connected, NRF51GPIOState), | ||
395 | + VMSTATE_END_OF_LIST() | ||
396 | + } | ||
397 | +}; | ||
398 | + | ||
399 | +static void nrf51_gpio_init(Object *obj) | ||
400 | +{ | ||
401 | + NRF51GPIOState *s = NRF51_GPIO(obj); | ||
402 | + | ||
403 | + memory_region_init_io(&s->mmio, obj, &gpio_ops, s, | ||
404 | + TYPE_NRF51_GPIO, NRF51_GPIO_SIZE); | ||
405 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); | ||
406 | + | ||
407 | + qdev_init_gpio_in(DEVICE(s), nrf51_gpio_set, NRF51_GPIO_PINS); | ||
408 | + qdev_init_gpio_out(DEVICE(s), s->output, NRF51_GPIO_PINS); | ||
409 | +} | ||
410 | + | ||
411 | +static void nrf51_gpio_class_init(ObjectClass *klass, void *data) | ||
412 | +{ | ||
413 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
414 | + | ||
415 | + dc->vmsd = &vmstate_nrf51_gpio; | ||
416 | + dc->reset = nrf51_gpio_reset; | ||
417 | + dc->desc = "nRF51 GPIO"; | ||
418 | +} | ||
419 | + | ||
420 | +static const TypeInfo nrf51_gpio_info = { | ||
421 | + .name = TYPE_NRF51_GPIO, | ||
422 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
423 | + .instance_size = sizeof(NRF51GPIOState), | ||
424 | + .instance_init = nrf51_gpio_init, | ||
425 | + .class_init = nrf51_gpio_class_init | ||
426 | +}; | ||
427 | + | ||
428 | +static void nrf51_gpio_register_types(void) | ||
429 | +{ | ||
430 | + type_register_static(&nrf51_gpio_info); | ||
431 | +} | ||
432 | + | ||
433 | +type_init(nrf51_gpio_register_types) | ||
434 | diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events | ||
435 | new file mode 100644 | ||
436 | index XXXXXXX..XXXXXXX | ||
437 | --- /dev/null | ||
438 | +++ b/hw/gpio/trace-events | ||
439 | @@ -XXX,XX +XXX,XX @@ | ||
440 | +# See docs/devel/tracing.txt for syntax documentation. | ||
441 | + | ||
442 | +# hw/gpio/nrf51_gpio.c | ||
443 | +nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 | ||
444 | +nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 | ||
445 | +nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 | ||
446 | +nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 | ||
447 | \ No newline at end of file | ||
448 | -- | ||
449 | 2.19.2 | ||
450 | |||
451 | diff view generated by jsdifflib |
1 | From: Luc MICHEL <luc.michel@git.antfield.fr> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | When there is no active interrupts in the GIC, a read to the C_RPR | 3 | Instantiates GPIO peripheral model |
4 | register should return the value of the "Idle priority", which is either | ||
5 | the maximum value an IRQ priority field can be set to, or 0xff. | ||
6 | 4 | ||
7 | Since the QEMU GIC model implements all the 8 priority bits, the Idle | 5 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
8 | priority is 0xff. | 6 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> |
9 | |||
10 | Internally, when there is no active interrupt, the running priority | ||
11 | value is 0x100. The gic_get_running_priority function returns an uint8_t | ||
12 | and thus, truncate this value to 0x00 when returning it. This is wrong since | ||
13 | a value of 0x00 correspond to the maximum possible priority. | ||
14 | |||
15 | This commit fixes the returned value when the internal value is 0x100. | ||
16 | |||
17 | Note that it is correct for the Non-Secure view to return 0xff even | ||
18 | though from the NS world point of view, only 7 priority bits are | ||
19 | implemented. The specification states that the Idle priority can be 0xff | ||
20 | even when not all the 8 priority bits are implemented. This has been | ||
21 | verified against a real GICv2 hardware on a Xilinx ZynqMP based board. | ||
22 | |||
23 | Regarding the ARM11MPCore version of the GIC, the specification is not | ||
24 | clear on that point, so this commit does not alter its behavior. | ||
25 | |||
26 | Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr> | ||
27 | Message-id: 20180119145756.7629-4-luc.michel@greensocs.com | ||
28 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
9 | Message-id: 20190103091119.9367-7-stefanha@redhat.com | ||
29 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
30 | --- | 11 | --- |
31 | hw/intc/arm_gic.c | 5 +++++ | 12 | include/hw/arm/nrf51_soc.h | 2 ++ |
32 | 1 file changed, 5 insertions(+) | 13 | hw/arm/nrf51_soc.c | 16 ++++++++++++++++ |
14 | 2 files changed, 18 insertions(+) | ||
33 | 15 | ||
34 | diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c | 16 | diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h |
35 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
36 | --- a/hw/intc/arm_gic.c | 18 | --- a/include/hw/arm/nrf51_soc.h |
37 | +++ b/hw/intc/arm_gic.c | 19 | +++ b/include/hw/arm/nrf51_soc.h |
38 | @@ -XXX,XX +XXX,XX @@ static void gic_set_cpu_control(GICState *s, int cpu, uint32_t value, | 20 | @@ -XXX,XX +XXX,XX @@ |
39 | 21 | #include "hw/arm/armv7m.h" | |
40 | static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs) | 22 | #include "hw/char/nrf51_uart.h" |
41 | { | 23 | #include "hw/misc/nrf51_rng.h" |
42 | + if ((s->revision != REV_11MPCORE) && (s->running_priority[cpu] > 0xff)) { | 24 | +#include "hw/gpio/nrf51_gpio.h" |
43 | + /* Idle priority */ | 25 | |
44 | + return 0xff; | 26 | #define TYPE_NRF51_SOC "nrf51-soc" |
27 | #define NRF51_SOC(obj) \ | ||
28 | @@ -XXX,XX +XXX,XX @@ typedef struct NRF51State { | ||
29 | |||
30 | NRF51UARTState uart; | ||
31 | NRF51RNGState rng; | ||
32 | + NRF51GPIOState gpio; | ||
33 | |||
34 | MemoryRegion iomem; | ||
35 | MemoryRegion sram; | ||
36 | diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/hw/arm/nrf51_soc.c | ||
39 | +++ b/hw/arm/nrf51_soc.c | ||
40 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
41 | qdev_get_gpio_in(DEVICE(&s->cpu), | ||
42 | BASE_TO_IRQ(NRF51_RNG_BASE))); | ||
43 | |||
44 | + /* GPIO */ | ||
45 | + object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); | ||
46 | + if (err) { | ||
47 | + error_propagate(errp, err); | ||
48 | + return; | ||
45 | + } | 49 | + } |
46 | + | 50 | + |
47 | if (s->security_extn && !attrs.secure) { | 51 | + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0); |
48 | if (s->running_priority[cpu] & 0x80) { | 52 | + memory_region_add_subregion_overlap(&s->container, NRF51_GPIO_BASE, mr, 0); |
49 | /* Running priority in upper half of range: return the Non-secure | 53 | + |
54 | + /* Pass all GPIOs to the SOC layer so they are available to the board */ | ||
55 | + qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL); | ||
56 | + | ||
57 | create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE, | ||
58 | NRF51_IOMEM_SIZE); | ||
59 | create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE, | ||
60 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj) | ||
61 | |||
62 | sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), | ||
63 | TYPE_NRF51_RNG); | ||
64 | + | ||
65 | + sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio), | ||
66 | + TYPE_NRF51_GPIO); | ||
67 | } | ||
68 | |||
69 | static Property nrf51_soc_properties[] = { | ||
50 | -- | 70 | -- |
51 | 2.7.4 | 71 | 2.19.2 |
52 | 72 | ||
53 | 73 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> | |
2 | |||
3 | The test suite for the nRF51 GPIO peripheral for now | ||
4 | only tests initial state. Additionally a set of | ||
5 | tests testing an implementation detail of the model | ||
6 | are included. | ||
7 | |||
8 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> | ||
9 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
10 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | Message-id: 20190103091119.9367-8-stefanha@redhat.com | ||
12 | [PMM: fixed stray space at start of file] | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | --- | ||
15 | tests/Makefile.include | 2 + | ||
16 | tests/microbit-test.c | 160 +++++++++++++++++++++++++++++++++++++++++ | ||
17 | 2 files changed, 162 insertions(+) | ||
18 | create mode 100644 tests/microbit-test.c | ||
19 | |||
20 | diff --git a/tests/Makefile.include b/tests/Makefile.include | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/tests/Makefile.include | ||
23 | +++ b/tests/Makefile.include | ||
24 | @@ -XXX,XX +XXX,XX @@ check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF) | ||
25 | check-qtest-arm-y += tests/tmp105-test$(EXESUF) | ||
26 | check-qtest-arm-y += tests/pca9552-test$(EXESUF) | ||
27 | check-qtest-arm-y += tests/ds1338-test$(EXESUF) | ||
28 | +check-qtest-arm-y += tests/microbit-test$(EXESUF) | ||
29 | check-qtest-arm-y += tests/m25p80-test$(EXESUF) | ||
30 | check-qtest-arm-y += tests/virtio-blk-test$(EXESUF) | ||
31 | check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) | ||
32 | @@ -XXX,XX +XXX,XX @@ tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) | ||
33 | tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) | ||
34 | tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y) | ||
35 | tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y) | ||
36 | +tests/microbit-test$(EXESUF): tests/microbit-test.o | ||
37 | tests/m25p80-test$(EXESUF): tests/m25p80-test.o | ||
38 | tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) | ||
39 | tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y) | ||
40 | diff --git a/tests/microbit-test.c b/tests/microbit-test.c | ||
41 | new file mode 100644 | ||
42 | index XXXXXXX..XXXXXXX | ||
43 | --- /dev/null | ||
44 | +++ b/tests/microbit-test.c | ||
45 | @@ -XXX,XX +XXX,XX @@ | ||
46 | +/* | ||
47 | + * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC. | ||
48 | + * | ||
49 | + * nRF51: | ||
50 | + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
51 | + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf | ||
52 | + * | ||
53 | + * Microbit Board: http://microbit.org/ | ||
54 | + * | ||
55 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
56 | + * | ||
57 | + * This code is licensed under the GPL version 2 or later. See | ||
58 | + * the COPYING file in the top-level directory. | ||
59 | + */ | ||
60 | + | ||
61 | + | ||
62 | +#include "qemu/osdep.h" | ||
63 | +#include "exec/hwaddr.h" | ||
64 | +#include "libqtest.h" | ||
65 | + | ||
66 | +#include "hw/arm/nrf51.h" | ||
67 | +#include "hw/gpio/nrf51_gpio.h" | ||
68 | + | ||
69 | +static void test_nrf51_gpio(void) | ||
70 | +{ | ||
71 | + size_t i; | ||
72 | + uint32_t actual, expected; | ||
73 | + | ||
74 | + struct { | ||
75 | + hwaddr addr; | ||
76 | + uint32_t expected; | ||
77 | + } const reset_state[] = { | ||
78 | + {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000}, | ||
79 | + {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000}, | ||
80 | + {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000}, | ||
81 | + {NRF51_GPIO_REG_DIRCLR, 0x00000000} | ||
82 | + }; | ||
83 | + | ||
84 | + /* Check reset state */ | ||
85 | + for (i = 0; i < ARRAY_SIZE(reset_state); i++) { | ||
86 | + expected = reset_state[i].expected; | ||
87 | + actual = readl(NRF51_GPIO_BASE + reset_state[i].addr); | ||
88 | + g_assert_cmpuint(actual, ==, expected); | ||
89 | + } | ||
90 | + | ||
91 | + for (i = 0; i < NRF51_GPIO_PINS; i++) { | ||
92 | + expected = 0x00000002; | ||
93 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4); | ||
94 | + g_assert_cmpuint(actual, ==, expected); | ||
95 | + } | ||
96 | + | ||
97 | + /* Check dir bit consistency between dir and cnf */ | ||
98 | + /* Check set via DIRSET */ | ||
99 | + expected = 0x80000001; | ||
100 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected); | ||
101 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); | ||
102 | + g_assert_cmpuint(actual, ==, expected); | ||
103 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; | ||
104 | + g_assert_cmpuint(actual, ==, 0x01); | ||
105 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; | ||
106 | + g_assert_cmpuint(actual, ==, 0x01); | ||
107 | + | ||
108 | + /* Check clear via DIRCLR */ | ||
109 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001); | ||
110 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); | ||
111 | + g_assert_cmpuint(actual, ==, 0x00000000); | ||
112 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; | ||
113 | + g_assert_cmpuint(actual, ==, 0x00); | ||
114 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; | ||
115 | + g_assert_cmpuint(actual, ==, 0x00); | ||
116 | + | ||
117 | + /* Check set via DIR */ | ||
118 | + expected = 0x80000001; | ||
119 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected); | ||
120 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); | ||
121 | + g_assert_cmpuint(actual, ==, expected); | ||
122 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; | ||
123 | + g_assert_cmpuint(actual, ==, 0x01); | ||
124 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; | ||
125 | + g_assert_cmpuint(actual, ==, 0x01); | ||
126 | + | ||
127 | + /* Reset DIR */ | ||
128 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000); | ||
129 | + | ||
130 | + /* Check Input propagates */ | ||
131 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00); | ||
132 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); | ||
133 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
134 | + g_assert_cmpuint(actual, ==, 0x00); | ||
135 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1); | ||
136 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
137 | + g_assert_cmpuint(actual, ==, 0x01); | ||
138 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1); | ||
139 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
140 | + g_assert_cmpuint(actual, ==, 0x01); | ||
141 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); | ||
142 | + | ||
143 | + /* Check pull-up working */ | ||
144 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); | ||
145 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000); | ||
146 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
147 | + g_assert_cmpuint(actual, ==, 0x00); | ||
148 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110); | ||
149 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
150 | + g_assert_cmpuint(actual, ==, 0x01); | ||
151 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); | ||
152 | + | ||
153 | + /* Check pull-down working */ | ||
154 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1); | ||
155 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000); | ||
156 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
157 | + g_assert_cmpuint(actual, ==, 0x01); | ||
158 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110); | ||
159 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
160 | + g_assert_cmpuint(actual, ==, 0x00); | ||
161 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); | ||
162 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1); | ||
163 | + | ||
164 | + /* Check Output propagates */ | ||
165 | + irq_intercept_out("/machine/nrf51"); | ||
166 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011); | ||
167 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); | ||
168 | + g_assert_true(get_irq(0)); | ||
169 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01); | ||
170 | + g_assert_false(get_irq(0)); | ||
171 | + | ||
172 | + /* Check self-stimulation */ | ||
173 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01); | ||
174 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); | ||
175 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
176 | + g_assert_cmpuint(actual, ==, 0x01); | ||
177 | + | ||
178 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01); | ||
179 | + actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; | ||
180 | + g_assert_cmpuint(actual, ==, 0x00); | ||
181 | + | ||
182 | + /* | ||
183 | + * Check short-circuit - generates an guest_error which must be checked | ||
184 | + * manually as long as qtest can not scan qemu_log messages | ||
185 | + */ | ||
186 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01); | ||
187 | + writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); | ||
188 | + qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); | ||
189 | +} | ||
190 | + | ||
191 | +int main(int argc, char **argv) | ||
192 | +{ | ||
193 | + int ret; | ||
194 | + | ||
195 | + g_test_init(&argc, &argv, NULL); | ||
196 | + | ||
197 | + global_qtest = qtest_initf("-machine microbit"); | ||
198 | + | ||
199 | + qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio); | ||
200 | + | ||
201 | + ret = g_test_run(); | ||
202 | + | ||
203 | + qtest_quit(global_qtest); | ||
204 | + return ret; | ||
205 | +} | ||
206 | -- | ||
207 | 2.19.2 | ||
208 | |||
209 | diff view generated by jsdifflib |
1 | From: Luc MICHEL <luc.michel@git.antfield.fr> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | In the GIC, when an IRQ is acknowledged, its state goes from "pending" | 3 | This patch adds the model for the nRF51 timer peripheral. |
4 | to: | 4 | Currently, only the TIMER mode is implemented. |
5 | - "active" if the corresponding IRQ pin has been de-asserted | ||
6 | - "active and pending" otherwise. | ||
7 | The GICv2 manual states that when a IRQ becomes active (or active and | ||
8 | pending), the GIC should either signal another (higher priority) IRQ to | ||
9 | the CPU if there is one, or de-assert the CPU IRQ pin. | ||
10 | 5 | ||
11 | The current implementation of the GIC in QEMU does not check if the | 6 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
12 | IRQ is already active when looking for pending interrupts with | 7 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
13 | sufficient priority in gic_update(). This can lead to signaling an | 8 | Message-id: 20190103091119.9367-9-stefanha@redhat.com |
14 | interrupt that is already active. | ||
15 | |||
16 | This usually happens when splitting priority drop and interrupt | ||
17 | deactivation. On priority drop, the IRQ stays active until deactivation. | ||
18 | If it becomes pending again, chances are that it will be incorrectly | ||
19 | selected as best_irq in gic_update(). | ||
20 | |||
21 | This commit fixes this by checking if the IRQ is not already active when | ||
22 | looking for best_irq in gic_update(). | ||
23 | |||
24 | Note that regarding the ARM11MPCore GIC version, the corresponding | ||
25 | manual is not clear on that point, but it has has no priority | ||
26 | drop/interrupt deactivation separation, so this case should not happen. | ||
27 | |||
28 | Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr> | ||
29 | Message-id: 20180119145756.7629-3-luc.michel@greensocs.com | ||
30 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
31 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
32 | --- | 11 | --- |
33 | hw/intc/arm_gic.c | 1 + | 12 | hw/timer/Makefile.objs | 1 + |
34 | 1 file changed, 1 insertion(+) | 13 | include/hw/timer/nrf51_timer.h | 80 +++++++ |
14 | hw/timer/nrf51_timer.c | 393 +++++++++++++++++++++++++++++++++ | ||
15 | hw/timer/trace-events | 5 + | ||
16 | 4 files changed, 479 insertions(+) | ||
17 | create mode 100644 include/hw/timer/nrf51_timer.h | ||
18 | create mode 100644 hw/timer/nrf51_timer.c | ||
35 | 19 | ||
36 | diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c | 20 | diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs |
37 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
38 | --- a/hw/intc/arm_gic.c | 22 | --- a/hw/timer/Makefile.objs |
39 | +++ b/hw/intc/arm_gic.c | 23 | +++ b/hw/timer/Makefile.objs |
40 | @@ -XXX,XX +XXX,XX @@ void gic_update(GICState *s) | 24 | @@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_gpt.o |
41 | best_irq = 1023; | 25 | common-obj-$(CONFIG_LM32) += lm32_timer.o |
42 | for (irq = 0; irq < s->num_irq; irq++) { | 26 | common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o |
43 | if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm) && | 27 | common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o |
44 | + (!GIC_TEST_ACTIVE(irq, cm)) && | 28 | +common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o |
45 | (irq < GIC_INTERNAL || GIC_TARGET(irq) & cm)) { | 29 | |
46 | if (GIC_GET_PRIORITY(irq, cpu) < best_prio) { | 30 | obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o |
47 | best_prio = GIC_GET_PRIORITY(irq, cpu); | 31 | obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o |
32 | diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h | ||
33 | new file mode 100644 | ||
34 | index XXXXXXX..XXXXXXX | ||
35 | --- /dev/null | ||
36 | +++ b/include/hw/timer/nrf51_timer.h | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | +/* | ||
39 | + * nRF51 System-on-Chip Timer peripheral | ||
40 | + * | ||
41 | + * QEMU interface: | ||
42 | + * + sysbus MMIO regions 0: GPIO registers | ||
43 | + * + sysbus irq | ||
44 | + * | ||
45 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
46 | + * | ||
47 | + * This code is licensed under the GPL version 2 or later. See | ||
48 | + * the COPYING file in the top-level directory. | ||
49 | + */ | ||
50 | +#ifndef NRF51_TIMER_H | ||
51 | +#define NRF51_TIMER_H | ||
52 | + | ||
53 | +#include "hw/sysbus.h" | ||
54 | +#include "qemu/timer.h" | ||
55 | +#define TYPE_NRF51_TIMER "nrf51_soc.timer" | ||
56 | +#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER) | ||
57 | + | ||
58 | +#define NRF51_TIMER_REG_COUNT 4 | ||
59 | + | ||
60 | +#define NRF51_TIMER_TASK_START 0x000 | ||
61 | +#define NRF51_TIMER_TASK_STOP 0x004 | ||
62 | +#define NRF51_TIMER_TASK_COUNT 0x008 | ||
63 | +#define NRF51_TIMER_TASK_CLEAR 0x00C | ||
64 | +#define NRF51_TIMER_TASK_SHUTDOWN 0x010 | ||
65 | +#define NRF51_TIMER_TASK_CAPTURE_0 0x040 | ||
66 | +#define NRF51_TIMER_TASK_CAPTURE_3 0x04C | ||
67 | + | ||
68 | +#define NRF51_TIMER_EVENT_COMPARE_0 0x140 | ||
69 | +#define NRF51_TIMER_EVENT_COMPARE_1 0x144 | ||
70 | +#define NRF51_TIMER_EVENT_COMPARE_2 0x148 | ||
71 | +#define NRF51_TIMER_EVENT_COMPARE_3 0x14C | ||
72 | + | ||
73 | +#define NRF51_TIMER_REG_SHORTS 0x200 | ||
74 | +#define NRF51_TIMER_REG_SHORTS_MASK 0xf0f | ||
75 | +#define NRF51_TIMER_REG_INTENSET 0x304 | ||
76 | +#define NRF51_TIMER_REG_INTENCLR 0x308 | ||
77 | +#define NRF51_TIMER_REG_INTEN_MASK 0xf0000 | ||
78 | +#define NRF51_TIMER_REG_MODE 0x504 | ||
79 | +#define NRF51_TIMER_REG_MODE_MASK 0x01 | ||
80 | +#define NRF51_TIMER_TIMER 0 | ||
81 | +#define NRF51_TIMER_COUNTER 1 | ||
82 | +#define NRF51_TIMER_REG_BITMODE 0x508 | ||
83 | +#define NRF51_TIMER_REG_BITMODE_MASK 0x03 | ||
84 | +#define NRF51_TIMER_WIDTH_16 0 | ||
85 | +#define NRF51_TIMER_WIDTH_8 1 | ||
86 | +#define NRF51_TIMER_WIDTH_24 2 | ||
87 | +#define NRF51_TIMER_WIDTH_32 3 | ||
88 | +#define NRF51_TIMER_REG_PRESCALER 0x510 | ||
89 | +#define NRF51_TIMER_REG_PRESCALER_MASK 0x0F | ||
90 | +#define NRF51_TIMER_REG_CC0 0x540 | ||
91 | +#define NRF51_TIMER_REG_CC3 0x54C | ||
92 | + | ||
93 | +typedef struct NRF51TimerState { | ||
94 | + SysBusDevice parent_obj; | ||
95 | + | ||
96 | + MemoryRegion iomem; | ||
97 | + qemu_irq irq; | ||
98 | + | ||
99 | + QEMUTimer timer; | ||
100 | + int64_t timer_start_ns; | ||
101 | + int64_t update_counter_ns; | ||
102 | + uint32_t counter; | ||
103 | + | ||
104 | + bool running; | ||
105 | + | ||
106 | + uint8_t events_compare[NRF51_TIMER_REG_COUNT]; | ||
107 | + uint32_t cc[NRF51_TIMER_REG_COUNT]; | ||
108 | + uint32_t shorts; | ||
109 | + uint32_t inten; | ||
110 | + uint32_t mode; | ||
111 | + uint32_t bitmode; | ||
112 | + uint32_t prescaler; | ||
113 | + | ||
114 | +} NRF51TimerState; | ||
115 | + | ||
116 | + | ||
117 | +#endif | ||
118 | diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c | ||
119 | new file mode 100644 | ||
120 | index XXXXXXX..XXXXXXX | ||
121 | --- /dev/null | ||
122 | +++ b/hw/timer/nrf51_timer.c | ||
123 | @@ -XXX,XX +XXX,XX @@ | ||
124 | +/* | ||
125 | + * nRF51 System-on-Chip Timer peripheral | ||
126 | + * | ||
127 | + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf | ||
128 | + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf | ||
129 | + * | ||
130 | + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> | ||
131 | + * Copyright (c) 2019 Red Hat, Inc. | ||
132 | + * | ||
133 | + * This code is licensed under the GPL version 2 or later. See | ||
134 | + * the COPYING file in the top-level directory. | ||
135 | + */ | ||
136 | + | ||
137 | +#include "qemu/osdep.h" | ||
138 | +#include "qemu/log.h" | ||
139 | +#include "hw/arm/nrf51.h" | ||
140 | +#include "hw/timer/nrf51_timer.h" | ||
141 | +#include "trace.h" | ||
142 | + | ||
143 | +#define TIMER_CLK_FREQ 16000000UL | ||
144 | + | ||
145 | +static uint32_t const bitwidths[] = {16, 8, 24, 32}; | ||
146 | + | ||
147 | +static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns) | ||
148 | +{ | ||
149 | + uint32_t freq = TIMER_CLK_FREQ >> s->prescaler; | ||
150 | + | ||
151 | + return muldiv64(ns, freq, NANOSECONDS_PER_SECOND); | ||
152 | +} | ||
153 | + | ||
154 | +static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks) | ||
155 | +{ | ||
156 | + uint32_t freq = TIMER_CLK_FREQ >> s->prescaler; | ||
157 | + | ||
158 | + return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq); | ||
159 | +} | ||
160 | + | ||
161 | +/* Returns number of ticks since last call */ | ||
162 | +static uint32_t update_counter(NRF51TimerState *s, int64_t now) | ||
163 | +{ | ||
164 | + uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns); | ||
165 | + | ||
166 | + s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]); | ||
167 | + s->update_counter_ns = now; | ||
168 | + return ticks; | ||
169 | +} | ||
170 | + | ||
171 | +/* Assumes s->counter is up-to-date */ | ||
172 | +static void rearm_timer(NRF51TimerState *s, int64_t now) | ||
173 | +{ | ||
174 | + int64_t min_ns = INT64_MAX; | ||
175 | + size_t i; | ||
176 | + | ||
177 | + for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) { | ||
178 | + int64_t delta_ns; | ||
179 | + | ||
180 | + if (s->events_compare[i]) { | ||
181 | + continue; /* already expired, ignore it for now */ | ||
182 | + } | ||
183 | + | ||
184 | + if (s->cc[i] <= s->counter) { | ||
185 | + delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) - | ||
186 | + s->counter + s->cc[i]); | ||
187 | + } else { | ||
188 | + delta_ns = ticks_to_ns(s, s->cc[i] - s->counter); | ||
189 | + } | ||
190 | + | ||
191 | + if (delta_ns < min_ns) { | ||
192 | + min_ns = delta_ns; | ||
193 | + } | ||
194 | + } | ||
195 | + | ||
196 | + if (min_ns != INT64_MAX) { | ||
197 | + timer_mod_ns(&s->timer, now + min_ns); | ||
198 | + } | ||
199 | +} | ||
200 | + | ||
201 | +static void update_irq(NRF51TimerState *s) | ||
202 | +{ | ||
203 | + bool flag = false; | ||
204 | + size_t i; | ||
205 | + | ||
206 | + for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) { | ||
207 | + flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1); | ||
208 | + } | ||
209 | + qemu_set_irq(s->irq, flag); | ||
210 | +} | ||
211 | + | ||
212 | +static void timer_expire(void *opaque) | ||
213 | +{ | ||
214 | + NRF51TimerState *s = NRF51_TIMER(opaque); | ||
215 | + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | ||
216 | + uint32_t cc_remaining[NRF51_TIMER_REG_COUNT]; | ||
217 | + bool should_stop = false; | ||
218 | + uint32_t ticks; | ||
219 | + size_t i; | ||
220 | + | ||
221 | + for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) { | ||
222 | + if (s->cc[i] > s->counter) { | ||
223 | + cc_remaining[i] = s->cc[i] - s->counter; | ||
224 | + } else { | ||
225 | + cc_remaining[i] = BIT(bitwidths[s->bitmode]) - | ||
226 | + s->counter + s->cc[i]; | ||
227 | + } | ||
228 | + } | ||
229 | + | ||
230 | + ticks = update_counter(s, now); | ||
231 | + | ||
232 | + for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) { | ||
233 | + if (cc_remaining[i] <= ticks) { | ||
234 | + s->events_compare[i] = 1; | ||
235 | + | ||
236 | + if (s->shorts & BIT(i)) { | ||
237 | + s->timer_start_ns = now; | ||
238 | + s->update_counter_ns = s->timer_start_ns; | ||
239 | + s->counter = 0; | ||
240 | + } | ||
241 | + | ||
242 | + should_stop |= s->shorts & BIT(i + 8); | ||
243 | + } | ||
244 | + } | ||
245 | + | ||
246 | + update_irq(s); | ||
247 | + | ||
248 | + if (should_stop) { | ||
249 | + s->running = false; | ||
250 | + timer_del(&s->timer); | ||
251 | + } else { | ||
252 | + rearm_timer(s, now); | ||
253 | + } | ||
254 | +} | ||
255 | + | ||
256 | +static void counter_compare(NRF51TimerState *s) | ||
257 | +{ | ||
258 | + uint32_t counter = s->counter; | ||
259 | + size_t i; | ||
260 | + | ||
261 | + for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) { | ||
262 | + if (counter == s->cc[i]) { | ||
263 | + s->events_compare[i] = 1; | ||
264 | + | ||
265 | + if (s->shorts & BIT(i)) { | ||
266 | + s->counter = 0; | ||
267 | + } | ||
268 | + } | ||
269 | + } | ||
270 | +} | ||
271 | + | ||
272 | +static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size) | ||
273 | +{ | ||
274 | + NRF51TimerState *s = NRF51_TIMER(opaque); | ||
275 | + uint64_t r = 0; | ||
276 | + | ||
277 | + switch (offset) { | ||
278 | + case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3: | ||
279 | + r = s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4]; | ||
280 | + break; | ||
281 | + case NRF51_TIMER_REG_SHORTS: | ||
282 | + r = s->shorts; | ||
283 | + break; | ||
284 | + case NRF51_TIMER_REG_INTENSET: | ||
285 | + r = s->inten; | ||
286 | + break; | ||
287 | + case NRF51_TIMER_REG_INTENCLR: | ||
288 | + r = s->inten; | ||
289 | + break; | ||
290 | + case NRF51_TIMER_REG_MODE: | ||
291 | + r = s->mode; | ||
292 | + break; | ||
293 | + case NRF51_TIMER_REG_BITMODE: | ||
294 | + r = s->bitmode; | ||
295 | + break; | ||
296 | + case NRF51_TIMER_REG_PRESCALER: | ||
297 | + r = s->prescaler; | ||
298 | + break; | ||
299 | + case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3: | ||
300 | + r = s->cc[(offset - NRF51_TIMER_REG_CC0) / 4]; | ||
301 | + break; | ||
302 | + default: | ||
303 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
304 | + "%s: bad read offset 0x%" HWADDR_PRIx "\n", | ||
305 | + __func__, offset); | ||
306 | + } | ||
307 | + | ||
308 | + trace_nrf51_timer_read(offset, r, size); | ||
309 | + | ||
310 | + return r; | ||
311 | +} | ||
312 | + | ||
313 | +static void nrf51_timer_write(void *opaque, hwaddr offset, | ||
314 | + uint64_t value, unsigned int size) | ||
315 | +{ | ||
316 | + NRF51TimerState *s = NRF51_TIMER(opaque); | ||
317 | + uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | ||
318 | + size_t idx; | ||
319 | + | ||
320 | + trace_nrf51_timer_write(offset, value, size); | ||
321 | + | ||
322 | + switch (offset) { | ||
323 | + case NRF51_TIMER_TASK_START: | ||
324 | + if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_TIMER) { | ||
325 | + s->running = true; | ||
326 | + s->timer_start_ns = now - ticks_to_ns(s, s->counter); | ||
327 | + s->update_counter_ns = s->timer_start_ns; | ||
328 | + rearm_timer(s, now); | ||
329 | + } | ||
330 | + break; | ||
331 | + case NRF51_TIMER_TASK_STOP: | ||
332 | + case NRF51_TIMER_TASK_SHUTDOWN: | ||
333 | + if (value == NRF51_TRIGGER_TASK) { | ||
334 | + s->running = false; | ||
335 | + timer_del(&s->timer); | ||
336 | + } | ||
337 | + break; | ||
338 | + case NRF51_TIMER_TASK_COUNT: | ||
339 | + if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) { | ||
340 | + s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]); | ||
341 | + counter_compare(s); | ||
342 | + } | ||
343 | + break; | ||
344 | + case NRF51_TIMER_TASK_CLEAR: | ||
345 | + if (value == NRF51_TRIGGER_TASK) { | ||
346 | + s->timer_start_ns = now; | ||
347 | + s->update_counter_ns = s->timer_start_ns; | ||
348 | + s->counter = 0; | ||
349 | + if (s->running) { | ||
350 | + rearm_timer(s, now); | ||
351 | + } | ||
352 | + } | ||
353 | + break; | ||
354 | + case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3: | ||
355 | + if (value == NRF51_TRIGGER_TASK) { | ||
356 | + if (s->running) { | ||
357 | + timer_expire(s); /* update counter and all state */ | ||
358 | + } | ||
359 | + | ||
360 | + idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4; | ||
361 | + s->cc[idx] = s->counter; | ||
362 | + } | ||
363 | + break; | ||
364 | + case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3: | ||
365 | + if (value == NRF51_EVENT_CLEAR) { | ||
366 | + s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0; | ||
367 | + | ||
368 | + if (s->running) { | ||
369 | + timer_expire(s); /* update counter and all state */ | ||
370 | + } | ||
371 | + } | ||
372 | + break; | ||
373 | + case NRF51_TIMER_REG_SHORTS: | ||
374 | + s->shorts = value & NRF51_TIMER_REG_SHORTS_MASK; | ||
375 | + break; | ||
376 | + case NRF51_TIMER_REG_INTENSET: | ||
377 | + s->inten |= value & NRF51_TIMER_REG_INTEN_MASK; | ||
378 | + break; | ||
379 | + case NRF51_TIMER_REG_INTENCLR: | ||
380 | + s->inten &= ~(value & NRF51_TIMER_REG_INTEN_MASK); | ||
381 | + break; | ||
382 | + case NRF51_TIMER_REG_MODE: | ||
383 | + s->mode = value; | ||
384 | + break; | ||
385 | + case NRF51_TIMER_REG_BITMODE: | ||
386 | + if (s->mode == NRF51_TIMER_TIMER && s->running) { | ||
387 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
388 | + "%s: erroneous change of BITMODE while timer is running\n", | ||
389 | + __func__); | ||
390 | + } | ||
391 | + s->bitmode = value & NRF51_TIMER_REG_BITMODE_MASK; | ||
392 | + break; | ||
393 | + case NRF51_TIMER_REG_PRESCALER: | ||
394 | + if (s->mode == NRF51_TIMER_TIMER && s->running) { | ||
395 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
396 | + "%s: erroneous change of PRESCALER while timer is running\n", | ||
397 | + __func__); | ||
398 | + } | ||
399 | + s->prescaler = value & NRF51_TIMER_REG_PRESCALER_MASK; | ||
400 | + break; | ||
401 | + case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3: | ||
402 | + if (s->running) { | ||
403 | + timer_expire(s); /* update counter */ | ||
404 | + } | ||
405 | + | ||
406 | + idx = (offset - NRF51_TIMER_REG_CC0) / 4; | ||
407 | + s->cc[idx] = value % BIT(bitwidths[s->bitmode]); | ||
408 | + | ||
409 | + if (s->running) { | ||
410 | + rearm_timer(s, now); | ||
411 | + } | ||
412 | + break; | ||
413 | + default: | ||
414 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
415 | + "%s: bad write offset 0x%" HWADDR_PRIx "\n", | ||
416 | + __func__, offset); | ||
417 | + } | ||
418 | + | ||
419 | + update_irq(s); | ||
420 | +} | ||
421 | + | ||
422 | +static const MemoryRegionOps rng_ops = { | ||
423 | + .read = nrf51_timer_read, | ||
424 | + .write = nrf51_timer_write, | ||
425 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
426 | + .impl.min_access_size = 4, | ||
427 | + .impl.max_access_size = 4, | ||
428 | +}; | ||
429 | + | ||
430 | +static void nrf51_timer_init(Object *obj) | ||
431 | +{ | ||
432 | + NRF51TimerState *s = NRF51_TIMER(obj); | ||
433 | + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
434 | + | ||
435 | + memory_region_init_io(&s->iomem, obj, &rng_ops, s, | ||
436 | + TYPE_NRF51_TIMER, NRF51_TIMER_SIZE); | ||
437 | + sysbus_init_mmio(sbd, &s->iomem); | ||
438 | + sysbus_init_irq(sbd, &s->irq); | ||
439 | + | ||
440 | + timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s); | ||
441 | +} | ||
442 | + | ||
443 | +static void nrf51_timer_reset(DeviceState *dev) | ||
444 | +{ | ||
445 | + NRF51TimerState *s = NRF51_TIMER(dev); | ||
446 | + | ||
447 | + timer_del(&s->timer); | ||
448 | + s->timer_start_ns = 0x00; | ||
449 | + s->update_counter_ns = 0x00; | ||
450 | + s->counter = 0x00; | ||
451 | + s->running = false; | ||
452 | + | ||
453 | + memset(s->events_compare, 0x00, sizeof(s->events_compare)); | ||
454 | + memset(s->cc, 0x00, sizeof(s->cc)); | ||
455 | + | ||
456 | + s->shorts = 0x00; | ||
457 | + s->inten = 0x00; | ||
458 | + s->mode = 0x00; | ||
459 | + s->bitmode = 0x00; | ||
460 | + s->prescaler = 0x00; | ||
461 | +} | ||
462 | + | ||
463 | +static int nrf51_timer_post_load(void *opaque, int version_id) | ||
464 | +{ | ||
465 | + NRF51TimerState *s = NRF51_TIMER(opaque); | ||
466 | + | ||
467 | + if (s->running && s->mode == NRF51_TIMER_TIMER) { | ||
468 | + timer_expire(s); | ||
469 | + } | ||
470 | + return 0; | ||
471 | +} | ||
472 | + | ||
473 | +static const VMStateDescription vmstate_nrf51_timer = { | ||
474 | + .name = TYPE_NRF51_TIMER, | ||
475 | + .version_id = 1, | ||
476 | + .post_load = nrf51_timer_post_load, | ||
477 | + .fields = (VMStateField[]) { | ||
478 | + VMSTATE_TIMER(timer, NRF51TimerState), | ||
479 | + VMSTATE_INT64(timer_start_ns, NRF51TimerState), | ||
480 | + VMSTATE_INT64(update_counter_ns, NRF51TimerState), | ||
481 | + VMSTATE_UINT32(counter, NRF51TimerState), | ||
482 | + VMSTATE_BOOL(running, NRF51TimerState), | ||
483 | + VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState, | ||
484 | + NRF51_TIMER_REG_COUNT), | ||
485 | + VMSTATE_UINT32_ARRAY(cc, NRF51TimerState, NRF51_TIMER_REG_COUNT), | ||
486 | + VMSTATE_UINT32(shorts, NRF51TimerState), | ||
487 | + VMSTATE_UINT32(inten, NRF51TimerState), | ||
488 | + VMSTATE_UINT32(mode, NRF51TimerState), | ||
489 | + VMSTATE_UINT32(bitmode, NRF51TimerState), | ||
490 | + VMSTATE_UINT32(prescaler, NRF51TimerState), | ||
491 | + VMSTATE_END_OF_LIST() | ||
492 | + } | ||
493 | +}; | ||
494 | + | ||
495 | +static void nrf51_timer_class_init(ObjectClass *klass, void *data) | ||
496 | +{ | ||
497 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
498 | + | ||
499 | + dc->reset = nrf51_timer_reset; | ||
500 | + dc->vmsd = &vmstate_nrf51_timer; | ||
501 | +} | ||
502 | + | ||
503 | +static const TypeInfo nrf51_timer_info = { | ||
504 | + .name = TYPE_NRF51_TIMER, | ||
505 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
506 | + .instance_size = sizeof(NRF51TimerState), | ||
507 | + .instance_init = nrf51_timer_init, | ||
508 | + .class_init = nrf51_timer_class_init | ||
509 | +}; | ||
510 | + | ||
511 | +static void nrf51_timer_register_types(void) | ||
512 | +{ | ||
513 | + type_register_static(&nrf51_timer_info); | ||
514 | +} | ||
515 | + | ||
516 | +type_init(nrf51_timer_register_types) | ||
517 | diff --git a/hw/timer/trace-events b/hw/timer/trace-events | ||
518 | index XXXXXXX..XXXXXXX 100644 | ||
519 | --- a/hw/timer/trace-events | ||
520 | +++ b/hw/timer/trace-events | ||
521 | @@ -XXX,XX +XXX,XX @@ sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value | ||
522 | |||
523 | # hw/timer/xlnx-zynqmp-rtc.c | ||
524 | xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d" | ||
525 | + | ||
526 | +# hw/timer/nrf51_timer.c | ||
527 | +nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" | ||
528 | +nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" | ||
529 | + | ||
48 | -- | 530 | -- |
49 | 2.7.4 | 531 | 2.19.2 |
50 | 532 | ||
51 | 533 | diff view generated by jsdifflib |
1 | From: Jean-Christophe Dubois <jcd@tribudubois.net> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | The actual imx_eth_enable_rx() function is buggy. | 3 | Instantiates TIMER0 - TIMER2 |
4 | 4 | ||
5 | It updates s->regs[ENET_RDAR] after calling qemu_flush_queued_packets(). | 5 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
6 | 6 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | |
7 | qemu_flush_queued_packets() is going to call imx_XXX_receive() which itself | ||
8 | is going to call imx_eth_enable_rx(). | ||
9 | |||
10 | By updating s->regs[ENET_RDAR] after calling qemu_flush_queued_packets() | ||
11 | we end up updating the register with an outdated value which might | ||
12 | lead to disabling the receive function in the i.MX FEC/ENET device. | ||
13 | |||
14 | This patch change the place where the register update is done so that the | ||
15 | register value stays up to date and the receive function can keep | ||
16 | running. | ||
17 | |||
18 | Reported-by: Fyleo <fyleo45@gmail.com> | ||
19 | Tested-by: Fyleo <fyleo45@gmail.com> | ||
20 | Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net> | ||
21 | Message-id: 20180113113445.2705-1-jcd@tribudubois.net | ||
22 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
23 | Reviewed-by: Andrey Smirnov <andrew.smirnov@gmail.com> | 8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
24 | Tested-by: Andrey Smirnov <andrew.smirnov@gmail.com> | 9 | Message-id: 20190103091119.9367-10-stefanha@redhat.com |
25 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
26 | --- | 11 | --- |
27 | hw/net/imx_fec.c | 8 ++------ | 12 | include/hw/arm/nrf51_soc.h | 4 ++++ |
28 | 1 file changed, 2 insertions(+), 6 deletions(-) | 13 | hw/arm/nrf51_soc.c | 26 ++++++++++++++++++++++++++ |
14 | 2 files changed, 30 insertions(+) | ||
29 | 15 | ||
30 | diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c | 16 | diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h |
31 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/hw/net/imx_fec.c | 18 | --- a/include/hw/arm/nrf51_soc.h |
33 | +++ b/hw/net/imx_fec.c | 19 | +++ b/include/hw/arm/nrf51_soc.h |
34 | @@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s, uint32_t index) | 20 | @@ -XXX,XX +XXX,XX @@ |
35 | static void imx_eth_enable_rx(IMXFECState *s, bool flush) | 21 | #include "hw/char/nrf51_uart.h" |
22 | #include "hw/misc/nrf51_rng.h" | ||
23 | #include "hw/gpio/nrf51_gpio.h" | ||
24 | +#include "hw/timer/nrf51_timer.h" | ||
25 | |||
26 | #define TYPE_NRF51_SOC "nrf51-soc" | ||
27 | #define NRF51_SOC(obj) \ | ||
28 | OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC) | ||
29 | |||
30 | +#define NRF51_NUM_TIMERS 3 | ||
31 | + | ||
32 | typedef struct NRF51State { | ||
33 | /*< private >*/ | ||
34 | SysBusDevice parent_obj; | ||
35 | @@ -XXX,XX +XXX,XX @@ typedef struct NRF51State { | ||
36 | NRF51UARTState uart; | ||
37 | NRF51RNGState rng; | ||
38 | NRF51GPIOState gpio; | ||
39 | + NRF51TimerState timer[NRF51_NUM_TIMERS]; | ||
40 | |||
41 | MemoryRegion iomem; | ||
42 | MemoryRegion sram; | ||
43 | diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/hw/arm/nrf51_soc.c | ||
46 | +++ b/hw/arm/nrf51_soc.c | ||
47 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
48 | NRF51State *s = NRF51_SOC(dev_soc); | ||
49 | MemoryRegion *mr; | ||
50 | Error *err = NULL; | ||
51 | + uint8_t i = 0; | ||
52 | + hwaddr base_addr = 0; | ||
53 | |||
54 | if (!s->board_memory) { | ||
55 | error_setg(errp, "memory property was not set"); | ||
56 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
57 | /* Pass all GPIOs to the SOC layer so they are available to the board */ | ||
58 | qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL); | ||
59 | |||
60 | + /* TIMER */ | ||
61 | + for (i = 0; i < NRF51_NUM_TIMERS; i++) { | ||
62 | + object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); | ||
63 | + if (err) { | ||
64 | + error_propagate(errp, err); | ||
65 | + return; | ||
66 | + } | ||
67 | + | ||
68 | + base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE; | ||
69 | + | ||
70 | + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr); | ||
71 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0, | ||
72 | + qdev_get_gpio_in(DEVICE(&s->cpu), | ||
73 | + BASE_TO_IRQ(base_addr))); | ||
74 | + } | ||
75 | + | ||
76 | create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE, | ||
77 | NRF51_IOMEM_SIZE); | ||
78 | create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE, | ||
79 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) | ||
80 | |||
81 | static void nrf51_soc_init(Object *obj) | ||
36 | { | 82 | { |
37 | IMXFECBufDesc bd; | 83 | + uint8_t i = 0; |
38 | - bool rx_ring_full; | 84 | + |
39 | 85 | NRF51State *s = NRF51_SOC(obj); | |
40 | imx_fec_read_bd(&bd, s->rx_descriptor); | 86 | |
41 | 87 | memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX); | |
42 | - rx_ring_full = !(bd.flags & ENET_BD_E); | 88 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj) |
43 | + s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0; | 89 | |
44 | 90 | sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio), | |
45 | - if (rx_ring_full) { | 91 | TYPE_NRF51_GPIO); |
46 | + if (!s->regs[ENET_RDAR]) { | 92 | + |
47 | FEC_PRINTF("RX buffer full\n"); | 93 | + for (i = 0; i < NRF51_NUM_TIMERS; i++) { |
48 | } else if (flush) { | 94 | + sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], |
49 | qemu_flush_queued_packets(qemu_get_queue(s->nic)); | 95 | + sizeof(s->timer[i]), TYPE_NRF51_TIMER); |
50 | } | 96 | + |
51 | - | 97 | + } |
52 | - s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR; | ||
53 | } | 98 | } |
54 | 99 | ||
55 | static void imx_eth_reset(DeviceState *d) | 100 | static Property nrf51_soc_properties[] = { |
56 | @@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, | ||
57 | case ENET_RDAR: | ||
58 | if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) { | ||
59 | if (!s->regs[index]) { | ||
60 | - s->regs[index] = ENET_RDAR_RDAR; | ||
61 | imx_eth_enable_rx(s, true); | ||
62 | } | ||
63 | } else { | ||
64 | -- | 101 | -- |
65 | 2.7.4 | 102 | 2.19.2 |
66 | 103 | ||
67 | 104 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | At the same time, move VMSTATE_UINT32_SUB_ARRAY | 3 | Basic tests for nRF51 Timer Peripheral. |
4 | beside the other UINT32 definitions. | ||
5 | 4 | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 5 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 6 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> |
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 7 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
9 | Message-id: 20180119045438.28582-8-richard.henderson@linaro.org | 8 | Message-id: 20190103091119.9367-11-stefanha@redhat.com |
10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
12 | --- | 10 | --- |
13 | include/migration/vmstate.h | 9 ++++++--- | 11 | tests/microbit-test.c | 95 +++++++++++++++++++++++++++++++++++++++++++ |
14 | 1 file changed, 6 insertions(+), 3 deletions(-) | 12 | 1 file changed, 95 insertions(+) |
15 | 13 | ||
16 | diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h | 14 | diff --git a/tests/microbit-test.c b/tests/microbit-test.c |
17 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/include/migration/vmstate.h | 16 | --- a/tests/microbit-test.c |
19 | +++ b/include/migration/vmstate.h | 17 | +++ b/tests/microbit-test.c |
20 | @@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq; | 18 | @@ -XXX,XX +XXX,XX @@ |
21 | #define VMSTATE_UINT32_ARRAY(_f, _s, _n) \ | 19 | |
22 | VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0) | 20 | #include "hw/arm/nrf51.h" |
23 | 21 | #include "hw/gpio/nrf51_gpio.h" | |
24 | +#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \ | 22 | +#include "hw/timer/nrf51_timer.h" |
25 | + VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t) | 23 | |
24 | static void test_nrf51_gpio(void) | ||
25 | { | ||
26 | @@ -XXX,XX +XXX,XX @@ static void test_nrf51_gpio(void) | ||
27 | qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); | ||
28 | } | ||
29 | |||
30 | +static void timer_task(hwaddr task) | ||
31 | +{ | ||
32 | + writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK); | ||
33 | +} | ||
26 | + | 34 | + |
27 | #define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2) \ | 35 | +static void timer_clear_event(hwaddr event) |
28 | VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0) | 36 | +{ |
29 | 37 | + writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR); | |
30 | @@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq; | 38 | +} |
31 | #define VMSTATE_UINT64_ARRAY(_f, _s, _n) \ | ||
32 | VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0) | ||
33 | |||
34 | +#define VMSTATE_UINT64_SUB_ARRAY(_f, _s, _start, _num) \ | ||
35 | + VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint64, uint64_t) | ||
36 | + | 39 | + |
37 | #define VMSTATE_UINT64_2DARRAY(_f, _s, _n1, _n2) \ | 40 | +static void timer_set_bitmode(uint8_t mode) |
38 | VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, 0) | 41 | +{ |
39 | 42 | + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode); | |
40 | @@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq; | 43 | +} |
41 | #define VMSTATE_INT32_ARRAY(_f, _s, _n) \ | 44 | + |
42 | VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0) | 45 | +static void timer_set_prescaler(uint8_t prescaler) |
43 | 46 | +{ | |
44 | -#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \ | 47 | + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler); |
45 | - VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t) | 48 | +} |
46 | - | 49 | + |
47 | #define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v) \ | 50 | +static void timer_set_cc(size_t idx, uint32_t value) |
48 | VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t) | 51 | +{ |
52 | + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value); | ||
53 | +} | ||
54 | + | ||
55 | +static void timer_assert_events(uint32_t ev0, uint32_t ev1, uint32_t ev2, | ||
56 | + uint32_t ev3) | ||
57 | +{ | ||
58 | + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) == ev0); | ||
59 | + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) == ev1); | ||
60 | + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) == ev2); | ||
61 | + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) == ev3); | ||
62 | +} | ||
63 | + | ||
64 | +static void test_nrf51_timer(void) | ||
65 | +{ | ||
66 | + uint32_t steps_to_overflow = 408; | ||
67 | + | ||
68 | + /* Compare Match */ | ||
69 | + timer_task(NRF51_TIMER_TASK_STOP); | ||
70 | + timer_task(NRF51_TIMER_TASK_CLEAR); | ||
71 | + | ||
72 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); | ||
73 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); | ||
74 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); | ||
75 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); | ||
76 | + | ||
77 | + timer_set_bitmode(NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */ | ||
78 | + timer_set_prescaler(0); | ||
79 | + /* Swept over in first step */ | ||
80 | + timer_set_cc(0, 2); | ||
81 | + /* Barely miss on first step */ | ||
82 | + timer_set_cc(1, 162); | ||
83 | + /* Spot on on third step */ | ||
84 | + timer_set_cc(2, 480); | ||
85 | + | ||
86 | + timer_assert_events(0, 0, 0, 0); | ||
87 | + | ||
88 | + timer_task(NRF51_TIMER_TASK_START); | ||
89 | + clock_step(10000); | ||
90 | + timer_assert_events(1, 0, 0, 0); | ||
91 | + | ||
92 | + /* Swept over on first overflow */ | ||
93 | + timer_set_cc(3, 114); | ||
94 | + | ||
95 | + clock_step(10000); | ||
96 | + timer_assert_events(1, 1, 0, 0); | ||
97 | + | ||
98 | + clock_step(10000); | ||
99 | + timer_assert_events(1, 1, 1, 0); | ||
100 | + | ||
101 | + /* Wrap time until internal counter overflows */ | ||
102 | + while (steps_to_overflow--) { | ||
103 | + timer_assert_events(1, 1, 1, 0); | ||
104 | + clock_step(10000); | ||
105 | + } | ||
106 | + | ||
107 | + timer_assert_events(1, 1, 1, 1); | ||
108 | + | ||
109 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); | ||
110 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); | ||
111 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); | ||
112 | + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); | ||
113 | + timer_assert_events(0, 0, 0, 0); | ||
114 | + | ||
115 | + timer_task(NRF51_TIMER_TASK_STOP); | ||
116 | + | ||
117 | + /* Test Proposal: Stop/Shutdown */ | ||
118 | + /* Test Proposal: Shortcut Compare -> Clear */ | ||
119 | + /* Test Proposal: Shortcut Compare -> Stop */ | ||
120 | + /* Test Proposal: Counter Mode */ | ||
121 | +} | ||
122 | + | ||
123 | int main(int argc, char **argv) | ||
124 | { | ||
125 | int ret; | ||
126 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) | ||
127 | global_qtest = qtest_initf("-machine microbit"); | ||
128 | |||
129 | qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio); | ||
130 | + qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer); | ||
131 | |||
132 | ret = g_test_run(); | ||
49 | 133 | ||
50 | -- | 134 | -- |
51 | 2.7.4 | 135 | 2.19.2 |
52 | 136 | ||
53 | 137 | diff view generated by jsdifflib |
1 | From: Linus Walleij <linus.walleij@linaro.org> | 1 | From: Steffen Görtz <contrib@steffen-goertz.de> |
---|---|---|---|
2 | 2 | ||
3 | This implements rudimentary support for interrupt generation on the | 3 | This stubs enables the microbit-micropython firmware to run |
4 | PL110. I am working on a new DRI/KMS driver for Linux and since that | 4 | on the microbit machine. |
5 | uses the blanking interrupt, we need something to fire here. Without | ||
6 | any interrupt support Linux waits for a while and then gives ugly | ||
7 | messages about the vblank not working in the console (it does not | ||
8 | hang perpetually or anything though, DRI is pretty forgiving). | ||
9 | 5 | ||
10 | I solved it for now by setting up a timer to fire at 60Hz and pull | 6 | Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de> |
11 | the interrupts for "vertical compare" and "next memory base" | 7 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> |
12 | at this interval. This works fine and fires roughly the same number | 8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
13 | of IRQs on QEMU as on the hardware and leaves the console clean | 9 | Message-id: 20190103091119.9367-12-stefanha@redhat.com |
14 | and nice. | ||
15 | |||
16 | People who want to create more accurate emulation can probably work | ||
17 | on top of this if need be. It is certainly closer to the hardware | ||
18 | behaviour than what we have today anyway. | ||
19 | |||
20 | Cc: Peter Maydell <peter.maydell@linaro.org> | ||
21 | Signed-off-by: Linus Walleij <linus.walleij@linaro.org> | ||
22 | Message-id: 20180123225654.5764-1-linus.walleij@linaro.org | ||
23 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
24 | [PMM: folded long lines] | ||
25 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
26 | --- | 11 | --- |
27 | hw/display/pl110.c | 30 +++++++++++++++++++++++++++++- | 12 | include/hw/arm/nrf51_soc.h | 1 + |
28 | 1 file changed, 29 insertions(+), 1 deletion(-) | 13 | hw/arm/nrf51_soc.c | 26 ++++++++++++++++++++++++++ |
14 | 2 files changed, 27 insertions(+) | ||
29 | 15 | ||
30 | diff --git a/hw/display/pl110.c b/hw/display/pl110.c | 16 | diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h |
31 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/hw/display/pl110.c | 18 | --- a/include/hw/arm/nrf51_soc.h |
33 | +++ b/hw/display/pl110.c | 19 | +++ b/include/hw/arm/nrf51_soc.h |
20 | @@ -XXX,XX +XXX,XX @@ typedef struct NRF51State { | ||
21 | MemoryRegion iomem; | ||
22 | MemoryRegion sram; | ||
23 | MemoryRegion flash; | ||
24 | + MemoryRegion clock; | ||
25 | |||
26 | uint32_t sram_size; | ||
27 | uint32_t flash_size; | ||
28 | diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/arm/nrf51_soc.c | ||
31 | +++ b/hw/arm/nrf51_soc.c | ||
34 | @@ -XXX,XX +XXX,XX @@ | 32 | @@ -XXX,XX +XXX,XX @@ |
35 | #include "ui/console.h" | 33 | |
36 | #include "framebuffer.h" | 34 | #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F) |
37 | #include "ui/pixel_ops.h" | 35 | |
38 | +#include "qemu/timer.h" | 36 | +static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size) |
39 | #include "qemu/log.h" | 37 | +{ |
40 | 38 | + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", | |
41 | #define PL110_CR_EN 0x001 | 39 | + __func__, addr, size); |
42 | @@ -XXX,XX +XXX,XX @@ | 40 | + return 1; |
43 | #define PL110_CR_BEBO 0x200 | ||
44 | #define PL110_CR_BEPO 0x400 | ||
45 | #define PL110_CR_PWR 0x800 | ||
46 | +#define PL110_IE_NB 0x004 | ||
47 | +#define PL110_IE_VC 0x008 | ||
48 | |||
49 | enum pl110_bppmode | ||
50 | { | ||
51 | @@ -XXX,XX +XXX,XX @@ typedef struct PL110State { | ||
52 | MemoryRegion iomem; | ||
53 | MemoryRegionSection fbsection; | ||
54 | QemuConsole *con; | ||
55 | + QEMUTimer *vblank_timer; | ||
56 | |||
57 | int version; | ||
58 | uint32_t timing[4]; | ||
59 | @@ -XXX,XX +XXX,XX @@ static void pl110_resize(PL110State *s, int width, int height) | ||
60 | /* Update interrupts. */ | ||
61 | static void pl110_update(PL110State *s) | ||
62 | { | ||
63 | - /* TODO: Implement interrupts. */ | ||
64 | + /* Raise IRQ if enabled and any status bit is 1 */ | ||
65 | + if (s->int_status & s->int_mask) { | ||
66 | + qemu_irq_raise(s->irq); | ||
67 | + } else { | ||
68 | + qemu_irq_lower(s->irq); | ||
69 | + } | ||
70 | +} | 41 | +} |
71 | + | 42 | + |
72 | +static void pl110_vblank_interrupt(void *opaque) | 43 | +static void clock_write(void *opaque, hwaddr addr, uint64_t data, |
44 | + unsigned int size) | ||
73 | +{ | 45 | +{ |
74 | + PL110State *s = opaque; | 46 | + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n", |
47 | + __func__, addr, data, size); | ||
48 | +} | ||
75 | + | 49 | + |
76 | + /* Fire the vertical compare and next base IRQs and re-arm */ | 50 | +static const MemoryRegionOps clock_ops = { |
77 | + s->int_status |= (PL110_IE_NB | PL110_IE_VC); | 51 | + .read = clock_read, |
78 | + timer_mod(s->vblank_timer, | 52 | + .write = clock_write |
79 | + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + | 53 | +}; |
80 | + NANOSECONDS_PER_SECOND / 60); | 54 | + |
81 | + pl110_update(s); | 55 | + |
82 | } | 56 | static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) |
83 | 57 | { | |
84 | static uint64_t pl110_read(void *opaque, hwaddr offset, | 58 | NRF51State *s = NRF51_SOC(dev_soc); |
85 | @@ -XXX,XX +XXX,XX @@ static void pl110_write(void *opaque, hwaddr offset, | 59 | @@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) |
86 | s->bpp = (val >> 1) & 7; | 60 | BASE_TO_IRQ(base_addr))); |
87 | if (pl110_enabled(s)) { | 61 | } |
88 | qemu_console_resize(s->con, s->cols, s->rows); | 62 | |
89 | + timer_mod(s->vblank_timer, | 63 | + /* STUB Peripherals */ |
90 | + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + | 64 | + memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, |
91 | + NANOSECONDS_PER_SECOND / 60); | 65 | + "nrf51_soc.clock", 0x1000); |
92 | + } else { | 66 | + memory_region_add_subregion_overlap(&s->container, |
93 | + timer_del(s->vblank_timer); | 67 | + NRF51_IOMEM_BASE, &s->clock, -1); |
94 | } | 68 | + |
95 | break; | 69 | create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE, |
96 | case 10: /* LCDICR */ | 70 | NRF51_IOMEM_SIZE); |
97 | @@ -XXX,XX +XXX,XX @@ static void pl110_realize(DeviceState *dev, Error **errp) | 71 | create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE, |
98 | memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000); | ||
99 | sysbus_init_mmio(sbd, &s->iomem); | ||
100 | sysbus_init_irq(sbd, &s->irq); | ||
101 | + s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, | ||
102 | + pl110_vblank_interrupt, s); | ||
103 | qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1); | ||
104 | s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s); | ||
105 | } | ||
106 | -- | 72 | -- |
107 | 2.7.4 | 73 | 2.19.2 |
108 | 74 | ||
109 | 75 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | Now that MTTCG is here, the comment in the 32-bit Arm decoder that |
---|---|---|---|
2 | "Since the emulation does not have barriers, the acquire/release | ||
3 | semantics need no special handling" is no longer true. Emit the | ||
4 | correct barriers for the load-acquire/store-release insns, as | ||
5 | we already do in the A64 decoder. | ||
2 | 6 | ||
3 | All direct users of this field want an integral value. Drop all | 7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
4 | of the extra casting between uint64_t and float64. | 8 | Tested-by: Alex Bennée <alex.bennee@linaro.org> |
9 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
10 | --- | ||
11 | target/arm/translate.c | 33 ++++++++++++++++++++++++++------- | ||
12 | 1 file changed, 26 insertions(+), 7 deletions(-) | ||
5 | 13 | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20180119045438.28582-6-richard.henderson@linaro.org | ||
8 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | --- | ||
11 | target/arm/cpu.h | 2 +- | ||
12 | target/arm/arch_dump.c | 4 ++-- | ||
13 | target/arm/helper.c | 20 ++++++++++---------- | ||
14 | target/arm/machine.c | 2 +- | ||
15 | target/arm/translate-a64.c | 8 ++++---- | ||
16 | target/arm/translate.c | 2 +- | ||
17 | 6 files changed, 19 insertions(+), 19 deletions(-) | ||
18 | |||
19 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/target/arm/cpu.h | ||
22 | +++ b/target/arm/cpu.h | ||
23 | @@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState { | ||
24 | * the two execution states, and means we do not need to explicitly | ||
25 | * map these registers when changing states. | ||
26 | */ | ||
27 | - float64 regs[64]; | ||
28 | + uint64_t regs[64]; | ||
29 | |||
30 | uint32_t xregs[16]; | ||
31 | /* We store these fpcsr fields separately for convenience. */ | ||
32 | diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/target/arm/arch_dump.c | ||
35 | +++ b/target/arm/arch_dump.c | ||
36 | @@ -XXX,XX +XXX,XX @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f, | ||
37 | aarch64_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp)); | ||
38 | |||
39 | for (i = 0; i < 64; ++i) { | ||
40 | - note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i])); | ||
41 | + note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]); | ||
42 | } | ||
43 | |||
44 | if (s->dump_info.d_endian == ELFDATA2MSB) { | ||
45 | @@ -XXX,XX +XXX,XX @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env, | ||
46 | arm_note_init(¬e, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp)); | ||
47 | |||
48 | for (i = 0; i < 32; ++i) { | ||
49 | - note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i])); | ||
50 | + note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]); | ||
51 | } | ||
52 | |||
53 | note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env)); | ||
54 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/target/arm/helper.c | ||
57 | +++ b/target/arm/helper.c | ||
58 | @@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
59 | /* VFP data registers are always little-endian. */ | ||
60 | nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16; | ||
61 | if (reg < nregs) { | ||
62 | - stfq_le_p(buf, env->vfp.regs[reg]); | ||
63 | + stq_le_p(buf, env->vfp.regs[reg]); | ||
64 | return 8; | ||
65 | } | ||
66 | if (arm_feature(env, ARM_FEATURE_NEON)) { | ||
67 | /* Aliases for Q regs. */ | ||
68 | nregs += 16; | ||
69 | if (reg < nregs) { | ||
70 | - stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]); | ||
71 | - stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]); | ||
72 | + stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]); | ||
73 | + stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]); | ||
74 | return 16; | ||
75 | } | ||
76 | } | ||
77 | @@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
78 | |||
79 | nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16; | ||
80 | if (reg < nregs) { | ||
81 | - env->vfp.regs[reg] = ldfq_le_p(buf); | ||
82 | + env->vfp.regs[reg] = ldq_le_p(buf); | ||
83 | return 8; | ||
84 | } | ||
85 | if (arm_feature(env, ARM_FEATURE_NEON)) { | ||
86 | nregs += 16; | ||
87 | if (reg < nregs) { | ||
88 | - env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf); | ||
89 | - env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8); | ||
90 | + env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf); | ||
91 | + env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8); | ||
92 | return 16; | ||
93 | } | ||
94 | } | ||
95 | @@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
96 | switch (reg) { | ||
97 | case 0 ... 31: | ||
98 | /* 128 bit FP register */ | ||
99 | - stfq_le_p(buf, env->vfp.regs[reg * 2]); | ||
100 | - stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]); | ||
101 | + stq_le_p(buf, env->vfp.regs[reg * 2]); | ||
102 | + stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]); | ||
103 | return 16; | ||
104 | case 32: | ||
105 | /* FPSR */ | ||
106 | @@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | ||
107 | switch (reg) { | ||
108 | case 0 ... 31: | ||
109 | /* 128 bit FP register */ | ||
110 | - env->vfp.regs[reg * 2] = ldfq_le_p(buf); | ||
111 | - env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8); | ||
112 | + env->vfp.regs[reg * 2] = ldq_le_p(buf); | ||
113 | + env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8); | ||
114 | return 16; | ||
115 | case 32: | ||
116 | /* FPSR */ | ||
117 | diff --git a/target/arm/machine.c b/target/arm/machine.c | ||
118 | index XXXXXXX..XXXXXXX 100644 | ||
119 | --- a/target/arm/machine.c | ||
120 | +++ b/target/arm/machine.c | ||
121 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_vfp = { | ||
122 | .minimum_version_id = 3, | ||
123 | .needed = vfp_needed, | ||
124 | .fields = (VMStateField[]) { | ||
125 | - VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64), | ||
126 | + VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64), | ||
127 | /* The xregs array is a little awkward because element 1 (FPSCR) | ||
128 | * requires a specific accessor, so we have to split it up in | ||
129 | * the vmstate: | ||
130 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
131 | index XXXXXXX..XXXXXXX 100644 | ||
132 | --- a/target/arm/translate-a64.c | ||
133 | +++ b/target/arm/translate-a64.c | ||
134 | @@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, | ||
135 | if (flags & CPU_DUMP_FPU) { | ||
136 | int numvfpregs = 32; | ||
137 | for (i = 0; i < numvfpregs; i += 2) { | ||
138 | - uint64_t vlo = float64_val(env->vfp.regs[i * 2]); | ||
139 | - uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]); | ||
140 | + uint64_t vlo = env->vfp.regs[i * 2]; | ||
141 | + uint64_t vhi = env->vfp.regs[(i * 2) + 1]; | ||
142 | cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ", | ||
143 | i, vhi, vlo); | ||
144 | - vlo = float64_val(env->vfp.regs[(i + 1) * 2]); | ||
145 | - vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]); | ||
146 | + vlo = env->vfp.regs[(i + 1) * 2]; | ||
147 | + vhi = env->vfp.regs[((i + 1) * 2) + 1]; | ||
148 | cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n", | ||
149 | i + 1, vhi, vlo); | ||
150 | } | ||
151 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 14 | diff --git a/target/arm/translate.c b/target/arm/translate.c |
152 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
153 | --- a/target/arm/translate.c | 16 | --- a/target/arm/translate.c |
154 | +++ b/target/arm/translate.c | 17 | +++ b/target/arm/translate.c |
155 | @@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, | 18 | @@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) |
156 | numvfpregs += 16; | 19 | rd = (insn >> 12) & 0xf; |
157 | } | 20 | if (insn & (1 << 23)) { |
158 | for (i = 0; i < numvfpregs; i++) { | 21 | /* load/store exclusive */ |
159 | - uint64_t v = float64_val(env->vfp.regs[i]); | 22 | + bool is_ld = extract32(insn, 20, 1); |
160 | + uint64_t v = env->vfp.regs[i]; | 23 | + bool is_lasr = !extract32(insn, 8, 1); |
161 | cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n", | 24 | int op2 = (insn >> 8) & 3; |
162 | i * 2, (uint32_t)v, | 25 | op1 = (insn >> 21) & 0x3; |
163 | i * 2 + 1, (uint32_t)(v >> 32), | 26 | |
27 | @@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) | ||
28 | addr = tcg_temp_local_new_i32(); | ||
29 | load_reg_var(s, addr, rn); | ||
30 | |||
31 | - /* Since the emulation does not have barriers, | ||
32 | - the acquire/release semantics need no special | ||
33 | - handling */ | ||
34 | + if (is_lasr && !is_ld) { | ||
35 | + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); | ||
36 | + } | ||
37 | + | ||
38 | if (op2 == 0) { | ||
39 | - if (insn & (1 << 20)) { | ||
40 | + if (is_ld) { | ||
41 | tmp = tcg_temp_new_i32(); | ||
42 | switch (op1) { | ||
43 | case 0: /* lda */ | ||
44 | @@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) | ||
45 | } | ||
46 | tcg_temp_free_i32(tmp); | ||
47 | } | ||
48 | - } else if (insn & (1 << 20)) { | ||
49 | + } else if (is_ld) { | ||
50 | switch (op1) { | ||
51 | case 0: /* ldrex */ | ||
52 | gen_load_exclusive(s, rd, 15, addr, 2); | ||
53 | @@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) | ||
54 | } | ||
55 | } | ||
56 | tcg_temp_free_i32(addr); | ||
57 | + | ||
58 | + if (is_lasr && is_ld) { | ||
59 | + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); | ||
60 | + } | ||
61 | } else if ((insn & 0x00300f00) == 0) { | ||
62 | /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx | ||
63 | * - SWP, SWPB | ||
64 | @@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) | ||
65 | tcg_gen_addi_i32(tmp, tmp, s->pc); | ||
66 | store_reg(s, 15, tmp); | ||
67 | } else { | ||
68 | + bool is_lasr = false; | ||
69 | + bool is_ld = extract32(insn, 20, 1); | ||
70 | int op2 = (insn >> 6) & 0x3; | ||
71 | op = (insn >> 4) & 0x3; | ||
72 | switch (op2) { | ||
73 | @@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) | ||
74 | case 3: | ||
75 | /* Load-acquire/store-release exclusive */ | ||
76 | ARCH(8); | ||
77 | + is_lasr = true; | ||
78 | break; | ||
79 | } | ||
80 | + | ||
81 | + if (is_lasr && !is_ld) { | ||
82 | + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); | ||
83 | + } | ||
84 | + | ||
85 | addr = tcg_temp_local_new_i32(); | ||
86 | load_reg_var(s, addr, rn); | ||
87 | if (!(op2 & 1)) { | ||
88 | - if (insn & (1 << 20)) { | ||
89 | + if (is_ld) { | ||
90 | tmp = tcg_temp_new_i32(); | ||
91 | switch (op) { | ||
92 | case 0: /* ldab */ | ||
93 | @@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) | ||
94 | } | ||
95 | tcg_temp_free_i32(tmp); | ||
96 | } | ||
97 | - } else if (insn & (1 << 20)) { | ||
98 | + } else if (is_ld) { | ||
99 | gen_load_exclusive(s, rs, rd, addr, op); | ||
100 | } else { | ||
101 | gen_store_exclusive(s, rm, rs, rd, addr, op); | ||
102 | } | ||
103 | tcg_temp_free_i32(addr); | ||
104 | + | ||
105 | + if (is_lasr && is_ld) { | ||
106 | + tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); | ||
107 | + } | ||
108 | } | ||
109 | } else { | ||
110 | /* Load/store multiple, RFE, SRS. */ | ||
164 | -- | 111 | -- |
165 | 2.7.4 | 112 | 2.19.2 |
166 | 113 | ||
167 | 114 | diff view generated by jsdifflib |
1 | We were passing a NULL error pointer to the object_property_set_bool() | 1 | In the TZ Memory Protection Controller, the BLK_MAX register is supposed |
---|---|---|---|
2 | call that realizes the CPU object. This meant that we wouldn't detect | 2 | to return the maximum permitted value of the BLK_IDX register. Our |
3 | failure, and would plough blindly on to crash later trying to use a | 3 | implementation incorrectly returned max+1 (ie the total number of |
4 | NULL CPU object pointer. Detect errors and fail instead. | 4 | valid index values, since BLK_IDX is zero-based). |
5 | 5 | ||
6 | In particular, this will be necessary to detect the user error | 6 | Correct this off-by-one error. Since we consistently initialize |
7 | of using "-cpu host" without "-enable-kvm" once we make the host | 7 | and use s->blk_max throughout the implementation as the 'size' |
8 | CPU type be registered unconditionally rather than only in | 8 | of the LUT, just adjust the value we return when the guest reads |
9 | kvm_arch_init(). | 9 | the BLK_MAX register, rather than trying to change the semantics |
10 | of the s->blk_max internal struct field. | ||
10 | 11 | ||
12 | Fixes: https://bugs.launchpad.net/qemu/+bug/1806824 | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | Message-id: 20181213183249.3468-1-peter.maydell@linaro.org | ||
12 | --- | 16 | --- |
13 | hw/arm/virt.c | 2 +- | 17 | hw/misc/tz-mpc.c | 2 +- |
14 | 1 file changed, 1 insertion(+), 1 deletion(-) | 18 | 1 file changed, 1 insertion(+), 1 deletion(-) |
15 | 19 | ||
16 | diff --git a/hw/arm/virt.c b/hw/arm/virt.c | 20 | diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c |
17 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/hw/arm/virt.c | 22 | --- a/hw/misc/tz-mpc.c |
19 | +++ b/hw/arm/virt.c | 23 | +++ b/hw/misc/tz-mpc.c |
20 | @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) | 24 | @@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, |
21 | "secure-memory", &error_abort); | 25 | r = s->ctrl; |
22 | } | 26 | break; |
23 | 27 | case A_BLK_MAX: | |
24 | - object_property_set_bool(cpuobj, true, "realized", NULL); | 28 | - r = s->blk_max; |
25 | + object_property_set_bool(cpuobj, true, "realized", &error_fatal); | 29 | + r = s->blk_max - 1; |
26 | object_unref(cpuobj); | 30 | break; |
27 | } | 31 | case A_BLK_CFG: |
28 | fdt_add_timer_nodes(vms); | 32 | /* We are never in "init in progress state", so this just indicates |
29 | -- | 33 | -- |
30 | 2.7.4 | 34 | 2.19.2 |
31 | 35 | ||
32 | 36 | diff view generated by jsdifflib |
1 | From: Ard Biesheuvel <ard.biesheuvel@linaro.org> | 1 | From: Nick Hudson <nick.hudson@gmx.co.uk> |
---|---|---|---|
2 | 2 | ||
3 | Commit ("3b39d734141a target/arm: Handle page table walk load failures | 3 | noload kernels are loaded with the u-boot image header and as a result |
4 | correctly") modified both versions of the page table walking code (i.e., | 4 | the header size needs adding to the entry point. Fake up a hdr so the |
5 | arm_ldl_ptw and arm_ldq_ptw) to record the result of the translation in | 5 | kernel image is loaded at the right address and the entry point is |
6 | a temporary 'data' variable so that it can be inspected before being | 6 | adjusted appropriately. |
7 | returned. However, arm_ldq_ptw() returns an uint64_t, and using a | ||
8 | temporary uint32_t variable truncates the upper bits, corrupting the | ||
9 | result. This causes problems when using more than 4 GB of memory in | ||
10 | a TCG guest. So use a uint64_t instead. | ||
11 | 7 | ||
12 | Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> | 8 | The default location for the uboot file is 32MiB above bottom of DRAM. |
13 | Message-id: 20180119194648.25501-1-ard.biesheuvel@linaro.org | 9 | This matches the recommendation in Documentation/arm/Booting. |
10 | |||
11 | Clarify the load_uimage API to state the passing of a load address when an | ||
12 | image doesn't specify one, or when loading a ramdisk is expected. | ||
13 | |||
14 | Adjust callers of load_uimage, etc. | ||
15 | |||
16 | Signed-off-by: Nick Hudson <skrll@netbsd.org> | ||
17 | Message-id: 11488a08-1fe0-a278-2210-deb64731107f@gmx.co.uk | ||
14 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 18 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
16 | --- | 20 | --- |
17 | target/arm/helper.c | 2 +- | 21 | hw/core/uboot_image.h | 1 + |
18 | 1 file changed, 1 insertion(+), 1 deletion(-) | 22 | include/hw/loader.h | 7 ++++++- |
23 | hw/arm/boot.c | 8 +++++--- | ||
24 | hw/core/loader.c | 19 ++++++++++++++++--- | ||
25 | hw/microblaze/boot.c | 2 +- | ||
26 | hw/nios2/boot.c | 2 +- | ||
27 | hw/ppc/e500.c | 1 + | ||
28 | hw/ppc/ppc440_bamboo.c | 2 +- | ||
29 | hw/ppc/sam460ex.c | 2 +- | ||
30 | 9 files changed, 33 insertions(+), 11 deletions(-) | ||
19 | 31 | ||
20 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 32 | diff --git a/hw/core/uboot_image.h b/hw/core/uboot_image.h |
21 | index XXXXXXX..XXXXXXX 100644 | 33 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/target/arm/helper.c | 34 | --- a/hw/core/uboot_image.h |
23 | +++ b/target/arm/helper.c | 35 | +++ b/hw/core/uboot_image.h |
24 | @@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure, | 36 | @@ -XXX,XX +XXX,XX @@ |
25 | MemTxAttrs attrs = {}; | 37 | #define IH_TYPE_SCRIPT 6 /* Script file */ |
26 | MemTxResult result = MEMTX_OK; | 38 | #define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */ |
27 | AddressSpace *as; | 39 | #define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */ |
28 | - uint32_t data; | 40 | +#define IH_TYPE_KERNEL_NOLOAD 14 /* OS Kernel Image (noload) */ |
29 | + uint64_t data; | 41 | |
30 | 42 | /* | |
31 | attrs.secure = is_secure; | 43 | * Compression Types |
32 | as = arm_addressspace(cs, attrs); | 44 | diff --git a/include/hw/loader.h b/include/hw/loader.h |
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/include/hw/loader.h | ||
47 | +++ b/include/hw/loader.h | ||
48 | @@ -XXX,XX +XXX,XX @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp); | ||
49 | int load_aout(const char *filename, hwaddr addr, int max_sz, | ||
50 | int bswap_needed, hwaddr target_page_size); | ||
51 | |||
52 | +#define LOAD_UIMAGE_LOADADDR_INVALID (-1) | ||
53 | + | ||
54 | /** load_uimage_as: | ||
55 | * @filename: Path of uimage file | ||
56 | * @ep: Populated with program entry point. Ignored if NULL. | ||
57 | - * @loadaddr: Populated with the load address. Ignored if NULL. | ||
58 | + * @loadaddr: load address if none specified in the image or when loading a | ||
59 | + * ramdisk. Populated with the load address. Ignored if NULL or | ||
60 | + * LOAD_UIMAGE_LOADADDR_INVALID (images which do not specify a load | ||
61 | + * address will not be loadable). | ||
62 | * @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL. | ||
63 | * @translate_fn: optional function to translate load addresses | ||
64 | * @translate_opaque: opaque data passed to @translate_fn | ||
65 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/hw/arm/boot.c | ||
68 | +++ b/hw/arm/boot.c | ||
69 | @@ -XXX,XX +XXX,XX @@ | ||
70 | * Documentation/arm/Booting and Documentation/arm64/booting.txt | ||
71 | * They have different preferred image load offsets from system RAM base. | ||
72 | */ | ||
73 | -#define KERNEL_ARGS_ADDR 0x100 | ||
74 | -#define KERNEL_LOAD_ADDR 0x00010000 | ||
75 | +#define KERNEL_ARGS_ADDR 0x100 | ||
76 | +#define KERNEL_NOLOAD_ADDR 0x02000000 | ||
77 | +#define KERNEL_LOAD_ADDR 0x00010000 | ||
78 | #define KERNEL64_LOAD_ADDR 0x00080000 | ||
79 | |||
80 | #define ARM64_TEXT_OFFSET_OFFSET 8 | ||
81 | @@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) | ||
82 | } | ||
83 | entry = elf_entry; | ||
84 | if (kernel_size < 0) { | ||
85 | - kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL, | ||
86 | + uint64_t loadaddr = info->loader_start + KERNEL_NOLOAD_ADDR; | ||
87 | + kernel_size = load_uimage_as(info->kernel_filename, &entry, &loadaddr, | ||
88 | &is_linux, NULL, NULL, as); | ||
89 | } | ||
90 | if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) { | ||
91 | diff --git a/hw/core/loader.c b/hw/core/loader.c | ||
92 | index XXXXXXX..XXXXXXX 100644 | ||
93 | --- a/hw/core/loader.c | ||
94 | +++ b/hw/core/loader.c | ||
95 | @@ -XXX,XX +XXX,XX @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr, | ||
96 | goto out; | ||
97 | |||
98 | if (hdr->ih_type != image_type) { | ||
99 | - fprintf(stderr, "Wrong image type %d, expected %d\n", hdr->ih_type, | ||
100 | - image_type); | ||
101 | - goto out; | ||
102 | + if (!(image_type == IH_TYPE_KERNEL && | ||
103 | + hdr->ih_type == IH_TYPE_KERNEL_NOLOAD)) { | ||
104 | + fprintf(stderr, "Wrong image type %d, expected %d\n", hdr->ih_type, | ||
105 | + image_type); | ||
106 | + goto out; | ||
107 | + } | ||
108 | } | ||
109 | |||
110 | /* TODO: Implement other image types. */ | ||
111 | switch (hdr->ih_type) { | ||
112 | + case IH_TYPE_KERNEL_NOLOAD: | ||
113 | + if (!loadaddr || *loadaddr == LOAD_UIMAGE_LOADADDR_INVALID) { | ||
114 | + fprintf(stderr, "this image format (kernel_noload) cannot be " | ||
115 | + "loaded on this machine type"); | ||
116 | + goto out; | ||
117 | + } | ||
118 | + | ||
119 | + hdr->ih_load = *loadaddr + sizeof(*hdr); | ||
120 | + hdr->ih_ep += hdr->ih_load; | ||
121 | + /* fall through */ | ||
122 | case IH_TYPE_KERNEL: | ||
123 | address = hdr->ih_load; | ||
124 | if (translate_fn) { | ||
125 | diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c | ||
126 | index XXXXXXX..XXXXXXX 100644 | ||
127 | --- a/hw/microblaze/boot.c | ||
128 | +++ b/hw/microblaze/boot.c | ||
129 | @@ -XXX,XX +XXX,XX @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, | ||
130 | |||
131 | /* If it wasn't an ELF image, try an u-boot image. */ | ||
132 | if (kernel_size < 0) { | ||
133 | - hwaddr uentry, loadaddr; | ||
134 | + hwaddr uentry, loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; | ||
135 | |||
136 | kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0, | ||
137 | NULL, NULL); | ||
138 | diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c | ||
139 | index XXXXXXX..XXXXXXX 100644 | ||
140 | --- a/hw/nios2/boot.c | ||
141 | +++ b/hw/nios2/boot.c | ||
142 | @@ -XXX,XX +XXX,XX @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, | ||
143 | |||
144 | /* If it wasn't an ELF image, try an u-boot image. */ | ||
145 | if (kernel_size < 0) { | ||
146 | - hwaddr uentry, loadaddr; | ||
147 | + hwaddr uentry, loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; | ||
148 | |||
149 | kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0, | ||
150 | NULL, NULL); | ||
151 | diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c | ||
152 | index XXXXXXX..XXXXXXX 100644 | ||
153 | --- a/hw/ppc/e500.c | ||
154 | +++ b/hw/ppc/e500.c | ||
155 | @@ -XXX,XX +XXX,XX @@ void ppce500_init(MachineState *machine) | ||
156 | * Hrm. No ELF image? Try a uImage, maybe someone is giving us an | ||
157 | * ePAPR compliant kernel | ||
158 | */ | ||
159 | + loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; | ||
160 | payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL, | ||
161 | NULL, NULL); | ||
162 | if (payload_size < 0) { | ||
163 | diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c | ||
164 | index XXXXXXX..XXXXXXX 100644 | ||
165 | --- a/hw/ppc/ppc440_bamboo.c | ||
166 | +++ b/hw/ppc/ppc440_bamboo.c | ||
167 | @@ -XXX,XX +XXX,XX @@ static void bamboo_init(MachineState *machine) | ||
168 | CPUPPCState *env; | ||
169 | uint64_t elf_entry; | ||
170 | uint64_t elf_lowaddr; | ||
171 | - hwaddr loadaddr = 0; | ||
172 | + hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; | ||
173 | target_long initrd_size = 0; | ||
174 | DeviceState *dev; | ||
175 | int success; | ||
176 | diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c | ||
177 | index XXXXXXX..XXXXXXX 100644 | ||
178 | --- a/hw/ppc/sam460ex.c | ||
179 | +++ b/hw/ppc/sam460ex.c | ||
180 | @@ -XXX,XX +XXX,XX @@ static void sam460ex_init(MachineState *machine) | ||
181 | CPUPPCState *env; | ||
182 | PPC4xxI2CState *i2c[2]; | ||
183 | hwaddr entry = UBOOT_ENTRY; | ||
184 | - hwaddr loadaddr = 0; | ||
185 | + hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; | ||
186 | target_long initrd_size = 0; | ||
187 | DeviceState *dev; | ||
188 | SysBusDevice *sbdev; | ||
33 | -- | 189 | -- |
34 | 2.7.4 | 190 | 2.19.2 |
35 | 191 | ||
36 | 192 | diff view generated by jsdifflib |