1 | My OS Lock/DoubleLock patches, plus a small selection of other | 1 | A last small test of bug fixes before rc1. |
---|---|---|---|
2 | bug fixes and minor things. | ||
3 | 2 | ||
4 | thanks | 3 | thanks |
5 | -- PMM | 4 | -- PMM |
6 | 5 | ||
7 | The following changes since commit 8e9398e3b1a860b8c29c670c1b6c36afe8d87849: | 6 | The following changes since commit ed8ad9728a9c0eec34db9dff61dfa2f1dd625637: |
8 | 7 | ||
9 | Merge tag 'pull-ppc-20220706' of https://gitlab.com/danielhb/qemu into staging (2022-07-07 06:21:05 +0530) | 8 | Merge tag 'pull-tpm-2023-07-14-1' of https://github.com/stefanberger/qemu-tpm into staging (2023-07-15 14:54:04 +0100) |
10 | 9 | ||
11 | are available in the Git repository at: | 10 | are available in the Git repository at: |
12 | 11 | ||
13 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220707 | 12 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230717 |
14 | 13 | ||
15 | for you to fetch changes up to c2360eaa0262a816faf8032b7762d0c73df2cc62: | 14 | for you to fetch changes up to c2c1c4a35c7c2b1a4140b0942b9797c857e476a4: |
16 | 15 | ||
17 | target/arm: Fix qemu-system-arm handling of LPAE block descriptors for highmem (2022-07-07 11:41:04 +0100) | 16 | hw/nvram: Avoid unnecessary Xilinx eFuse backstore write (2023-07-17 11:05:52 +0100) |
18 | 17 | ||
19 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
20 | target-arm queue: | 19 | target-arm queue: |
21 | * hw/arm/virt: dt: add rng-seed property | 20 | * hw/arm/sbsa-ref: set 'slots' property of xhci |
22 | * Fix MTE check in sve_ldnfff1_r | 21 | * linux-user: Remove pointless NULL check in clock_adjtime handling |
23 | * Record tagged bit for user-only in sve_probe_page | 22 | * ptw: Fix S1_ptw_translate() debug path |
24 | * Correctly implement OS Lock and OS DoubleLock | 23 | * ptw: Account for FEAT_RME when applying {N}SW, SA bits |
25 | * Implement DBGDEVID, DBGDEVID1, DBGDEVID2 registers | 24 | * accel/tcg: Zero-pad PC in TCG CPU exec trace lines |
26 | * Fix qemu-system-arm handling of LPAE block descriptors for highmem | 25 | * hw/nvram: Avoid unnecessary Xilinx eFuse backstore write |
27 | 26 | ||
28 | ---------------------------------------------------------------- | 27 | ---------------------------------------------------------------- |
29 | Jason A. Donenfeld (1): | 28 | Peter Maydell (5): |
30 | hw/arm/virt: dt: add rng-seed property | 29 | linux-user: Remove pointless NULL check in clock_adjtime handling |
30 | target/arm/ptw.c: Add comments to S1Translate struct fields | ||
31 | target/arm: Fix S1_ptw_translate() debug path | ||
32 | target/arm/ptw.c: Account for FEAT_RME when applying {N}SW, SA bits | ||
33 | accel/tcg: Zero-pad PC in TCG CPU exec trace lines | ||
31 | 34 | ||
32 | Peter Maydell (6): | 35 | Tong Ho (1): |
33 | target/arm: Fix code style issues in debug helper functions | 36 | hw/nvram: Avoid unnecessary Xilinx eFuse backstore write |
34 | target/arm: Move define_debug_regs() to debug_helper.c | ||
35 | target/arm: Suppress debug exceptions when OS Lock set | ||
36 | target/arm: Implement AArch32 DBGDEVID, DBGDEVID1, DBGDEVID2 | ||
37 | target/arm: Correctly implement Feat_DoubleLock | ||
38 | target/arm: Fix qemu-system-arm handling of LPAE block descriptors for highmem | ||
39 | 37 | ||
40 | Richard Henderson (2): | 38 | Yuquan Wang (1): |
41 | target/arm: Fix MTE check in sve_ldnfff1_r | 39 | hw/arm/sbsa-ref: set 'slots' property of xhci |
42 | target/arm: Record tagged bit for user-only in sve_probe_page | ||
43 | 40 | ||
44 | docs/about/deprecated.rst | 8 + | 41 | accel/tcg/cpu-exec.c | 4 +-- |
45 | docs/system/arm/virt.rst | 17 +- | 42 | accel/tcg/translate-all.c | 2 +- |
46 | include/hw/arm/virt.h | 2 +- | 43 | hw/arm/sbsa-ref.c | 1 + |
47 | target/arm/cpregs.h | 3 + | 44 | hw/nvram/xlnx-efuse.c | 11 ++++-- |
48 | target/arm/cpu.h | 27 +++ | 45 | linux-user/syscall.c | 12 +++---- |
49 | target/arm/internals.h | 9 + | 46 | target/arm/ptw.c | 90 +++++++++++++++++++++++++++++++++++++++++------ |
50 | hw/arm/virt.c | 44 ++-- | 47 | 6 files changed, 98 insertions(+), 22 deletions(-) |
51 | target/arm/cpu64.c | 6 + | ||
52 | target/arm/cpu_tcg.c | 6 + | ||
53 | target/arm/debug_helper.c | 580 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
54 | target/arm/helper.c | 513 +--------------------------------------- | ||
55 | target/arm/ptw.c | 2 +- | ||
56 | target/arm/sve_helper.c | 5 +- | ||
57 | 13 files changed, 684 insertions(+), 538 deletions(-) | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Yuquan Wang <wangyuquan1236@phytium.com.cn> |
---|---|---|---|
2 | 2 | ||
3 | Fixes a bug in that we were not honoring MTE from user-only | 3 | This extends the slots of xhci to 64, since the default xhci_sysbus |
4 | SVE. Copy the user-only MTE logic from allocation_tag_mem | 4 | just supports one slot. |
5 | into sve_probe_page. | ||
6 | 5 | ||
7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Wang Yuquan <wangyuquan1236@phytium.com.cn> |
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn> |
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Reviewed-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org> | ||
10 | Tested-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org> | ||
11 | Message-id: 20230710063750.473510-2-wangyuquan1236@phytium.com.cn | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 13 | --- |
11 | target/arm/sve_helper.c | 3 +++ | 14 | hw/arm/sbsa-ref.c | 1 + |
12 | 1 file changed, 3 insertions(+) | 15 | 1 file changed, 1 insertion(+) |
13 | 16 | ||
14 | diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c | 17 | diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c |
15 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/sve_helper.c | 19 | --- a/hw/arm/sbsa-ref.c |
17 | +++ b/target/arm/sve_helper.c | 20 | +++ b/hw/arm/sbsa-ref.c |
18 | @@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env, | 21 | @@ -XXX,XX +XXX,XX @@ static void create_xhci(const SBSAMachineState *sms) |
19 | 22 | hwaddr base = sbsa_ref_memmap[SBSA_XHCI].base; | |
20 | #ifdef CONFIG_USER_ONLY | 23 | int irq = sbsa_ref_irqmap[SBSA_XHCI]; |
21 | memset(&info->attrs, 0, sizeof(info->attrs)); | 24 | DeviceState *dev = qdev_new(TYPE_XHCI_SYSBUS); |
22 | + /* Require both MAP_ANON and PROT_MTE -- see allocation_tag_mem. */ | 25 | + qdev_prop_set_uint32(dev, "slots", XHCI_MAXSLOTS); |
23 | + arm_tlb_mte_tagged(&info->attrs) = | 26 | |
24 | + (flags & PAGE_ANON) && (flags & PAGE_MTE); | 27 | sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); |
25 | #else | 28 | sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); |
26 | /* | ||
27 | * Find the iotlbentry for addr and return the transaction attributes. | ||
28 | -- | 29 | -- |
29 | 2.25.1 | 30 | 2.34.1 | diff view generated by jsdifflib |
1 | Starting with v7 of the debug architecture, there are three extra | 1 | In the code for TARGET_NR_clock_adjtime, we set the pointer phtx to |
---|---|---|---|
2 | ID registers that add information on top of that provided in | 2 | the address of the local variable htx. This means it can never be |
3 | DBGDIDR. These are DBGDEVID, DBGDEVID1 and DBGDEVID2. In the | 3 | NULL, but later in the code we check it for NULL anyway. Coverity |
4 | v7 debug architecture, DBGDEVID is optional, present only of | 4 | complains about this (CID 1507683) because the NULL check comes after |
5 | DBGDIDR.DEVID_imp is set. In v7.1 all three must be present. | 5 | a call to clock_adjtime() that assumes it is non-NULL. |
6 | 6 | ||
7 | Implement the missing registers. Note that we only need to set the | 7 | Since phtx is always &htx, and is used only in three places, it's not |
8 | values in the ARMISARegisters struct for the CPUs Cortex-A7, A15, | 8 | really necessary. Remove it, bringing the code structure in to line |
9 | A53, A57 and A72 (plus the 32-bit 'max' which uses the Cortex-A53 | 9 | with that for TARGET_NR_clock_adjtime64, which already uses a simple |
10 | values): earlier CPUs didn't implement v7 of the architecture, and | 10 | '&htx' when it wants a pointer to 'htx'. |
11 | our other 64-bit CPUs (Cortex-A76, Neoverse-N1 and A64fx) don't have | ||
12 | AArch32 support at EL1. | ||
13 | 11 | ||
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
13 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
15 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
16 | Message-id: 20220630194116.3438513-5-peter.maydell@linaro.org | 15 | Message-id: 20230623144410.1837261-1-peter.maydell@linaro.org |
17 | --- | 16 | --- |
18 | target/arm/cpu.h | 7 +++++++ | 17 | linux-user/syscall.c | 12 +++++------- |
19 | target/arm/cpu64.c | 6 ++++++ | 18 | 1 file changed, 5 insertions(+), 7 deletions(-) |
20 | target/arm/cpu_tcg.c | 6 ++++++ | ||
21 | target/arm/debug_helper.c | 36 ++++++++++++++++++++++++++++++++++++ | ||
22 | 4 files changed, 55 insertions(+) | ||
23 | 19 | ||
24 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 20 | diff --git a/linux-user/syscall.c b/linux-user/syscall.c |
25 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/target/arm/cpu.h | 22 | --- a/linux-user/syscall.c |
27 | +++ b/target/arm/cpu.h | 23 | +++ b/linux-user/syscall.c |
28 | @@ -XXX,XX +XXX,XX @@ struct ArchCPU { | 24 | @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, |
29 | uint32_t mvfr2; | 25 | #if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME) |
30 | uint32_t id_dfr0; | 26 | case TARGET_NR_clock_adjtime: |
31 | uint32_t dbgdidr; | 27 | { |
32 | + uint32_t dbgdevid; | 28 | - struct timex htx, *phtx = &htx; |
33 | + uint32_t dbgdevid1; | 29 | + struct timex htx; |
34 | uint64_t id_aa64isar0; | 30 | |
35 | uint64_t id_aa64isar1; | 31 | - if (target_to_host_timex(phtx, arg2) != 0) { |
36 | uint64_t id_aa64pfr0; | 32 | + if (target_to_host_timex(&htx, arg2) != 0) { |
37 | @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) | 33 | return -TARGET_EFAULT; |
38 | return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; | 34 | } |
39 | } | 35 | - ret = get_errno(clock_adjtime(arg1, phtx)); |
40 | 36 | - if (!is_error(ret) && phtx) { | |
41 | +static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) | 37 | - if (host_to_target_timex(arg2, phtx) != 0) { |
42 | +{ | 38 | - return -TARGET_EFAULT; |
43 | + return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; | 39 | - } |
44 | +} | 40 | + ret = get_errno(clock_adjtime(arg1, &htx)); |
45 | + | 41 | + if (!is_error(ret) && host_to_target_timex(arg2, &htx)) { |
46 | static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) | 42 | + return -TARGET_EFAULT; |
47 | { | 43 | } |
48 | return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; | 44 | } |
49 | diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c | 45 | return ret; |
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/target/arm/cpu64.c | ||
52 | +++ b/target/arm/cpu64.c | ||
53 | @@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj) | ||
54 | cpu->isar.id_aa64isar0 = 0x00011120; | ||
55 | cpu->isar.id_aa64mmfr0 = 0x00001124; | ||
56 | cpu->isar.dbgdidr = 0x3516d000; | ||
57 | + cpu->isar.dbgdevid = 0x01110f13; | ||
58 | + cpu->isar.dbgdevid1 = 0x2; | ||
59 | cpu->isar.reset_pmcr_el0 = 0x41013000; | ||
60 | cpu->clidr = 0x0a200023; | ||
61 | cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ | ||
62 | @@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj) | ||
63 | cpu->isar.id_aa64isar0 = 0x00011120; | ||
64 | cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ | ||
65 | cpu->isar.dbgdidr = 0x3516d000; | ||
66 | + cpu->isar.dbgdevid = 0x00110f13; | ||
67 | + cpu->isar.dbgdevid1 = 0x1; | ||
68 | cpu->isar.reset_pmcr_el0 = 0x41033000; | ||
69 | cpu->clidr = 0x0a200023; | ||
70 | cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ | ||
71 | @@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj) | ||
72 | cpu->isar.id_aa64isar0 = 0x00011120; | ||
73 | cpu->isar.id_aa64mmfr0 = 0x00001124; | ||
74 | cpu->isar.dbgdidr = 0x3516d000; | ||
75 | + cpu->isar.dbgdevid = 0x01110f13; | ||
76 | + cpu->isar.dbgdevid1 = 0x2; | ||
77 | cpu->isar.reset_pmcr_el0 = 0x41023000; | ||
78 | cpu->clidr = 0x0a200023; | ||
79 | cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ | ||
80 | diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c | ||
81 | index XXXXXXX..XXXXXXX 100644 | ||
82 | --- a/target/arm/cpu_tcg.c | ||
83 | +++ b/target/arm/cpu_tcg.c | ||
84 | @@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj) | ||
85 | cpu->isar.id_isar3 = 0x11112131; | ||
86 | cpu->isar.id_isar4 = 0x10011142; | ||
87 | cpu->isar.dbgdidr = 0x3515f005; | ||
88 | + cpu->isar.dbgdevid = 0x01110f13; | ||
89 | + cpu->isar.dbgdevid1 = 0x1; | ||
90 | cpu->clidr = 0x0a200023; | ||
91 | cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ | ||
92 | cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ | ||
93 | @@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj) | ||
94 | cpu->isar.id_isar3 = 0x11112131; | ||
95 | cpu->isar.id_isar4 = 0x10011142; | ||
96 | cpu->isar.dbgdidr = 0x3515f021; | ||
97 | + cpu->isar.dbgdevid = 0x01110f13; | ||
98 | + cpu->isar.dbgdevid1 = 0x0; | ||
99 | cpu->clidr = 0x0a200023; | ||
100 | cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ | ||
101 | cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ | ||
102 | @@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj) | ||
103 | cpu->isar.id_isar5 = 0x00011121; | ||
104 | cpu->isar.id_isar6 = 0; | ||
105 | cpu->isar.dbgdidr = 0x3516d000; | ||
106 | + cpu->isar.dbgdevid = 0x00110f13; | ||
107 | + cpu->isar.dbgdevid1 = 0x2; | ||
108 | cpu->isar.reset_pmcr_el0 = 0x41013000; | ||
109 | cpu->clidr = 0x0a200023; | ||
110 | cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ | ||
111 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | ||
112 | index XXXXXXX..XXXXXXX 100644 | ||
113 | --- a/target/arm/debug_helper.c | ||
114 | +++ b/target/arm/debug_helper.c | ||
115 | @@ -XXX,XX +XXX,XX @@ void define_debug_regs(ARMCPU *cpu) | ||
116 | define_one_arm_cp_reg(cpu, &dbgdidr); | ||
117 | } | ||
118 | |||
119 | + /* | ||
120 | + * DBGDEVID is present in the v7 debug architecture if | ||
121 | + * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is | ||
122 | + * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist | ||
123 | + * from v7.1 of the debug architecture. Because no fields have yet | ||
124 | + * been defined in DBGDEVID2 (and quite possibly none will ever | ||
125 | + * be) we don't define an ARMISARegisters field for it. | ||
126 | + * These registers exist only if EL1 can use AArch32, but that | ||
127 | + * happens naturally because they are only PL1 accessible anyway. | ||
128 | + */ | ||
129 | + if (extract32(cpu->isar.dbgdidr, 15, 1)) { | ||
130 | + ARMCPRegInfo dbgdevid = { | ||
131 | + .name = "DBGDEVID", | ||
132 | + .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 2, .crn = 7, | ||
133 | + .access = PL1_R, .accessfn = access_tda, | ||
134 | + .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid, | ||
135 | + }; | ||
136 | + define_one_arm_cp_reg(cpu, &dbgdevid); | ||
137 | + } | ||
138 | + if (cpu_isar_feature(aa32_debugv7p1, cpu)) { | ||
139 | + ARMCPRegInfo dbgdevid12[] = { | ||
140 | + { | ||
141 | + .name = "DBGDEVID1", | ||
142 | + .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 1, .crn = 7, | ||
143 | + .access = PL1_R, .accessfn = access_tda, | ||
144 | + .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid1, | ||
145 | + }, { | ||
146 | + .name = "DBGDEVID2", | ||
147 | + .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 0, .crn = 7, | ||
148 | + .access = PL1_R, .accessfn = access_tda, | ||
149 | + .type = ARM_CP_CONST, .resetvalue = 0, | ||
150 | + }, | ||
151 | + }; | ||
152 | + define_arm_cp_regs(cpu, dbgdevid12); | ||
153 | + } | ||
154 | + | ||
155 | brps = arm_num_brps(cpu); | ||
156 | wrps = arm_num_wrps(cpu); | ||
157 | ctx_cmps = arm_num_ctx_cmps(cpu); | ||
158 | -- | 46 | -- |
159 | 2.25.1 | 47 | 2.34.1 |
48 | |||
49 | diff view generated by jsdifflib |
1 | The "OS Lock" in the Arm debug architecture is a way for software | 1 | Add comments to the in_* fields in the S1Translate struct |
---|---|---|---|
2 | to suppress debug exceptions while it is trying to power down | 2 | that explain what they're doing. |
3 | a CPU and save the state of the breakpoint and watchpoint | ||
4 | registers. In QEMU we implemented the support for writing | ||
5 | the OS Lock bit via OSLAR_EL1 and reading it via OSLSR_EL1, | ||
6 | but didn't implement the actual behaviour. | ||
7 | |||
8 | The required behaviour with the OS Lock set is: | ||
9 | * debug exceptions (apart from BKPT insns) are suppressed | ||
10 | * some MDSCR_EL1 bits allow write access to the corresponding | ||
11 | EDSCR external debug status register that they shadow | ||
12 | (we can ignore this because we don't implement external debug) | ||
13 | * similarly with the OSECCR_EL1 which shadows the EDECCR | ||
14 | (but we don't implement OSECCR_EL1 anyway) | ||
15 | |||
16 | Implement the missing behaviour of suppressing debug | ||
17 | exceptions. | ||
18 | 3 | ||
19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
20 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
21 | Message-id: 20220630194116.3438513-4-peter.maydell@linaro.org | 6 | Message-id: 20230710152130.3928330-2-peter.maydell@linaro.org |
22 | --- | 7 | --- |
23 | target/arm/debug_helper.c | 3 +++ | 8 | target/arm/ptw.c | 40 ++++++++++++++++++++++++++++++++++++++++ |
24 | 1 file changed, 3 insertions(+) | 9 | 1 file changed, 40 insertions(+) |
25 | 10 | ||
26 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | 11 | diff --git a/target/arm/ptw.c b/target/arm/ptw.c |
27 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
28 | --- a/target/arm/debug_helper.c | 13 | --- a/target/arm/ptw.c |
29 | +++ b/target/arm/debug_helper.c | 14 | +++ b/target/arm/ptw.c |
30 | @@ -XXX,XX +XXX,XX @@ static bool aa32_generate_debug_exceptions(CPUARMState *env) | 15 | @@ -XXX,XX +XXX,XX @@ |
31 | */ | 16 | #endif |
32 | bool arm_generate_debug_exceptions(CPUARMState *env) | 17 | |
33 | { | 18 | typedef struct S1Translate { |
34 | + if (env->cp15.oslsr_el1 & 1) { | 19 | + /* |
35 | + return false; | 20 | + * in_mmu_idx : specifies which TTBR, TCR, etc to use for the walk. |
36 | + } | 21 | + * Together with in_space, specifies the architectural translation regime. |
37 | if (is_a64(env)) { | 22 | + */ |
38 | return aa64_generate_debug_exceptions(env); | 23 | ARMMMUIdx in_mmu_idx; |
39 | } else { | 24 | + /* |
25 | + * in_ptw_idx: specifies which mmuidx to use for the actual | ||
26 | + * page table descriptor load operations. This will be one of the | ||
27 | + * ARMMMUIdx_Stage2* or one of the ARMMMUIdx_Phys_* indexes. | ||
28 | + * If a Secure ptw is "downgraded" to NonSecure by an NSTable bit, | ||
29 | + * this field is updated accordingly. | ||
30 | + */ | ||
31 | ARMMMUIdx in_ptw_idx; | ||
32 | + /* | ||
33 | + * in_space: the security space for this walk. This plus | ||
34 | + * the in_mmu_idx specify the architectural translation regime. | ||
35 | + * If a Secure ptw is "downgraded" to NonSecure by an NSTable bit, | ||
36 | + * this field is updated accordingly. | ||
37 | + * | ||
38 | + * Note that the security space for the in_ptw_idx may be different | ||
39 | + * from that for the in_mmu_idx. We do not need to explicitly track | ||
40 | + * the in_ptw_idx security space because: | ||
41 | + * - if the in_ptw_idx is an ARMMMUIdx_Phys_* then the mmuidx | ||
42 | + * itself specifies the security space | ||
43 | + * - if the in_ptw_idx is an ARMMMUIdx_Stage2* then the security | ||
44 | + * space used for ptw reads is the same as that of the security | ||
45 | + * space of the stage 1 translation for all cases except where | ||
46 | + * stage 1 is Secure; in that case the only possibilities for | ||
47 | + * the ptw read are Secure and NonSecure, and the in_ptw_idx | ||
48 | + * value being Stage2 vs Stage2_S distinguishes those. | ||
49 | + */ | ||
50 | ARMSecuritySpace in_space; | ||
51 | + /* | ||
52 | + * in_secure: whether the translation regime is a Secure one. | ||
53 | + * This is always equal to arm_space_is_secure(in_space). | ||
54 | + * If a Secure ptw is "downgraded" to NonSecure by an NSTable bit, | ||
55 | + * this field is updated accordingly. | ||
56 | + */ | ||
57 | bool in_secure; | ||
58 | + /* | ||
59 | + * in_debug: is this a QEMU debug access (gdbstub, etc)? Debug | ||
60 | + * accesses will not update the guest page table access flags | ||
61 | + * and will not change the state of the softmmu TLBs. | ||
62 | + */ | ||
63 | bool in_debug; | ||
64 | /* | ||
65 | * If this is stage 2 of a stage 1+2 page table walk, then this must | ||
40 | -- | 66 | -- |
41 | 2.25.1 | 67 | 2.34.1 | diff view generated by jsdifflib |
1 | The target/arm/helper.c file is very long and is a grabbag of all | 1 | In commit fe4a5472ccd6 we rearranged the logic in S1_ptw_translate() |
---|---|---|---|
2 | kinds of functionality. We have already a debug_helper.c which has | 2 | so that the debug-access "call get_phys_addr_*" codepath is used both |
3 | code for implementing architectural debug. Move the code which | 3 | when S1 is doing ptw reads from stage 2 and when it is doing ptw |
4 | defines the debug-related system registers out to this file also. | 4 | reads from physical memory. However, we didn't update the |
5 | This affects the define_debug_regs() function and the various | 5 | calculation of s2ptw->in_space and s2ptw->in_secure to account for |
6 | functions and arrays which are used only by it. | 6 | the "ptw reads from physical memory" case. This meant that debug |
7 | accesses when in Secure state broke. | ||
7 | 8 | ||
8 | The functions raw_write() and arm_mdcr_el2_eff() and | 9 | Create a new function S2_security_space() which returns the |
9 | define_debug_regs() now need to be global rather than local to | 10 | correct security space to use for the ptw load, and use it to |
10 | helper.c; everything else is pure code movement. | 11 | determine the correct .in_secure and .in_space fields for the |
12 | stage 2 lookup for the ptw load. | ||
11 | 13 | ||
14 | Reported-by: Jean-Philippe Brucker <jean-philippe@linaro.org> | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
16 | Tested-by: Jean-Philippe Brucker <jean-philippe@linaro.org> | ||
13 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 17 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
14 | Message-id: 20220630194116.3438513-3-peter.maydell@linaro.org | 18 | Message-id: 20230710152130.3928330-3-peter.maydell@linaro.org |
19 | Fixes: fe4a5472ccd6 ("target/arm: Use get_phys_addr_with_struct in S1_ptw_translate") | ||
20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
15 | --- | 21 | --- |
16 | target/arm/cpregs.h | 3 + | 22 | target/arm/ptw.c | 37 ++++++++++++++++++++++++++++++++----- |
17 | target/arm/internals.h | 9 + | 23 | 1 file changed, 32 insertions(+), 5 deletions(-) |
18 | target/arm/debug_helper.c | 525 +++++++++++++++++++++++++++++++++++++ | ||
19 | target/arm/helper.c | 531 +------------------------------------- | ||
20 | 4 files changed, 538 insertions(+), 530 deletions(-) | ||
21 | 24 | ||
22 | diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h | 25 | diff --git a/target/arm/ptw.c b/target/arm/ptw.c |
23 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/target/arm/cpregs.h | 27 | --- a/target/arm/ptw.c |
25 | +++ b/target/arm/cpregs.h | 28 | +++ b/target/arm/ptw.c |
26 | @@ -XXX,XX +XXX,XX @@ void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, | 29 | @@ -XXX,XX +XXX,XX @@ static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs) |
27 | /* CPReadFn that can be used for read-as-zero behaviour */ | 30 | } |
28 | uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri); | ||
29 | |||
30 | +/* CPWriteFn that just writes the value to ri->fieldoffset */ | ||
31 | +void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value); | ||
32 | + | ||
33 | /* | ||
34 | * CPResetFn that does nothing, for use if no reset is required even | ||
35 | * if fieldoffset is non zero. | ||
36 | diff --git a/target/arm/internals.h b/target/arm/internals.h | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/target/arm/internals.h | ||
39 | +++ b/target/arm/internals.h | ||
40 | @@ -XXX,XX +XXX,XX @@ int exception_target_el(CPUARMState *env); | ||
41 | bool arm_singlestep_active(CPUARMState *env); | ||
42 | bool arm_generate_debug_exceptions(CPUARMState *env); | ||
43 | |||
44 | +/* Add the cpreg definitions for debug related system registers */ | ||
45 | +void define_debug_regs(ARMCPU *cpu); | ||
46 | + | ||
47 | +/* Effective value of MDCR_EL2 */ | ||
48 | +static inline uint64_t arm_mdcr_el2_eff(CPUARMState *env) | ||
49 | +{ | ||
50 | + return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0; | ||
51 | +} | ||
52 | + | ||
53 | /* Powers of 2 for sve_vq_map et al. */ | ||
54 | #define SVE_VQ_POW2_MAP \ | ||
55 | ((1 << (1 - 1)) | (1 << (2 - 1)) | \ | ||
56 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | ||
57 | index XXXXXXX..XXXXXXX 100644 | ||
58 | --- a/target/arm/debug_helper.c | ||
59 | +++ b/target/arm/debug_helper.c | ||
60 | @@ -XXX,XX +XXX,XX @@ | ||
61 | * SPDX-License-Identifier: GPL-2.0-or-later | ||
62 | */ | ||
63 | #include "qemu/osdep.h" | ||
64 | +#include "qemu/log.h" | ||
65 | #include "cpu.h" | ||
66 | #include "internals.h" | ||
67 | +#include "cpregs.h" | ||
68 | #include "exec/exec-all.h" | ||
69 | #include "exec/helper-proto.h" | ||
70 | |||
71 | @@ -XXX,XX +XXX,XX @@ void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) | ||
72 | raise_exception_debug(env, EXCP_UDEF, syndrome); | ||
73 | } | 31 | } |
74 | 32 | ||
75 | +/* | 33 | +static ARMSecuritySpace S2_security_space(ARMSecuritySpace s1_space, |
76 | + * Check for traps to "powerdown debug" registers, which are controlled | 34 | + ARMMMUIdx s2_mmu_idx) |
77 | + * by MDCR.TDOSA | ||
78 | + */ | ||
79 | +static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, | ||
80 | + bool isread) | ||
81 | +{ | ||
82 | + int el = arm_current_el(env); | ||
83 | + uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | ||
84 | + bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) || | ||
85 | + (arm_hcr_el2_eff(env) & HCR_TGE); | ||
86 | + | ||
87 | + if (el < 2 && mdcr_el2_tdosa) { | ||
88 | + return CP_ACCESS_TRAP_EL2; | ||
89 | + } | ||
90 | + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { | ||
91 | + return CP_ACCESS_TRAP_EL3; | ||
92 | + } | ||
93 | + return CP_ACCESS_OK; | ||
94 | +} | ||
95 | + | ||
96 | +/* | ||
97 | + * Check for traps to "debug ROM" registers, which are controlled | ||
98 | + * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. | ||
99 | + */ | ||
100 | +static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, | ||
101 | + bool isread) | ||
102 | +{ | ||
103 | + int el = arm_current_el(env); | ||
104 | + uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | ||
105 | + bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) || | ||
106 | + (arm_hcr_el2_eff(env) & HCR_TGE); | ||
107 | + | ||
108 | + if (el < 2 && mdcr_el2_tdra) { | ||
109 | + return CP_ACCESS_TRAP_EL2; | ||
110 | + } | ||
111 | + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { | ||
112 | + return CP_ACCESS_TRAP_EL3; | ||
113 | + } | ||
114 | + return CP_ACCESS_OK; | ||
115 | +} | ||
116 | + | ||
117 | +/* | ||
118 | + * Check for traps to general debug registers, which are controlled | ||
119 | + * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. | ||
120 | + */ | ||
121 | +static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, | ||
122 | + bool isread) | ||
123 | +{ | ||
124 | + int el = arm_current_el(env); | ||
125 | + uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | ||
126 | + bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || | ||
127 | + (arm_hcr_el2_eff(env) & HCR_TGE); | ||
128 | + | ||
129 | + if (el < 2 && mdcr_el2_tda) { | ||
130 | + return CP_ACCESS_TRAP_EL2; | ||
131 | + } | ||
132 | + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { | ||
133 | + return CP_ACCESS_TRAP_EL3; | ||
134 | + } | ||
135 | + return CP_ACCESS_OK; | ||
136 | +} | ||
137 | + | ||
138 | +static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
139 | + uint64_t value) | ||
140 | +{ | 35 | +{ |
141 | + /* | 36 | + /* |
142 | + * Writes to OSLAR_EL1 may update the OS lock status, which can be | 37 | + * Return the security space to use for stage 2 when doing |
143 | + * read via a bit in OSLSR_EL1. | 38 | + * the S1 page table descriptor load. |
144 | + */ | 39 | + */ |
145 | + int oslock; | 40 | + if (regime_is_stage2(s2_mmu_idx)) { |
146 | + | 41 | + /* |
147 | + if (ri->state == ARM_CP_STATE_AA32) { | 42 | + * The security space for ptw reads is almost always the same |
148 | + oslock = (value == 0xC5ACCE55); | 43 | + * as that of the security space of the stage 1 translation. |
44 | + * The only exception is when stage 1 is Secure; in that case | ||
45 | + * the ptw read might be to the Secure or the NonSecure space | ||
46 | + * (but never Realm or Root), and the s2_mmu_idx tells us which. | ||
47 | + * Root translations are always single-stage. | ||
48 | + */ | ||
49 | + if (s1_space == ARMSS_Secure) { | ||
50 | + return arm_secure_to_space(s2_mmu_idx == ARMMMUIdx_Stage2_S); | ||
51 | + } else { | ||
52 | + assert(s2_mmu_idx != ARMMMUIdx_Stage2_S); | ||
53 | + assert(s1_space != ARMSS_Root); | ||
54 | + return s1_space; | ||
55 | + } | ||
149 | + } else { | 56 | + } else { |
150 | + oslock = value & 1; | 57 | + /* ptw loads are from phys: the mmu idx itself says which space */ |
151 | + } | 58 | + return arm_phys_to_space(s2_mmu_idx); |
152 | + | ||
153 | + env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock); | ||
154 | +} | ||
155 | + | ||
156 | +static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
157 | + /* | ||
158 | + * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped | ||
159 | + * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; | ||
160 | + * unlike DBGDRAR it is never accessible from EL0. | ||
161 | + * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64 | ||
162 | + * accessor. | ||
163 | + */ | ||
164 | + { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, | ||
165 | + .access = PL0_R, .accessfn = access_tdra, | ||
166 | + .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
167 | + { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64, | ||
168 | + .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0, | ||
169 | + .access = PL1_R, .accessfn = access_tdra, | ||
170 | + .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
171 | + { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, | ||
172 | + .access = PL0_R, .accessfn = access_tdra, | ||
173 | + .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
174 | + /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */ | ||
175 | + { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH, | ||
176 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, | ||
177 | + .access = PL1_RW, .accessfn = access_tda, | ||
178 | + .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), | ||
179 | + .resetvalue = 0 }, | ||
180 | + /* | ||
181 | + * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external | ||
182 | + * Debug Communication Channel is not implemented. | ||
183 | + */ | ||
184 | + { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64, | ||
185 | + .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0, | ||
186 | + .access = PL0_R, .accessfn = access_tda, | ||
187 | + .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
188 | + /* | ||
189 | + * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as | ||
190 | + * it is unlikely a guest will care. | ||
191 | + * We don't implement the configurable EL0 access. | ||
192 | + */ | ||
193 | + { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32, | ||
194 | + .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, | ||
195 | + .type = ARM_CP_ALIAS, | ||
196 | + .access = PL1_R, .accessfn = access_tda, | ||
197 | + .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), }, | ||
198 | + { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH, | ||
199 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4, | ||
200 | + .access = PL1_W, .type = ARM_CP_NO_RAW, | ||
201 | + .accessfn = access_tdosa, | ||
202 | + .writefn = oslar_write }, | ||
203 | + { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH, | ||
204 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4, | ||
205 | + .access = PL1_R, .resetvalue = 10, | ||
206 | + .accessfn = access_tdosa, | ||
207 | + .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) }, | ||
208 | + /* Dummy OSDLR_EL1: 32-bit Linux will read this */ | ||
209 | + { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH, | ||
210 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, | ||
211 | + .access = PL1_RW, .accessfn = access_tdosa, | ||
212 | + .type = ARM_CP_NOP }, | ||
213 | + /* | ||
214 | + * Dummy DBGVCR: Linux wants to clear this on startup, but we don't | ||
215 | + * implement vector catch debug events yet. | ||
216 | + */ | ||
217 | + { .name = "DBGVCR", | ||
218 | + .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, | ||
219 | + .access = PL1_RW, .accessfn = access_tda, | ||
220 | + .type = ARM_CP_NOP }, | ||
221 | + /* | ||
222 | + * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor | ||
223 | + * to save and restore a 32-bit guest's DBGVCR) | ||
224 | + */ | ||
225 | + { .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64, | ||
226 | + .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0, | ||
227 | + .access = PL2_RW, .accessfn = access_tda, | ||
228 | + .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP }, | ||
229 | + /* | ||
230 | + * Dummy MDCCINT_EL1, since we don't implement the Debug Communications | ||
231 | + * Channel but Linux may try to access this register. The 32-bit | ||
232 | + * alias is DBGDCCINT. | ||
233 | + */ | ||
234 | + { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH, | ||
235 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, | ||
236 | + .access = PL1_RW, .accessfn = access_tda, | ||
237 | + .type = ARM_CP_NOP }, | ||
238 | +}; | ||
239 | + | ||
240 | +static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { | ||
241 | + /* 64 bit access versions of the (dummy) debug registers */ | ||
242 | + { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0, | ||
243 | + .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
244 | + { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0, | ||
245 | + .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
246 | +}; | ||
247 | + | ||
248 | +void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
249 | +{ | ||
250 | + CPUARMState *env = &cpu->env; | ||
251 | + vaddr len = 0; | ||
252 | + vaddr wvr = env->cp15.dbgwvr[n]; | ||
253 | + uint64_t wcr = env->cp15.dbgwcr[n]; | ||
254 | + int mask; | ||
255 | + int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; | ||
256 | + | ||
257 | + if (env->cpu_watchpoint[n]) { | ||
258 | + cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); | ||
259 | + env->cpu_watchpoint[n] = NULL; | ||
260 | + } | ||
261 | + | ||
262 | + if (!FIELD_EX64(wcr, DBGWCR, E)) { | ||
263 | + /* E bit clear : watchpoint disabled */ | ||
264 | + return; | ||
265 | + } | ||
266 | + | ||
267 | + switch (FIELD_EX64(wcr, DBGWCR, LSC)) { | ||
268 | + case 0: | ||
269 | + /* LSC 00 is reserved and must behave as if the wp is disabled */ | ||
270 | + return; | ||
271 | + case 1: | ||
272 | + flags |= BP_MEM_READ; | ||
273 | + break; | ||
274 | + case 2: | ||
275 | + flags |= BP_MEM_WRITE; | ||
276 | + break; | ||
277 | + case 3: | ||
278 | + flags |= BP_MEM_ACCESS; | ||
279 | + break; | ||
280 | + } | ||
281 | + | ||
282 | + /* | ||
283 | + * Attempts to use both MASK and BAS fields simultaneously are | ||
284 | + * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, | ||
285 | + * thus generating a watchpoint for every byte in the masked region. | ||
286 | + */ | ||
287 | + mask = FIELD_EX64(wcr, DBGWCR, MASK); | ||
288 | + if (mask == 1 || mask == 2) { | ||
289 | + /* | ||
290 | + * Reserved values of MASK; we must act as if the mask value was | ||
291 | + * some non-reserved value, or as if the watchpoint were disabled. | ||
292 | + * We choose the latter. | ||
293 | + */ | ||
294 | + return; | ||
295 | + } else if (mask) { | ||
296 | + /* Watchpoint covers an aligned area up to 2GB in size */ | ||
297 | + len = 1ULL << mask; | ||
298 | + /* | ||
299 | + * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE | ||
300 | + * whether the watchpoint fires when the unmasked bits match; we opt | ||
301 | + * to generate the exceptions. | ||
302 | + */ | ||
303 | + wvr &= ~(len - 1); | ||
304 | + } else { | ||
305 | + /* Watchpoint covers bytes defined by the byte address select bits */ | ||
306 | + int bas = FIELD_EX64(wcr, DBGWCR, BAS); | ||
307 | + int basstart; | ||
308 | + | ||
309 | + if (extract64(wvr, 2, 1)) { | ||
310 | + /* | ||
311 | + * Deprecated case of an only 4-aligned address. BAS[7:4] are | ||
312 | + * ignored, and BAS[3:0] define which bytes to watch. | ||
313 | + */ | ||
314 | + bas &= 0xf; | ||
315 | + } | ||
316 | + | ||
317 | + if (bas == 0) { | ||
318 | + /* This must act as if the watchpoint is disabled */ | ||
319 | + return; | ||
320 | + } | ||
321 | + | ||
322 | + /* | ||
323 | + * The BAS bits are supposed to be programmed to indicate a contiguous | ||
324 | + * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether | ||
325 | + * we fire for each byte in the word/doubleword addressed by the WVR. | ||
326 | + * We choose to ignore any non-zero bits after the first range of 1s. | ||
327 | + */ | ||
328 | + basstart = ctz32(bas); | ||
329 | + len = cto32(bas >> basstart); | ||
330 | + wvr += basstart; | ||
331 | + } | ||
332 | + | ||
333 | + cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, | ||
334 | + &env->cpu_watchpoint[n]); | ||
335 | +} | ||
336 | + | ||
337 | +void hw_watchpoint_update_all(ARMCPU *cpu) | ||
338 | +{ | ||
339 | + int i; | ||
340 | + CPUARMState *env = &cpu->env; | ||
341 | + | ||
342 | + /* | ||
343 | + * Completely clear out existing QEMU watchpoints and our array, to | ||
344 | + * avoid possible stale entries following migration load. | ||
345 | + */ | ||
346 | + cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); | ||
347 | + memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); | ||
348 | + | ||
349 | + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { | ||
350 | + hw_watchpoint_update(cpu, i); | ||
351 | + } | 59 | + } |
352 | +} | 60 | +} |
353 | + | 61 | + |
354 | +static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, | 62 | /* Translate a S1 pagetable walk through S2 if needed. */ |
355 | + uint64_t value) | 63 | static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw, |
356 | +{ | 64 | hwaddr addr, ARMMMUFaultInfo *fi) |
357 | + ARMCPU *cpu = env_archcpu(env); | ||
358 | + int i = ri->crm; | ||
359 | + | ||
360 | + /* | ||
361 | + * Bits [1:0] are RES0. | ||
362 | + * | ||
363 | + * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) | ||
364 | + * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if | ||
365 | + * they contain the value written. It is CONSTRAINED UNPREDICTABLE | ||
366 | + * whether the RESS bits are ignored when comparing an address. | ||
367 | + * | ||
368 | + * Therefore we are allowed to compare the entire register, which lets | ||
369 | + * us avoid considering whether or not FEAT_LVA is actually enabled. | ||
370 | + */ | ||
371 | + value &= ~3ULL; | ||
372 | + | ||
373 | + raw_write(env, ri, value); | ||
374 | + hw_watchpoint_update(cpu, i); | ||
375 | +} | ||
376 | + | ||
377 | +static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
378 | + uint64_t value) | ||
379 | +{ | ||
380 | + ARMCPU *cpu = env_archcpu(env); | ||
381 | + int i = ri->crm; | ||
382 | + | ||
383 | + raw_write(env, ri, value); | ||
384 | + hw_watchpoint_update(cpu, i); | ||
385 | +} | ||
386 | + | ||
387 | +void hw_breakpoint_update(ARMCPU *cpu, int n) | ||
388 | +{ | ||
389 | + CPUARMState *env = &cpu->env; | ||
390 | + uint64_t bvr = env->cp15.dbgbvr[n]; | ||
391 | + uint64_t bcr = env->cp15.dbgbcr[n]; | ||
392 | + vaddr addr; | ||
393 | + int bt; | ||
394 | + int flags = BP_CPU; | ||
395 | + | ||
396 | + if (env->cpu_breakpoint[n]) { | ||
397 | + cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); | ||
398 | + env->cpu_breakpoint[n] = NULL; | ||
399 | + } | ||
400 | + | ||
401 | + if (!extract64(bcr, 0, 1)) { | ||
402 | + /* E bit clear : watchpoint disabled */ | ||
403 | + return; | ||
404 | + } | ||
405 | + | ||
406 | + bt = extract64(bcr, 20, 4); | ||
407 | + | ||
408 | + switch (bt) { | ||
409 | + case 4: /* unlinked address mismatch (reserved if AArch64) */ | ||
410 | + case 5: /* linked address mismatch (reserved if AArch64) */ | ||
411 | + qemu_log_mask(LOG_UNIMP, | ||
412 | + "arm: address mismatch breakpoint types not implemented\n"); | ||
413 | + return; | ||
414 | + case 0: /* unlinked address match */ | ||
415 | + case 1: /* linked address match */ | ||
416 | + { | ||
417 | + /* | ||
418 | + * Bits [1:0] are RES0. | ||
419 | + * | ||
420 | + * It is IMPLEMENTATION DEFINED whether bits [63:49] | ||
421 | + * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit | ||
422 | + * of the VA field ([48] or [52] for FEAT_LVA), or whether the | ||
423 | + * value is read as written. It is CONSTRAINED UNPREDICTABLE | ||
424 | + * whether the RESS bits are ignored when comparing an address. | ||
425 | + * Therefore we are allowed to compare the entire register, which | ||
426 | + * lets us avoid considering whether FEAT_LVA is actually enabled. | ||
427 | + * | ||
428 | + * The BAS field is used to allow setting breakpoints on 16-bit | ||
429 | + * wide instructions; it is CONSTRAINED UNPREDICTABLE whether | ||
430 | + * a bp will fire if the addresses covered by the bp and the addresses | ||
431 | + * covered by the insn overlap but the insn doesn't start at the | ||
432 | + * start of the bp address range. We choose to require the insn and | ||
433 | + * the bp to have the same address. The constraints on writing to | ||
434 | + * BAS enforced in dbgbcr_write mean we have only four cases: | ||
435 | + * 0b0000 => no breakpoint | ||
436 | + * 0b0011 => breakpoint on addr | ||
437 | + * 0b1100 => breakpoint on addr + 2 | ||
438 | + * 0b1111 => breakpoint on addr | ||
439 | + * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). | ||
440 | + */ | ||
441 | + int bas = extract64(bcr, 5, 4); | ||
442 | + addr = bvr & ~3ULL; | ||
443 | + if (bas == 0) { | ||
444 | + return; | ||
445 | + } | ||
446 | + if (bas == 0xc) { | ||
447 | + addr += 2; | ||
448 | + } | ||
449 | + break; | ||
450 | + } | ||
451 | + case 2: /* unlinked context ID match */ | ||
452 | + case 8: /* unlinked VMID match (reserved if no EL2) */ | ||
453 | + case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ | ||
454 | + qemu_log_mask(LOG_UNIMP, | ||
455 | + "arm: unlinked context breakpoint types not implemented\n"); | ||
456 | + return; | ||
457 | + case 9: /* linked VMID match (reserved if no EL2) */ | ||
458 | + case 11: /* linked context ID and VMID match (reserved if no EL2) */ | ||
459 | + case 3: /* linked context ID match */ | ||
460 | + default: | ||
461 | + /* | ||
462 | + * We must generate no events for Linked context matches (unless | ||
463 | + * they are linked to by some other bp/wp, which is handled in | ||
464 | + * updates for the linking bp/wp). We choose to also generate no events | ||
465 | + * for reserved values. | ||
466 | + */ | ||
467 | + return; | ||
468 | + } | ||
469 | + | ||
470 | + cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); | ||
471 | +} | ||
472 | + | ||
473 | +void hw_breakpoint_update_all(ARMCPU *cpu) | ||
474 | +{ | ||
475 | + int i; | ||
476 | + CPUARMState *env = &cpu->env; | ||
477 | + | ||
478 | + /* | ||
479 | + * Completely clear out existing QEMU breakpoints and our array, to | ||
480 | + * avoid possible stale entries following migration load. | ||
481 | + */ | ||
482 | + cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); | ||
483 | + memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); | ||
484 | + | ||
485 | + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { | ||
486 | + hw_breakpoint_update(cpu, i); | ||
487 | + } | ||
488 | +} | ||
489 | + | ||
490 | +static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
491 | + uint64_t value) | ||
492 | +{ | ||
493 | + ARMCPU *cpu = env_archcpu(env); | ||
494 | + int i = ri->crm; | ||
495 | + | ||
496 | + raw_write(env, ri, value); | ||
497 | + hw_breakpoint_update(cpu, i); | ||
498 | +} | ||
499 | + | ||
500 | +static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
501 | + uint64_t value) | ||
502 | +{ | ||
503 | + ARMCPU *cpu = env_archcpu(env); | ||
504 | + int i = ri->crm; | ||
505 | + | ||
506 | + /* | ||
507 | + * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only | ||
508 | + * copy of BAS[0]. | ||
509 | + */ | ||
510 | + value = deposit64(value, 6, 1, extract64(value, 5, 1)); | ||
511 | + value = deposit64(value, 8, 1, extract64(value, 7, 1)); | ||
512 | + | ||
513 | + raw_write(env, ri, value); | ||
514 | + hw_breakpoint_update(cpu, i); | ||
515 | +} | ||
516 | + | ||
517 | +void define_debug_regs(ARMCPU *cpu) | ||
518 | +{ | ||
519 | + /* | ||
520 | + * Define v7 and v8 architectural debug registers. | ||
521 | + * These are just dummy implementations for now. | ||
522 | + */ | ||
523 | + int i; | ||
524 | + int wrps, brps, ctx_cmps; | ||
525 | + | ||
526 | + /* | ||
527 | + * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot | ||
528 | + * use AArch32. Given that bit 15 is RES1, if the value is 0 then | ||
529 | + * the register must not exist for this cpu. | ||
530 | + */ | ||
531 | + if (cpu->isar.dbgdidr != 0) { | ||
532 | + ARMCPRegInfo dbgdidr = { | ||
533 | + .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, | ||
534 | + .opc1 = 0, .opc2 = 0, | ||
535 | + .access = PL0_R, .accessfn = access_tda, | ||
536 | + .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, | ||
537 | + }; | ||
538 | + define_one_arm_cp_reg(cpu, &dbgdidr); | ||
539 | + } | ||
540 | + | ||
541 | + brps = arm_num_brps(cpu); | ||
542 | + wrps = arm_num_wrps(cpu); | ||
543 | + ctx_cmps = arm_num_ctx_cmps(cpu); | ||
544 | + | ||
545 | + assert(ctx_cmps <= brps); | ||
546 | + | ||
547 | + define_arm_cp_regs(cpu, debug_cp_reginfo); | ||
548 | + | ||
549 | + if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) { | ||
550 | + define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); | ||
551 | + } | ||
552 | + | ||
553 | + for (i = 0; i < brps; i++) { | ||
554 | + char *dbgbvr_el1_name = g_strdup_printf("DBGBVR%d_EL1", i); | ||
555 | + char *dbgbcr_el1_name = g_strdup_printf("DBGBCR%d_EL1", i); | ||
556 | + ARMCPRegInfo dbgregs[] = { | ||
557 | + { .name = dbgbvr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
558 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, | ||
559 | + .access = PL1_RW, .accessfn = access_tda, | ||
560 | + .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]), | ||
561 | + .writefn = dbgbvr_write, .raw_writefn = raw_write | ||
562 | + }, | ||
563 | + { .name = dbgbcr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
564 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5, | ||
565 | + .access = PL1_RW, .accessfn = access_tda, | ||
566 | + .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]), | ||
567 | + .writefn = dbgbcr_write, .raw_writefn = raw_write | ||
568 | + }, | ||
569 | + }; | ||
570 | + define_arm_cp_regs(cpu, dbgregs); | ||
571 | + g_free(dbgbvr_el1_name); | ||
572 | + g_free(dbgbcr_el1_name); | ||
573 | + } | ||
574 | + | ||
575 | + for (i = 0; i < wrps; i++) { | ||
576 | + char *dbgwvr_el1_name = g_strdup_printf("DBGWVR%d_EL1", i); | ||
577 | + char *dbgwcr_el1_name = g_strdup_printf("DBGWCR%d_EL1", i); | ||
578 | + ARMCPRegInfo dbgregs[] = { | ||
579 | + { .name = dbgwvr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
580 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, | ||
581 | + .access = PL1_RW, .accessfn = access_tda, | ||
582 | + .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]), | ||
583 | + .writefn = dbgwvr_write, .raw_writefn = raw_write | ||
584 | + }, | ||
585 | + { .name = dbgwcr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
586 | + .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7, | ||
587 | + .access = PL1_RW, .accessfn = access_tda, | ||
588 | + .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]), | ||
589 | + .writefn = dbgwcr_write, .raw_writefn = raw_write | ||
590 | + }, | ||
591 | + }; | ||
592 | + define_arm_cp_regs(cpu, dbgregs); | ||
593 | + g_free(dbgwvr_el1_name); | ||
594 | + g_free(dbgwcr_el1_name); | ||
595 | + } | ||
596 | +} | ||
597 | + | ||
598 | #if !defined(CONFIG_USER_ONLY) | ||
599 | |||
600 | vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) | ||
601 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
602 | index XXXXXXX..XXXXXXX 100644 | ||
603 | --- a/target/arm/helper.c | ||
604 | +++ b/target/arm/helper.c | ||
605 | @@ -XXX,XX +XXX,XX @@ static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
606 | } | ||
607 | } | ||
608 | |||
609 | -static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
610 | - uint64_t value) | ||
611 | +void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) | ||
612 | { | 65 | { |
613 | assert(ri->fieldoffset); | 66 | - ARMSecuritySpace space = ptw->in_space; |
614 | if (cpreg_field_is_64bit(ri)) { | 67 | bool is_secure = ptw->in_secure; |
615 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult access_trap_aa32s_el1(CPUARMState *env, | 68 | ARMMMUIdx mmu_idx = ptw->in_mmu_idx; |
616 | return CP_ACCESS_TRAP_UNCATEGORIZED; | 69 | ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx; |
617 | } | 70 | @@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw, |
618 | 71 | * From gdbstub, do not use softmmu so that we don't modify the | |
619 | -static uint64_t arm_mdcr_el2_eff(CPUARMState *env) | 72 | * state of the cpu at all, including softmmu tlb contents. |
620 | -{ | 73 | */ |
621 | - return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0; | 74 | + ARMSecuritySpace s2_space = S2_security_space(ptw->in_space, s2_mmu_idx); |
622 | -} | 75 | S1Translate s2ptw = { |
623 | - | 76 | .in_mmu_idx = s2_mmu_idx, |
624 | -/* | 77 | .in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx), |
625 | - * Check for traps to "powerdown debug" registers, which are controlled | 78 | - .in_secure = s2_mmu_idx == ARMMMUIdx_Stage2_S, |
626 | - * by MDCR.TDOSA | 79 | - .in_space = (s2_mmu_idx == ARMMMUIdx_Stage2_S ? ARMSS_Secure |
627 | - */ | 80 | - : space == ARMSS_Realm ? ARMSS_Realm |
628 | -static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, | 81 | - : ARMSS_NonSecure), |
629 | - bool isread) | 82 | + .in_secure = arm_space_is_secure(s2_space), |
630 | -{ | 83 | + .in_space = s2_space, |
631 | - int el = arm_current_el(env); | 84 | .in_debug = true, |
632 | - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | 85 | }; |
633 | - bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) || | 86 | GetPhysAddrResult s2 = { }; |
634 | - (arm_hcr_el2_eff(env) & HCR_TGE); | ||
635 | - | ||
636 | - if (el < 2 && mdcr_el2_tdosa) { | ||
637 | - return CP_ACCESS_TRAP_EL2; | ||
638 | - } | ||
639 | - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { | ||
640 | - return CP_ACCESS_TRAP_EL3; | ||
641 | - } | ||
642 | - return CP_ACCESS_OK; | ||
643 | -} | ||
644 | - | ||
645 | -/* | ||
646 | - * Check for traps to "debug ROM" registers, which are controlled | ||
647 | - * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. | ||
648 | - */ | ||
649 | -static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, | ||
650 | - bool isread) | ||
651 | -{ | ||
652 | - int el = arm_current_el(env); | ||
653 | - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | ||
654 | - bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) || | ||
655 | - (arm_hcr_el2_eff(env) & HCR_TGE); | ||
656 | - | ||
657 | - if (el < 2 && mdcr_el2_tdra) { | ||
658 | - return CP_ACCESS_TRAP_EL2; | ||
659 | - } | ||
660 | - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { | ||
661 | - return CP_ACCESS_TRAP_EL3; | ||
662 | - } | ||
663 | - return CP_ACCESS_OK; | ||
664 | -} | ||
665 | - | ||
666 | -/* | ||
667 | - * Check for traps to general debug registers, which are controlled | ||
668 | - * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. | ||
669 | - */ | ||
670 | -static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, | ||
671 | - bool isread) | ||
672 | -{ | ||
673 | - int el = arm_current_el(env); | ||
674 | - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); | ||
675 | - bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || | ||
676 | - (arm_hcr_el2_eff(env) & HCR_TGE); | ||
677 | - | ||
678 | - if (el < 2 && mdcr_el2_tda) { | ||
679 | - return CP_ACCESS_TRAP_EL2; | ||
680 | - } | ||
681 | - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { | ||
682 | - return CP_ACCESS_TRAP_EL3; | ||
683 | - } | ||
684 | - return CP_ACCESS_OK; | ||
685 | -} | ||
686 | - | ||
687 | /* Check for traps to performance monitor registers, which are controlled | ||
688 | * by MDCR_EL2.TPM for EL2 and MDCR_EL3.TPM for EL3. | ||
689 | */ | ||
690 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri, | ||
691 | return CP_ACCESS_OK; | ||
692 | } | ||
693 | |||
694 | -static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
695 | - uint64_t value) | ||
696 | -{ | ||
697 | - /* | ||
698 | - * Writes to OSLAR_EL1 may update the OS lock status, which can be | ||
699 | - * read via a bit in OSLSR_EL1. | ||
700 | - */ | ||
701 | - int oslock; | ||
702 | - | ||
703 | - if (ri->state == ARM_CP_STATE_AA32) { | ||
704 | - oslock = (value == 0xC5ACCE55); | ||
705 | - } else { | ||
706 | - oslock = value & 1; | ||
707 | - } | ||
708 | - | ||
709 | - env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock); | ||
710 | -} | ||
711 | - | ||
712 | -static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
713 | - /* | ||
714 | - * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped | ||
715 | - * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; | ||
716 | - * unlike DBGDRAR it is never accessible from EL0. | ||
717 | - * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64 | ||
718 | - * accessor. | ||
719 | - */ | ||
720 | - { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, | ||
721 | - .access = PL0_R, .accessfn = access_tdra, | ||
722 | - .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
723 | - { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64, | ||
724 | - .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0, | ||
725 | - .access = PL1_R, .accessfn = access_tdra, | ||
726 | - .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
727 | - { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, | ||
728 | - .access = PL0_R, .accessfn = access_tdra, | ||
729 | - .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
730 | - /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */ | ||
731 | - { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH, | ||
732 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, | ||
733 | - .access = PL1_RW, .accessfn = access_tda, | ||
734 | - .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), | ||
735 | - .resetvalue = 0 }, | ||
736 | - /* | ||
737 | - * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external | ||
738 | - * Debug Communication Channel is not implemented. | ||
739 | - */ | ||
740 | - { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64, | ||
741 | - .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0, | ||
742 | - .access = PL0_R, .accessfn = access_tda, | ||
743 | - .type = ARM_CP_CONST, .resetvalue = 0 }, | ||
744 | - /* | ||
745 | - * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as | ||
746 | - * it is unlikely a guest will care. | ||
747 | - * We don't implement the configurable EL0 access. | ||
748 | - */ | ||
749 | - { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32, | ||
750 | - .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, | ||
751 | - .type = ARM_CP_ALIAS, | ||
752 | - .access = PL1_R, .accessfn = access_tda, | ||
753 | - .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), }, | ||
754 | - { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH, | ||
755 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4, | ||
756 | - .access = PL1_W, .type = ARM_CP_NO_RAW, | ||
757 | - .accessfn = access_tdosa, | ||
758 | - .writefn = oslar_write }, | ||
759 | - { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH, | ||
760 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4, | ||
761 | - .access = PL1_R, .resetvalue = 10, | ||
762 | - .accessfn = access_tdosa, | ||
763 | - .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) }, | ||
764 | - /* Dummy OSDLR_EL1: 32-bit Linux will read this */ | ||
765 | - { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH, | ||
766 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, | ||
767 | - .access = PL1_RW, .accessfn = access_tdosa, | ||
768 | - .type = ARM_CP_NOP }, | ||
769 | - /* | ||
770 | - * Dummy DBGVCR: Linux wants to clear this on startup, but we don't | ||
771 | - * implement vector catch debug events yet. | ||
772 | - */ | ||
773 | - { .name = "DBGVCR", | ||
774 | - .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, | ||
775 | - .access = PL1_RW, .accessfn = access_tda, | ||
776 | - .type = ARM_CP_NOP }, | ||
777 | - /* | ||
778 | - * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor | ||
779 | - * to save and restore a 32-bit guest's DBGVCR) | ||
780 | - */ | ||
781 | - { .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64, | ||
782 | - .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0, | ||
783 | - .access = PL2_RW, .accessfn = access_tda, | ||
784 | - .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP }, | ||
785 | - /* | ||
786 | - * Dummy MDCCINT_EL1, since we don't implement the Debug Communications | ||
787 | - * Channel but Linux may try to access this register. The 32-bit | ||
788 | - * alias is DBGDCCINT. | ||
789 | - */ | ||
790 | - { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH, | ||
791 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, | ||
792 | - .access = PL1_RW, .accessfn = access_tda, | ||
793 | - .type = ARM_CP_NOP }, | ||
794 | -}; | ||
795 | - | ||
796 | -static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { | ||
797 | - /* 64 bit access versions of the (dummy) debug registers */ | ||
798 | - { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0, | ||
799 | - .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
800 | - { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0, | ||
801 | - .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
802 | -}; | ||
803 | - | ||
804 | /* | ||
805 | * Check for traps to RAS registers, which are controlled | ||
806 | * by HCR_EL2.TERR and SCR_EL3.TERR. | ||
807 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo sme_reginfo[] = { | ||
808 | }; | ||
809 | #endif /* TARGET_AARCH64 */ | ||
810 | |||
811 | -void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
812 | -{ | ||
813 | - CPUARMState *env = &cpu->env; | ||
814 | - vaddr len = 0; | ||
815 | - vaddr wvr = env->cp15.dbgwvr[n]; | ||
816 | - uint64_t wcr = env->cp15.dbgwcr[n]; | ||
817 | - int mask; | ||
818 | - int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; | ||
819 | - | ||
820 | - if (env->cpu_watchpoint[n]) { | ||
821 | - cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); | ||
822 | - env->cpu_watchpoint[n] = NULL; | ||
823 | - } | ||
824 | - | ||
825 | - if (!FIELD_EX64(wcr, DBGWCR, E)) { | ||
826 | - /* E bit clear : watchpoint disabled */ | ||
827 | - return; | ||
828 | - } | ||
829 | - | ||
830 | - switch (FIELD_EX64(wcr, DBGWCR, LSC)) { | ||
831 | - case 0: | ||
832 | - /* LSC 00 is reserved and must behave as if the wp is disabled */ | ||
833 | - return; | ||
834 | - case 1: | ||
835 | - flags |= BP_MEM_READ; | ||
836 | - break; | ||
837 | - case 2: | ||
838 | - flags |= BP_MEM_WRITE; | ||
839 | - break; | ||
840 | - case 3: | ||
841 | - flags |= BP_MEM_ACCESS; | ||
842 | - break; | ||
843 | - } | ||
844 | - | ||
845 | - /* | ||
846 | - * Attempts to use both MASK and BAS fields simultaneously are | ||
847 | - * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, | ||
848 | - * thus generating a watchpoint for every byte in the masked region. | ||
849 | - */ | ||
850 | - mask = FIELD_EX64(wcr, DBGWCR, MASK); | ||
851 | - if (mask == 1 || mask == 2) { | ||
852 | - /* | ||
853 | - * Reserved values of MASK; we must act as if the mask value was | ||
854 | - * some non-reserved value, or as if the watchpoint were disabled. | ||
855 | - * We choose the latter. | ||
856 | - */ | ||
857 | - return; | ||
858 | - } else if (mask) { | ||
859 | - /* Watchpoint covers an aligned area up to 2GB in size */ | ||
860 | - len = 1ULL << mask; | ||
861 | - /* | ||
862 | - * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE | ||
863 | - * whether the watchpoint fires when the unmasked bits match; we opt | ||
864 | - * to generate the exceptions. | ||
865 | - */ | ||
866 | - wvr &= ~(len - 1); | ||
867 | - } else { | ||
868 | - /* Watchpoint covers bytes defined by the byte address select bits */ | ||
869 | - int bas = FIELD_EX64(wcr, DBGWCR, BAS); | ||
870 | - int basstart; | ||
871 | - | ||
872 | - if (extract64(wvr, 2, 1)) { | ||
873 | - /* | ||
874 | - * Deprecated case of an only 4-aligned address. BAS[7:4] are | ||
875 | - * ignored, and BAS[3:0] define which bytes to watch. | ||
876 | - */ | ||
877 | - bas &= 0xf; | ||
878 | - } | ||
879 | - | ||
880 | - if (bas == 0) { | ||
881 | - /* This must act as if the watchpoint is disabled */ | ||
882 | - return; | ||
883 | - } | ||
884 | - | ||
885 | - /* | ||
886 | - * The BAS bits are supposed to be programmed to indicate a contiguous | ||
887 | - * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether | ||
888 | - * we fire for each byte in the word/doubleword addressed by the WVR. | ||
889 | - * We choose to ignore any non-zero bits after the first range of 1s. | ||
890 | - */ | ||
891 | - basstart = ctz32(bas); | ||
892 | - len = cto32(bas >> basstart); | ||
893 | - wvr += basstart; | ||
894 | - } | ||
895 | - | ||
896 | - cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, | ||
897 | - &env->cpu_watchpoint[n]); | ||
898 | -} | ||
899 | - | ||
900 | -void hw_watchpoint_update_all(ARMCPU *cpu) | ||
901 | -{ | ||
902 | - int i; | ||
903 | - CPUARMState *env = &cpu->env; | ||
904 | - | ||
905 | - /* | ||
906 | - * Completely clear out existing QEMU watchpoints and our array, to | ||
907 | - * avoid possible stale entries following migration load. | ||
908 | - */ | ||
909 | - cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); | ||
910 | - memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); | ||
911 | - | ||
912 | - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { | ||
913 | - hw_watchpoint_update(cpu, i); | ||
914 | - } | ||
915 | -} | ||
916 | - | ||
917 | -static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
918 | - uint64_t value) | ||
919 | -{ | ||
920 | - ARMCPU *cpu = env_archcpu(env); | ||
921 | - int i = ri->crm; | ||
922 | - | ||
923 | - /* | ||
924 | - * Bits [1:0] are RES0. | ||
925 | - * | ||
926 | - * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) | ||
927 | - * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if | ||
928 | - * they contain the value written. It is CONSTRAINED UNPREDICTABLE | ||
929 | - * whether the RESS bits are ignored when comparing an address. | ||
930 | - * | ||
931 | - * Therefore we are allowed to compare the entire register, which lets | ||
932 | - * us avoid considering whether or not FEAT_LVA is actually enabled. | ||
933 | - */ | ||
934 | - value &= ~3ULL; | ||
935 | - | ||
936 | - raw_write(env, ri, value); | ||
937 | - hw_watchpoint_update(cpu, i); | ||
938 | -} | ||
939 | - | ||
940 | -static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
941 | - uint64_t value) | ||
942 | -{ | ||
943 | - ARMCPU *cpu = env_archcpu(env); | ||
944 | - int i = ri->crm; | ||
945 | - | ||
946 | - raw_write(env, ri, value); | ||
947 | - hw_watchpoint_update(cpu, i); | ||
948 | -} | ||
949 | - | ||
950 | -void hw_breakpoint_update(ARMCPU *cpu, int n) | ||
951 | -{ | ||
952 | - CPUARMState *env = &cpu->env; | ||
953 | - uint64_t bvr = env->cp15.dbgbvr[n]; | ||
954 | - uint64_t bcr = env->cp15.dbgbcr[n]; | ||
955 | - vaddr addr; | ||
956 | - int bt; | ||
957 | - int flags = BP_CPU; | ||
958 | - | ||
959 | - if (env->cpu_breakpoint[n]) { | ||
960 | - cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); | ||
961 | - env->cpu_breakpoint[n] = NULL; | ||
962 | - } | ||
963 | - | ||
964 | - if (!extract64(bcr, 0, 1)) { | ||
965 | - /* E bit clear : watchpoint disabled */ | ||
966 | - return; | ||
967 | - } | ||
968 | - | ||
969 | - bt = extract64(bcr, 20, 4); | ||
970 | - | ||
971 | - switch (bt) { | ||
972 | - case 4: /* unlinked address mismatch (reserved if AArch64) */ | ||
973 | - case 5: /* linked address mismatch (reserved if AArch64) */ | ||
974 | - qemu_log_mask(LOG_UNIMP, | ||
975 | - "arm: address mismatch breakpoint types not implemented\n"); | ||
976 | - return; | ||
977 | - case 0: /* unlinked address match */ | ||
978 | - case 1: /* linked address match */ | ||
979 | - { | ||
980 | - /* | ||
981 | - * Bits [1:0] are RES0. | ||
982 | - * | ||
983 | - * It is IMPLEMENTATION DEFINED whether bits [63:49] | ||
984 | - * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit | ||
985 | - * of the VA field ([48] or [52] for FEAT_LVA), or whether the | ||
986 | - * value is read as written. It is CONSTRAINED UNPREDICTABLE | ||
987 | - * whether the RESS bits are ignored when comparing an address. | ||
988 | - * Therefore we are allowed to compare the entire register, which | ||
989 | - * lets us avoid considering whether FEAT_LVA is actually enabled. | ||
990 | - * | ||
991 | - * The BAS field is used to allow setting breakpoints on 16-bit | ||
992 | - * wide instructions; it is CONSTRAINED UNPREDICTABLE whether | ||
993 | - * a bp will fire if the addresses covered by the bp and the addresses | ||
994 | - * covered by the insn overlap but the insn doesn't start at the | ||
995 | - * start of the bp address range. We choose to require the insn and | ||
996 | - * the bp to have the same address. The constraints on writing to | ||
997 | - * BAS enforced in dbgbcr_write mean we have only four cases: | ||
998 | - * 0b0000 => no breakpoint | ||
999 | - * 0b0011 => breakpoint on addr | ||
1000 | - * 0b1100 => breakpoint on addr + 2 | ||
1001 | - * 0b1111 => breakpoint on addr | ||
1002 | - * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). | ||
1003 | - */ | ||
1004 | - int bas = extract64(bcr, 5, 4); | ||
1005 | - addr = bvr & ~3ULL; | ||
1006 | - if (bas == 0) { | ||
1007 | - return; | ||
1008 | - } | ||
1009 | - if (bas == 0xc) { | ||
1010 | - addr += 2; | ||
1011 | - } | ||
1012 | - break; | ||
1013 | - } | ||
1014 | - case 2: /* unlinked context ID match */ | ||
1015 | - case 8: /* unlinked VMID match (reserved if no EL2) */ | ||
1016 | - case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ | ||
1017 | - qemu_log_mask(LOG_UNIMP, | ||
1018 | - "arm: unlinked context breakpoint types not implemented\n"); | ||
1019 | - return; | ||
1020 | - case 9: /* linked VMID match (reserved if no EL2) */ | ||
1021 | - case 11: /* linked context ID and VMID match (reserved if no EL2) */ | ||
1022 | - case 3: /* linked context ID match */ | ||
1023 | - default: | ||
1024 | - /* | ||
1025 | - * We must generate no events for Linked context matches (unless | ||
1026 | - * they are linked to by some other bp/wp, which is handled in | ||
1027 | - * updates for the linking bp/wp). We choose to also generate no events | ||
1028 | - * for reserved values. | ||
1029 | - */ | ||
1030 | - return; | ||
1031 | - } | ||
1032 | - | ||
1033 | - cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); | ||
1034 | -} | ||
1035 | - | ||
1036 | -void hw_breakpoint_update_all(ARMCPU *cpu) | ||
1037 | -{ | ||
1038 | - int i; | ||
1039 | - CPUARMState *env = &cpu->env; | ||
1040 | - | ||
1041 | - /* | ||
1042 | - * Completely clear out existing QEMU breakpoints and our array, to | ||
1043 | - * avoid possible stale entries following migration load. | ||
1044 | - */ | ||
1045 | - cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); | ||
1046 | - memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); | ||
1047 | - | ||
1048 | - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { | ||
1049 | - hw_breakpoint_update(cpu, i); | ||
1050 | - } | ||
1051 | -} | ||
1052 | - | ||
1053 | -static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
1054 | - uint64_t value) | ||
1055 | -{ | ||
1056 | - ARMCPU *cpu = env_archcpu(env); | ||
1057 | - int i = ri->crm; | ||
1058 | - | ||
1059 | - raw_write(env, ri, value); | ||
1060 | - hw_breakpoint_update(cpu, i); | ||
1061 | -} | ||
1062 | - | ||
1063 | -static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
1064 | - uint64_t value) | ||
1065 | -{ | ||
1066 | - ARMCPU *cpu = env_archcpu(env); | ||
1067 | - int i = ri->crm; | ||
1068 | - | ||
1069 | - /* | ||
1070 | - * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only | ||
1071 | - * copy of BAS[0]. | ||
1072 | - */ | ||
1073 | - value = deposit64(value, 6, 1, extract64(value, 5, 1)); | ||
1074 | - value = deposit64(value, 8, 1, extract64(value, 7, 1)); | ||
1075 | - | ||
1076 | - raw_write(env, ri, value); | ||
1077 | - hw_breakpoint_update(cpu, i); | ||
1078 | -} | ||
1079 | - | ||
1080 | -static void define_debug_regs(ARMCPU *cpu) | ||
1081 | -{ | ||
1082 | - /* | ||
1083 | - * Define v7 and v8 architectural debug registers. | ||
1084 | - * These are just dummy implementations for now. | ||
1085 | - */ | ||
1086 | - int i; | ||
1087 | - int wrps, brps, ctx_cmps; | ||
1088 | - | ||
1089 | - /* | ||
1090 | - * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot | ||
1091 | - * use AArch32. Given that bit 15 is RES1, if the value is 0 then | ||
1092 | - * the register must not exist for this cpu. | ||
1093 | - */ | ||
1094 | - if (cpu->isar.dbgdidr != 0) { | ||
1095 | - ARMCPRegInfo dbgdidr = { | ||
1096 | - .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, | ||
1097 | - .opc1 = 0, .opc2 = 0, | ||
1098 | - .access = PL0_R, .accessfn = access_tda, | ||
1099 | - .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, | ||
1100 | - }; | ||
1101 | - define_one_arm_cp_reg(cpu, &dbgdidr); | ||
1102 | - } | ||
1103 | - | ||
1104 | - brps = arm_num_brps(cpu); | ||
1105 | - wrps = arm_num_wrps(cpu); | ||
1106 | - ctx_cmps = arm_num_ctx_cmps(cpu); | ||
1107 | - | ||
1108 | - assert(ctx_cmps <= brps); | ||
1109 | - | ||
1110 | - define_arm_cp_regs(cpu, debug_cp_reginfo); | ||
1111 | - | ||
1112 | - if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) { | ||
1113 | - define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); | ||
1114 | - } | ||
1115 | - | ||
1116 | - for (i = 0; i < brps; i++) { | ||
1117 | - char *dbgbvr_el1_name = g_strdup_printf("DBGBVR%d_EL1", i); | ||
1118 | - char *dbgbcr_el1_name = g_strdup_printf("DBGBCR%d_EL1", i); | ||
1119 | - ARMCPRegInfo dbgregs[] = { | ||
1120 | - { .name = dbgbvr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
1121 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, | ||
1122 | - .access = PL1_RW, .accessfn = access_tda, | ||
1123 | - .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]), | ||
1124 | - .writefn = dbgbvr_write, .raw_writefn = raw_write | ||
1125 | - }, | ||
1126 | - { .name = dbgbcr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
1127 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5, | ||
1128 | - .access = PL1_RW, .accessfn = access_tda, | ||
1129 | - .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]), | ||
1130 | - .writefn = dbgbcr_write, .raw_writefn = raw_write | ||
1131 | - }, | ||
1132 | - }; | ||
1133 | - define_arm_cp_regs(cpu, dbgregs); | ||
1134 | - g_free(dbgbvr_el1_name); | ||
1135 | - g_free(dbgbcr_el1_name); | ||
1136 | - } | ||
1137 | - | ||
1138 | - for (i = 0; i < wrps; i++) { | ||
1139 | - char *dbgwvr_el1_name = g_strdup_printf("DBGWVR%d_EL1", i); | ||
1140 | - char *dbgwcr_el1_name = g_strdup_printf("DBGWCR%d_EL1", i); | ||
1141 | - ARMCPRegInfo dbgregs[] = { | ||
1142 | - { .name = dbgwvr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
1143 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, | ||
1144 | - .access = PL1_RW, .accessfn = access_tda, | ||
1145 | - .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]), | ||
1146 | - .writefn = dbgwvr_write, .raw_writefn = raw_write | ||
1147 | - }, | ||
1148 | - { .name = dbgwcr_el1_name, .state = ARM_CP_STATE_BOTH, | ||
1149 | - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7, | ||
1150 | - .access = PL1_RW, .accessfn = access_tda, | ||
1151 | - .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]), | ||
1152 | - .writefn = dbgwcr_write, .raw_writefn = raw_write | ||
1153 | - }, | ||
1154 | - }; | ||
1155 | - define_arm_cp_regs(cpu, dbgregs); | ||
1156 | - g_free(dbgwvr_el1_name); | ||
1157 | - g_free(dbgwcr_el1_name); | ||
1158 | - } | ||
1159 | -} | ||
1160 | - | ||
1161 | static void define_pmu_regs(ARMCPU *cpu) | ||
1162 | { | ||
1163 | /* | ||
1164 | -- | 87 | -- |
1165 | 2.25.1 | 88 | 2.34.1 | diff view generated by jsdifflib |
1 | In commit 39a1fd25287f5d we fixed a bug in the handling of LPAE block | 1 | In get_phys_addr_twostage() the code that applies the effects of |
---|---|---|---|
2 | descriptors where we weren't correctly zeroing out some RES0 bits. | 2 | VSTCR.{SA,SW} and VTCR.{NSA,NSW} only updates result->f.attrs.secure. |
3 | However this fix has a bug because the calculation of the mask is | 3 | Now we also have f.attrs.space for FEAT_RME, we need to keep the two |
4 | done at the wrong width: in | 4 | in sync. |
5 | descaddr &= ~(page_size - 1); | ||
6 | page_size is a target_ulong, so in the 'qemu-system-arm' binary it is | ||
7 | only 32 bits, and the effect is that we always zero out the top 32 | ||
8 | bits of the calculated address. Fix the calculation by forcing the | ||
9 | mask to be calculated with the same type as descaddr. | ||
10 | 5 | ||
11 | This only affects 32-bit CPUs which support LPAE (e.g. cortex-a15) | 6 | These bits only have an effect for Secure space translations, not |
12 | when used on board models which put RAM or devices above the 4GB | 7 | for Root, so use the input in_space field to determine whether to |
13 | mark and when the 'qemu-system-arm' executable is being used. | 8 | apply them rather than the input is_secure. This doesn't actually |
14 | It was also masked in 7.0 by the main bug reported in | 9 | make a difference because Root translations are never two-stage, |
15 | https://gitlab.com/qemu-project/qemu/-/issues/1078 where the | 10 | but it's a little clearer. |
16 | virt board incorrectly does not enable 'highmem' for 32-bit CPUs. | ||
17 | 11 | ||
18 | The workaround is to use 'qemu-system-aarch64' with the same | ||
19 | command line. | ||
20 | |||
21 | Reported-by: He Zhe <zhe.he@windriver.com> | ||
22 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
23 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 13 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
24 | Message-id: 20220627134620.3190252-1-peter.maydell@linaro.org | 14 | Message-id: 20230710152130.3928330-4-peter.maydell@linaro.org |
25 | Fixes: 39a1fd25287f5de ("target/arm: Fix handling of LPAE block descriptors") | ||
26 | Cc: qemu-stable@nongnu.org | ||
27 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
28 | --- | 15 | --- |
29 | target/arm/ptw.c | 2 +- | 16 | target/arm/ptw.c | 13 ++++++++----- |
30 | 1 file changed, 1 insertion(+), 1 deletion(-) | 17 | 1 file changed, 8 insertions(+), 5 deletions(-) |
31 | 18 | ||
32 | diff --git a/target/arm/ptw.c b/target/arm/ptw.c | 19 | diff --git a/target/arm/ptw.c b/target/arm/ptw.c |
33 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/target/arm/ptw.c | 21 | --- a/target/arm/ptw.c |
35 | +++ b/target/arm/ptw.c | 22 | +++ b/target/arm/ptw.c |
36 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, | 23 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, |
37 | * clear the lower bits here before ORing in the low vaddr bits. | 24 | hwaddr ipa; |
38 | */ | 25 | int s1_prot, s1_lgpgsz; |
39 | page_size = (1ULL << ((stride * (4 - level)) + 3)); | 26 | bool is_secure = ptw->in_secure; |
40 | - descaddr &= ~(page_size - 1); | 27 | + ARMSecuritySpace in_space = ptw->in_space; |
41 | + descaddr &= ~(hwaddr)(page_size - 1); | 28 | bool ret, ipa_secure; |
42 | descaddr |= (address & (page_size - 1)); | 29 | ARMCacheAttrs cacheattrs1; |
43 | /* Extract attributes from the descriptor */ | 30 | ARMSecuritySpace ipa_space; |
44 | attrs = extract64(descriptor, 2, 10) | 31 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, |
32 | * Check if IPA translates to secure or non-secure PA space. | ||
33 | * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA. | ||
34 | */ | ||
35 | - result->f.attrs.secure = | ||
36 | - (is_secure | ||
37 | - && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)) | ||
38 | - && (ipa_secure | ||
39 | - || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW)))); | ||
40 | + if (in_space == ARMSS_Secure) { | ||
41 | + result->f.attrs.secure = | ||
42 | + !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)) | ||
43 | + && (ipa_secure | ||
44 | + || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))); | ||
45 | + result->f.attrs.space = arm_secure_to_space(result->f.attrs.secure); | ||
46 | + } | ||
47 | |||
48 | return false; | ||
49 | } | ||
45 | -- | 50 | -- |
46 | 2.25.1 | 51 | 2.34.1 | diff view generated by jsdifflib |
1 | From: "Jason A. Donenfeld" <Jason@zx2c4.com> | 1 | In commit f0a08b0913befbd we changed the type of the PC from |
---|---|---|---|
2 | target_ulong to vaddr. In doing so we inadvertently dropped the | ||
3 | zero-padding on the PC in trace lines (the second item inside the [] | ||
4 | in these lines). They used to look like this on AArch64, for | ||
5 | instance: | ||
2 | 6 | ||
3 | In 60592cfed2 ("hw/arm/virt: dt: add kaslr-seed property"), the | 7 | Trace 0: 0x7f2260000100 [00000000/0000000040000000/00000061/ff200000] |
4 | kaslr-seed property was added, but the equally as important rng-seed | ||
5 | property was forgotten about, which has identical semantics for a | ||
6 | similar purpose. This commit implements it in exactly the same way as | ||
7 | kaslr-seed. It then changes the name of the disabling option to reflect | ||
8 | that this has more to do with randomness vs determinism, rather than | ||
9 | something particular about kaslr. | ||
10 | 8 | ||
11 | Cc: Peter Maydell <peter.maydell@linaro.org> | 9 | and now they look like this: |
12 | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> | 10 | Trace 0: 0x7f4f50000100 [00000000/40000000/00000061/ff200000] |
13 | [PMM: added deprecated.rst section for the deprecation] | 11 | |
14 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 12 | and if the PC happens to be somewhere low like 0x5000 |
13 | then the field is shown as /5000/. | ||
14 | |||
15 | This is because TARGET_FMT_lx is a "%08x" or "%016x" specifier, | ||
16 | depending on TARGET_LONG_SIZE, whereas VADDR_PRIx is just PRIx64 | ||
17 | with no width specifier. | ||
18 | |||
19 | Restore the zero-padding by adding an 016 width specifier to | ||
20 | this tracing and a couple of others that were similarly recently | ||
21 | changed to use VADDR_PRIx without a width specifier. | ||
22 | |||
23 | We can't unfortunately restore the "32-bit guests are padded to | ||
24 | 8 hex digits and 64-bit guests to 16 hex digits" behaviour so | ||
25 | easily. | ||
26 | |||
27 | Fixes: f0a08b0913befbd ("accel/tcg/cpu-exec.c: Widen pc to vaddr") | ||
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 28 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
29 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
30 | Reviewed-by: Anton Johansson <anjo@rev.ng> | ||
31 | Message-id: 20230711165434.4123674-1-peter.maydell@linaro.org | ||
16 | --- | 32 | --- |
17 | docs/about/deprecated.rst | 8 +++++++ | 33 | accel/tcg/cpu-exec.c | 4 ++-- |
18 | docs/system/arm/virt.rst | 17 +++++++++------ | 34 | accel/tcg/translate-all.c | 2 +- |
19 | include/hw/arm/virt.h | 2 +- | 35 | 2 files changed, 3 insertions(+), 3 deletions(-) |
20 | hw/arm/virt.c | 44 ++++++++++++++++++++++++--------------- | ||
21 | 4 files changed, 47 insertions(+), 24 deletions(-) | ||
22 | 36 | ||
23 | diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst | 37 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c |
24 | index XXXXXXX..XXXXXXX 100644 | 38 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/docs/about/deprecated.rst | 39 | --- a/accel/tcg/cpu-exec.c |
26 | +++ b/docs/about/deprecated.rst | 40 | +++ b/accel/tcg/cpu-exec.c |
27 | @@ -XXX,XX +XXX,XX @@ Use the more generic event ``DEVICE_UNPLUG_GUEST_ERROR`` instead. | 41 | @@ -XXX,XX +XXX,XX @@ static void log_cpu_exec(vaddr pc, CPUState *cpu, |
28 | System emulator machines | 42 | if (qemu_log_in_addr_range(pc)) { |
29 | ------------------------ | 43 | qemu_log_mask(CPU_LOG_EXEC, |
30 | 44 | "Trace %d: %p [%08" PRIx64 | |
31 | +Arm ``virt`` machine ``dtb-kaslr-seed`` property | 45 | - "/%" VADDR_PRIx "/%08x/%08x] %s\n", |
32 | +'''''''''''''''''''''''''''''''''''''''''''''''' | 46 | + "/%016" VADDR_PRIx "/%08x/%08x] %s\n", |
33 | + | 47 | cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc, |
34 | +The ``dtb-kaslr-seed`` property on the ``virt`` board has been | 48 | tb->flags, tb->cflags, lookup_symbol(pc)); |
35 | +deprecated; use the new name ``dtb-randomness`` instead. The new name | 49 | |
36 | +better reflects the way this property affects all random data within | 50 | @@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) |
37 | +the device tree blob, not just the ``kaslr-seed`` node. | 51 | if (qemu_loglevel_mask(CPU_LOG_EXEC)) { |
38 | + | 52 | vaddr pc = log_pc(cpu, last_tb); |
39 | PPC 405 ``taihu`` machine (since 7.0) | 53 | if (qemu_log_in_addr_range(pc)) { |
40 | ''''''''''''''''''''''''''''''''''''' | 54 | - qemu_log("Stopped execution of TB chain before %p [%" |
41 | 55 | + qemu_log("Stopped execution of TB chain before %p [%016" | |
42 | diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst | 56 | VADDR_PRIx "] %s\n", |
57 | last_tb->tc.ptr, pc, lookup_symbol(pc)); | ||
58 | } | ||
59 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | ||
43 | index XXXXXXX..XXXXXXX 100644 | 60 | index XXXXXXX..XXXXXXX 100644 |
44 | --- a/docs/system/arm/virt.rst | 61 | --- a/accel/tcg/translate-all.c |
45 | +++ b/docs/system/arm/virt.rst | 62 | +++ b/accel/tcg/translate-all.c |
46 | @@ -XXX,XX +XXX,XX @@ ras | 63 | @@ -XXX,XX +XXX,XX @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) |
47 | Set ``on``/``off`` to enable/disable reporting host memory errors to a guest | 64 | if (qemu_loglevel_mask(CPU_LOG_EXEC)) { |
48 | using ACPI and guest external abort exceptions. The default is off. | 65 | vaddr pc = log_pc(cpu, tb); |
49 | 66 | if (qemu_log_in_addr_range(pc)) { | |
50 | +dtb-randomness | 67 | - qemu_log("cpu_io_recompile: rewound execution of TB to %" |
51 | + Set ``on``/``off`` to pass random seeds via the guest DTB | 68 | + qemu_log("cpu_io_recompile: rewound execution of TB to %016" |
52 | + rng-seed and kaslr-seed nodes (in both "/chosen" and | 69 | VADDR_PRIx "\n", pc); |
53 | + "/secure-chosen") to use for features like the random number | ||
54 | + generator and address space randomisation. The default is | ||
55 | + ``on``. You will want to disable it if your trusted boot chain | ||
56 | + will verify the DTB it is passed, since this option causes the | ||
57 | + DTB to be non-deterministic. It would be the responsibility of | ||
58 | + the firmware to come up with a seed and pass it on if it wants to. | ||
59 | + | ||
60 | dtb-kaslr-seed | ||
61 | - Set ``on``/``off`` to pass a random seed via the guest dtb | ||
62 | - kaslr-seed node (in both "/chosen" and /secure-chosen) to use | ||
63 | - for features like address space randomisation. The default is | ||
64 | - ``on``. You will want to disable it if your trusted boot chain will | ||
65 | - verify the DTB it is passed. It would be the responsibility of the | ||
66 | - firmware to come up with a seed and pass it on if it wants to. | ||
67 | + A deprecated synonym for dtb-randomness. | ||
68 | |||
69 | Linux guest kernel configuration | ||
70 | """""""""""""""""""""""""""""""" | ||
71 | diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/include/hw/arm/virt.h | ||
74 | +++ b/include/hw/arm/virt.h | ||
75 | @@ -XXX,XX +XXX,XX @@ struct VirtMachineState { | ||
76 | bool virt; | ||
77 | bool ras; | ||
78 | bool mte; | ||
79 | - bool dtb_kaslr_seed; | ||
80 | + bool dtb_randomness; | ||
81 | OnOffAuto acpi; | ||
82 | VirtGICType gic_version; | ||
83 | VirtIOMMUType iommu; | ||
84 | diff --git a/hw/arm/virt.c b/hw/arm/virt.c | ||
85 | index XXXXXXX..XXXXXXX 100644 | ||
86 | --- a/hw/arm/virt.c | ||
87 | +++ b/hw/arm/virt.c | ||
88 | @@ -XXX,XX +XXX,XX @@ static bool cpu_type_valid(const char *cpu) | ||
89 | return false; | ||
90 | } | ||
91 | |||
92 | -static void create_kaslr_seed(MachineState *ms, const char *node) | ||
93 | +static void create_randomness(MachineState *ms, const char *node) | ||
94 | { | ||
95 | - uint64_t seed; | ||
96 | + struct { | ||
97 | + uint64_t kaslr; | ||
98 | + uint8_t rng[32]; | ||
99 | + } seed; | ||
100 | |||
101 | if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) { | ||
102 | return; | ||
103 | } | ||
104 | - qemu_fdt_setprop_u64(ms->fdt, node, "kaslr-seed", seed); | ||
105 | + qemu_fdt_setprop_u64(ms->fdt, node, "kaslr-seed", seed.kaslr); | ||
106 | + qemu_fdt_setprop(ms->fdt, node, "rng-seed", seed.rng, sizeof(seed.rng)); | ||
107 | } | ||
108 | |||
109 | static void create_fdt(VirtMachineState *vms) | ||
110 | @@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms) | ||
111 | |||
112 | /* /chosen must exist for load_dtb to fill in necessary properties later */ | ||
113 | qemu_fdt_add_subnode(fdt, "/chosen"); | ||
114 | - if (vms->dtb_kaslr_seed) { | ||
115 | - create_kaslr_seed(ms, "/chosen"); | ||
116 | + if (vms->dtb_randomness) { | ||
117 | + create_randomness(ms, "/chosen"); | ||
118 | } | ||
119 | |||
120 | if (vms->secure) { | ||
121 | qemu_fdt_add_subnode(fdt, "/secure-chosen"); | ||
122 | - if (vms->dtb_kaslr_seed) { | ||
123 | - create_kaslr_seed(ms, "/secure-chosen"); | ||
124 | + if (vms->dtb_randomness) { | ||
125 | + create_randomness(ms, "/secure-chosen"); | ||
126 | } | 70 | } |
127 | } | 71 | } |
128 | |||
129 | @@ -XXX,XX +XXX,XX @@ static void virt_set_its(Object *obj, bool value, Error **errp) | ||
130 | vms->its = value; | ||
131 | } | ||
132 | |||
133 | -static bool virt_get_dtb_kaslr_seed(Object *obj, Error **errp) | ||
134 | +static bool virt_get_dtb_randomness(Object *obj, Error **errp) | ||
135 | { | ||
136 | VirtMachineState *vms = VIRT_MACHINE(obj); | ||
137 | |||
138 | - return vms->dtb_kaslr_seed; | ||
139 | + return vms->dtb_randomness; | ||
140 | } | ||
141 | |||
142 | -static void virt_set_dtb_kaslr_seed(Object *obj, bool value, Error **errp) | ||
143 | +static void virt_set_dtb_randomness(Object *obj, bool value, Error **errp) | ||
144 | { | ||
145 | VirtMachineState *vms = VIRT_MACHINE(obj); | ||
146 | |||
147 | - vms->dtb_kaslr_seed = value; | ||
148 | + vms->dtb_randomness = value; | ||
149 | } | ||
150 | |||
151 | static char *virt_get_oem_id(Object *obj, Error **errp) | ||
152 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data) | ||
153 | "Set on/off to enable/disable " | ||
154 | "ITS instantiation"); | ||
155 | |||
156 | + object_class_property_add_bool(oc, "dtb-randomness", | ||
157 | + virt_get_dtb_randomness, | ||
158 | + virt_set_dtb_randomness); | ||
159 | + object_class_property_set_description(oc, "dtb-randomness", | ||
160 | + "Set off to disable passing random or " | ||
161 | + "non-deterministic dtb nodes to guest"); | ||
162 | + | ||
163 | object_class_property_add_bool(oc, "dtb-kaslr-seed", | ||
164 | - virt_get_dtb_kaslr_seed, | ||
165 | - virt_set_dtb_kaslr_seed); | ||
166 | + virt_get_dtb_randomness, | ||
167 | + virt_set_dtb_randomness); | ||
168 | object_class_property_set_description(oc, "dtb-kaslr-seed", | ||
169 | - "Set off to disable passing of kaslr-seed " | ||
170 | - "dtb node to guest"); | ||
171 | + "Deprecated synonym of dtb-randomness"); | ||
172 | |||
173 | object_class_property_add_str(oc, "x-oem-id", | ||
174 | virt_get_oem_id, | ||
175 | @@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj) | ||
176 | /* MTE is disabled by default. */ | ||
177 | vms->mte = false; | ||
178 | |||
179 | - /* Supply a kaslr-seed by default */ | ||
180 | - vms->dtb_kaslr_seed = true; | ||
181 | + /* Supply kaslr-seed and rng-seed by default */ | ||
182 | + vms->dtb_randomness = true; | ||
183 | |||
184 | vms->irqmap = a15irqmap; | ||
185 | |||
186 | -- | 72 | -- |
187 | 2.25.1 | 73 | 2.34.1 |
74 | |||
75 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Richard Henderson <richard.henderson@linaro.org> | ||
2 | 1 | ||
3 | The comment was correct, but the test was not: | ||
4 | disable mte if tagged is *not* set. | ||
5 | |||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | --- | ||
10 | target/arm/sve_helper.c | 2 +- | ||
11 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
12 | |||
13 | diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/sve_helper.c | ||
16 | +++ b/target/arm/sve_helper.c | ||
17 | @@ -XXX,XX +XXX,XX @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, | ||
18 | * Disable MTE checking if the Tagged bit is not set. Since TBI must | ||
19 | * be set within MTEDESC for MTE, !mtedesc => !mte_active. | ||
20 | */ | ||
21 | - if (arm_tlb_mte_tagged(&info.page[0].attrs)) { | ||
22 | + if (!arm_tlb_mte_tagged(&info.page[0].attrs)) { | ||
23 | mtedesc = 0; | ||
24 | } | ||
25 | |||
26 | -- | ||
27 | 2.25.1 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Before moving debug system register helper functions to a | ||
2 | different file, fix the code style issues (mostly block | ||
3 | comment syntax) so checkpatch doesn't complain about the | ||
4 | code-motion patch. | ||
5 | 1 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20220630194116.3438513-2-peter.maydell@linaro.org | ||
9 | --- | ||
10 | target/arm/helper.c | 58 +++++++++++++++++++++++++++++---------------- | ||
11 | 1 file changed, 38 insertions(+), 20 deletions(-) | ||
12 | |||
13 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/helper.c | ||
16 | +++ b/target/arm/helper.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static uint64_t arm_mdcr_el2_eff(CPUARMState *env) | ||
18 | return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0; | ||
19 | } | ||
20 | |||
21 | -/* Check for traps to "powerdown debug" registers, which are controlled | ||
22 | +/* | ||
23 | + * Check for traps to "powerdown debug" registers, which are controlled | ||
24 | * by MDCR.TDOSA | ||
25 | */ | ||
26 | static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, | ||
27 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, | ||
28 | return CP_ACCESS_OK; | ||
29 | } | ||
30 | |||
31 | -/* Check for traps to "debug ROM" registers, which are controlled | ||
32 | +/* | ||
33 | + * Check for traps to "debug ROM" registers, which are controlled | ||
34 | * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. | ||
35 | */ | ||
36 | static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, | ||
37 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, | ||
38 | return CP_ACCESS_OK; | ||
39 | } | ||
40 | |||
41 | -/* Check for traps to general debug registers, which are controlled | ||
42 | +/* | ||
43 | + * Check for traps to general debug registers, which are controlled | ||
44 | * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. | ||
45 | */ | ||
46 | static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, | ||
47 | @@ -XXX,XX +XXX,XX @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri, | ||
48 | static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
49 | uint64_t value) | ||
50 | { | ||
51 | - /* Writes to OSLAR_EL1 may update the OS lock status, which can be | ||
52 | + /* | ||
53 | + * Writes to OSLAR_EL1 may update the OS lock status, which can be | ||
54 | * read via a bit in OSLSR_EL1. | ||
55 | */ | ||
56 | int oslock; | ||
57 | @@ -XXX,XX +XXX,XX @@ static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
58 | } | ||
59 | |||
60 | static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
61 | - /* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped | ||
62 | + /* | ||
63 | + * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped | ||
64 | * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; | ||
65 | * unlike DBGDRAR it is never accessible from EL0. | ||
66 | * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64 | ||
67 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
68 | .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, | ||
69 | .access = PL1_RW, .accessfn = access_tdosa, | ||
70 | .type = ARM_CP_NOP }, | ||
71 | - /* Dummy DBGVCR: Linux wants to clear this on startup, but we don't | ||
72 | + /* | ||
73 | + * Dummy DBGVCR: Linux wants to clear this on startup, but we don't | ||
74 | * implement vector catch debug events yet. | ||
75 | */ | ||
76 | { .name = "DBGVCR", | ||
77 | .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, | ||
78 | .access = PL1_RW, .accessfn = access_tda, | ||
79 | .type = ARM_CP_NOP }, | ||
80 | - /* Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor | ||
81 | + /* | ||
82 | + * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor | ||
83 | * to save and restore a 32-bit guest's DBGVCR) | ||
84 | */ | ||
85 | { .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64, | ||
86 | .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0, | ||
87 | .access = PL2_RW, .accessfn = access_tda, | ||
88 | .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP }, | ||
89 | - /* Dummy MDCCINT_EL1, since we don't implement the Debug Communications | ||
90 | + /* | ||
91 | + * Dummy MDCCINT_EL1, since we don't implement the Debug Communications | ||
92 | * Channel but Linux may try to access this register. The 32-bit | ||
93 | * alias is DBGDCCINT. | ||
94 | */ | ||
95 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
96 | static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { | ||
97 | /* 64 bit access versions of the (dummy) debug registers */ | ||
98 | { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0, | ||
99 | - .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 }, | ||
100 | + .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
101 | { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0, | ||
102 | - .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 }, | ||
103 | + .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 }, | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | @@ -XXX,XX +XXX,XX @@ void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
108 | break; | ||
109 | } | ||
110 | |||
111 | - /* Attempts to use both MASK and BAS fields simultaneously are | ||
112 | + /* | ||
113 | + * Attempts to use both MASK and BAS fields simultaneously are | ||
114 | * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, | ||
115 | * thus generating a watchpoint for every byte in the masked region. | ||
116 | */ | ||
117 | mask = FIELD_EX64(wcr, DBGWCR, MASK); | ||
118 | if (mask == 1 || mask == 2) { | ||
119 | - /* Reserved values of MASK; we must act as if the mask value was | ||
120 | + /* | ||
121 | + * Reserved values of MASK; we must act as if the mask value was | ||
122 | * some non-reserved value, or as if the watchpoint were disabled. | ||
123 | * We choose the latter. | ||
124 | */ | ||
125 | @@ -XXX,XX +XXX,XX @@ void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
126 | } else if (mask) { | ||
127 | /* Watchpoint covers an aligned area up to 2GB in size */ | ||
128 | len = 1ULL << mask; | ||
129 | - /* If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE | ||
130 | + /* | ||
131 | + * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE | ||
132 | * whether the watchpoint fires when the unmasked bits match; we opt | ||
133 | * to generate the exceptions. | ||
134 | */ | ||
135 | @@ -XXX,XX +XXX,XX @@ void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
136 | int basstart; | ||
137 | |||
138 | if (extract64(wvr, 2, 1)) { | ||
139 | - /* Deprecated case of an only 4-aligned address. BAS[7:4] are | ||
140 | + /* | ||
141 | + * Deprecated case of an only 4-aligned address. BAS[7:4] are | ||
142 | * ignored, and BAS[3:0] define which bytes to watch. | ||
143 | */ | ||
144 | bas &= 0xf; | ||
145 | @@ -XXX,XX +XXX,XX @@ void hw_watchpoint_update(ARMCPU *cpu, int n) | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | - /* The BAS bits are supposed to be programmed to indicate a contiguous | ||
150 | + /* | ||
151 | + * The BAS bits are supposed to be programmed to indicate a contiguous | ||
152 | * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether | ||
153 | * we fire for each byte in the word/doubleword addressed by the WVR. | ||
154 | * We choose to ignore any non-zero bits after the first range of 1s. | ||
155 | @@ -XXX,XX +XXX,XX @@ void hw_watchpoint_update_all(ARMCPU *cpu) | ||
156 | int i; | ||
157 | CPUARMState *env = &cpu->env; | ||
158 | |||
159 | - /* Completely clear out existing QEMU watchpoints and our array, to | ||
160 | + /* | ||
161 | + * Completely clear out existing QEMU watchpoints and our array, to | ||
162 | * avoid possible stale entries following migration load. | ||
163 | */ | ||
164 | cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); | ||
165 | @@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n) | ||
166 | case 11: /* linked context ID and VMID match (reserved if no EL2) */ | ||
167 | case 3: /* linked context ID match */ | ||
168 | default: | ||
169 | - /* We must generate no events for Linked context matches (unless | ||
170 | + /* | ||
171 | + * We must generate no events for Linked context matches (unless | ||
172 | * they are linked to by some other bp/wp, which is handled in | ||
173 | * updates for the linking bp/wp). We choose to also generate no events | ||
174 | * for reserved values. | ||
175 | @@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update_all(ARMCPU *cpu) | ||
176 | int i; | ||
177 | CPUARMState *env = &cpu->env; | ||
178 | |||
179 | - /* Completely clear out existing QEMU breakpoints and our array, to | ||
180 | + /* | ||
181 | + * Completely clear out existing QEMU breakpoints and our array, to | ||
182 | * avoid possible stale entries following migration load. | ||
183 | */ | ||
184 | cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); | ||
185 | @@ -XXX,XX +XXX,XX @@ static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
186 | ARMCPU *cpu = env_archcpu(env); | ||
187 | int i = ri->crm; | ||
188 | |||
189 | - /* BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only | ||
190 | + /* | ||
191 | + * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only | ||
192 | * copy of BAS[0]. | ||
193 | */ | ||
194 | value = deposit64(value, 6, 1, extract64(value, 5, 1)); | ||
195 | @@ -XXX,XX +XXX,XX @@ static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
196 | |||
197 | static void define_debug_regs(ARMCPU *cpu) | ||
198 | { | ||
199 | - /* Define v7 and v8 architectural debug registers. | ||
200 | + /* | ||
201 | + * Define v7 and v8 architectural debug registers. | ||
202 | * These are just dummy implementations for now. | ||
203 | */ | ||
204 | int i; | ||
205 | -- | ||
206 | 2.25.1 | diff view generated by jsdifflib |
1 | The architecture defines the OS DoubleLock as a register which | 1 | From: Tong Ho <tong.ho@amd.com> |
---|---|---|---|
2 | (similarly to the OS Lock) suppresses debug events for use in CPU | ||
3 | powerdown sequences. This functionality is required in Arm v7 and | ||
4 | v8.0; from v8.2 it becomes optional and in v9 it must not be | ||
5 | implemented. | ||
6 | 2 | ||
7 | Currently in QEMU we implement the OSDLR_EL1 register as a NOP. This | 3 | Add a check in the bit-set operation to write the backstore |
8 | is wrong both for the "feature implemented" and the "feature not | 4 | only if the affected bit is 0 before. |
9 | implemented" cases: if the feature is implemented then the DLK bit | ||
10 | should read as written and cause suppression of debug exceptions, and | ||
11 | if it is not implemented then the bit must be RAZ/WI. | ||
12 | 5 | ||
13 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 6 | With this in place, there will be no need for callers to |
7 | do the checking in order to avoid unnecessary writes. | ||
8 | |||
9 | Signed-off-by: Tong Ho <tong.ho@amd.com> | ||
10 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
11 | Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
15 | --- | 14 | --- |
16 | target/arm/cpu.h | 20 ++++++++++++++++++++ | 15 | hw/nvram/xlnx-efuse.c | 11 +++++++++-- |
17 | target/arm/debug_helper.c | 20 ++++++++++++++++++-- | 16 | 1 file changed, 9 insertions(+), 2 deletions(-) |
18 | 2 files changed, 38 insertions(+), 2 deletions(-) | ||
19 | 17 | ||
20 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 18 | diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c |
21 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/target/arm/cpu.h | 20 | --- a/hw/nvram/xlnx-efuse.c |
23 | +++ b/target/arm/cpu.h | 21 | +++ b/hw/nvram/xlnx-efuse.c |
24 | @@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState { | 22 | @@ -XXX,XX +XXX,XX @@ static bool efuse_ro_bits_find(XlnxEFuse *s, uint32_t k) |
25 | uint64_t dbgwcr[16]; /* watchpoint control registers */ | 23 | |
26 | uint64_t mdscr_el1; | 24 | bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit) |
27 | uint64_t oslsr_el1; /* OS Lock Status */ | 25 | { |
28 | + uint64_t osdlr_el1; /* OS DoubleLock status */ | 26 | + uint32_t set, *row; |
29 | uint64_t mdcr_el2; | ||
30 | uint64_t mdcr_el3; | ||
31 | /* Stores the architectural value of the counter *the last time it was | ||
32 | @@ -XXX,XX +XXX,XX @@ FIELD(DBGDIDR, CTX_CMPS, 20, 4) | ||
33 | FIELD(DBGDIDR, BRPS, 24, 4) | ||
34 | FIELD(DBGDIDR, WRPS, 28, 4) | ||
35 | |||
36 | +FIELD(DBGDEVID, PCSAMPLE, 0, 4) | ||
37 | +FIELD(DBGDEVID, WPADDRMASK, 4, 4) | ||
38 | +FIELD(DBGDEVID, BPADDRMASK, 8, 4) | ||
39 | +FIELD(DBGDEVID, VECTORCATCH, 12, 4) | ||
40 | +FIELD(DBGDEVID, VIRTEXTNS, 16, 4) | ||
41 | +FIELD(DBGDEVID, DOUBLELOCK, 20, 4) | ||
42 | +FIELD(DBGDEVID, AUXREGS, 24, 4) | ||
43 | +FIELD(DBGDEVID, CIDMASK, 28, 4) | ||
44 | + | 27 | + |
45 | FIELD(MVFR0, SIMDREG, 0, 4) | 28 | if (efuse_ro_bits_find(s, bit)) { |
46 | FIELD(MVFR0, FPSP, 4, 4) | 29 | g_autofree char *path = object_get_canonical_path(OBJECT(s)); |
47 | FIELD(MVFR0, FPDP, 8, 4) | 30 | |
48 | @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) | 31 | @@ -XXX,XX +XXX,XX @@ bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit) |
49 | return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; | ||
50 | } | ||
51 | |||
52 | +static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) | ||
53 | +{ | ||
54 | + return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0; | ||
55 | +} | ||
56 | + | ||
57 | /* | ||
58 | * 64-bit feature tests via id registers. | ||
59 | */ | ||
60 | @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) | ||
61 | return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); | ||
62 | } | ||
63 | |||
64 | +static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) | ||
65 | +{ | ||
66 | + return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; | ||
67 | +} | ||
68 | + | ||
69 | /* | ||
70 | * Feature tests for "does this exist in either 32-bit or 64-bit?" | ||
71 | */ | ||
72 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | ||
73 | index XXXXXXX..XXXXXXX 100644 | ||
74 | --- a/target/arm/debug_helper.c | ||
75 | +++ b/target/arm/debug_helper.c | ||
76 | @@ -XXX,XX +XXX,XX @@ static bool aa32_generate_debug_exceptions(CPUARMState *env) | ||
77 | */ | ||
78 | bool arm_generate_debug_exceptions(CPUARMState *env) | ||
79 | { | ||
80 | - if (env->cp15.oslsr_el1 & 1) { | ||
81 | + if ((env->cp15.oslsr_el1 & 1) || (env->cp15.osdlr_el1 & 1)) { | ||
82 | return false; | 32 | return false; |
83 | } | 33 | } |
84 | if (is_a64(env)) { | 34 | |
85 | @@ -XXX,XX +XXX,XX @@ static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, | 35 | - s->fuse32[bit / 32] |= 1 << (bit % 32); |
86 | env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock); | 36 | - efuse_bdrv_sync(s, bit); |
37 | + /* Avoid back-end write unless there is a real update */ | ||
38 | + row = &s->fuse32[bit / 32]; | ||
39 | + set = 1 << (bit % 32); | ||
40 | + if (!(set & *row)) { | ||
41 | + *row |= set; | ||
42 | + efuse_bdrv_sync(s, bit); | ||
43 | + } | ||
44 | return true; | ||
87 | } | 45 | } |
88 | 46 | ||
89 | +static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
90 | + uint64_t value) | ||
91 | +{ | ||
92 | + ARMCPU *cpu = env_archcpu(env); | ||
93 | + /* | ||
94 | + * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not | ||
95 | + * implemented this is RAZ/WI. | ||
96 | + */ | ||
97 | + if(arm_feature(env, ARM_FEATURE_AARCH64) | ||
98 | + ? cpu_isar_feature(aa64_doublelock, cpu) | ||
99 | + : cpu_isar_feature(aa32_doublelock, cpu)) { | ||
100 | + env->cp15.osdlr_el1 = value & 1; | ||
101 | + } | ||
102 | +} | ||
103 | + | ||
104 | static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
105 | /* | ||
106 | * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped | ||
107 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = { | ||
108 | { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH, | ||
109 | .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, | ||
110 | .access = PL1_RW, .accessfn = access_tdosa, | ||
111 | - .type = ARM_CP_NOP }, | ||
112 | + .writefn = osdlr_write, | ||
113 | + .fieldoffset = offsetof(CPUARMState, cp15.osdlr_el1) }, | ||
114 | /* | ||
115 | * Dummy DBGVCR: Linux wants to clear this on startup, but we don't | ||
116 | * implement vector catch debug events yet. | ||
117 | -- | 47 | -- |
118 | 2.25.1 | 48 | 2.34.1 |
49 | |||
50 | diff view generated by jsdifflib |