1 | Some tlb instructions get the tlb_ps from tlb->misc but the | 1 | Some tlb instructions get the tlb_ps from tlb->misc but the |
---|---|---|---|
2 | value may has been initialized to 0,just check the tlb_e skip | 2 | value may has been initialized to 0,just check the tlb_e skip |
3 | the function and check_tlb_ps write a log. | 3 | the function and check_tlb_ps write a log. |
4 | 4 | ||
5 | For LoongArch th min tlb_ps is 12(4KB), for TLB code, | 5 | For LoongArch th min tlb_ps is 12(4KB), for TLB code, |
6 | the tlb_ps may be 0,this may case UndefinedBehavior | 6 | the tlb_ps may be 0,this may case UndefinedBehavior |
7 | Add a check-tlb_ps fuction to check tlb_ps, | 7 | Add a check-tlb_ps fuction to check tlb_ps, |
8 | to make sure the tlb_ps is avalablie. we check tlb_ps | 8 | to make sure the tlb_ps is avalablie. we check tlb_ps |
9 | when get the tlb_ps from tlb->misc or CSR bits. | 9 | when get the tlb_ps from tlb->misc or CSR bits. |
10 | 1. cpu reset. | 10 | 1. cpu reset. |
11 | set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value | 11 | set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value |
12 | from CSR_PRCFG2; | 12 | from CSR_PRCFG2; |
13 | 2. tlb instructions. | 13 | 2. tlb instructions. |
14 | some tlb instructions get the tlb_ps from tlb->misc but the | 14 | some tlb instructions get the tlb_ps from tlb->misc but the |
15 | value may has been initialized to 0. we need just check the tlb_e | 15 | value may has been initialized to 0. we need just check the tlb_e |
16 | skip the function and check tlb_ps write a guest log. | 16 | skip the function and check tlb_ps write a guest log. |
17 | 3. csrwr instructions. | 17 | 3. csrwr instructions. |
18 | to make sure CSR_PWCL.PTBASE and CSR_STLBPS.PS bits are avalable, | 18 | to make sure CSR_PWCL.PTBASE and CSR_STLBPS.PS bits are avalable, |
19 | cheke theses bits and set a default value from CSR_PRCFG2. | 19 | cheke theses bits and set a default value from CSR_PRCFG2. |
20 | 20 | ||
21 | 21 | ||
22 | v7: | 22 | v7: |
23 | clean code and rebase. | 23 | clean code and rebase. |
24 | 24 | ||
25 | v6: | 25 | v6: |
26 | 1 clean code. fix code style. | 26 | 1 clean code. fix code style. |
27 | 2 rebase and R-b. | 27 | 2 rebase and R-b. |
28 | 28 | ||
29 | V5: | 29 | V5: |
30 | 1 Add add chek_ps() function to check tlb_ps with CSR_PRCFG2; | 30 | 1 Add add chek_ps() function to check tlb_ps with CSR_PRCFG2; |
31 | 2 Some tlb instuctions, just check tlb_ps, do't rewrite the tlb_ps | 31 | 2 Some tlb instuctions, just check tlb_ps, do't rewrite the tlb_ps |
32 | bits just write a guest log; | 32 | bits just write a guest log; |
33 | 3 remove csrwr crmd helper function and crmd check PWCL and check CSR_STLBPS.just | 33 | 3 remove csrwr crmd helper function and crmd check PWCL and check CSR_STLBPS.just |
34 | chcek PWCL and STLBPS when csrwr CSR_PWCL and CSR_STLBPS; | 34 | chcek PWCL and STLBPS when csrwr CSR_PWCL and CSR_STLBPS; |
35 | 4 set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value | 35 | 4 set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value |
36 | from CSR_PRCFG2 when cpu reset. | 36 | from CSR_PRCFG2 when cpu reset. |
37 | V4: | 37 | V4: |
38 | 1.Get the default tlb_ps value from env->CSR_PRCFG2. | 38 | 1.Get the default tlb_ps value from env->CSR_PRCFG2. |
39 | 2.Some tlb instrucions check the tlb_ps such as tlbfill/tlbwr/invtlb. | 39 | 2.Some tlb instrucions check the tlb_ps such as tlbfill/tlbwr/invtlb. |
40 | 3.check_tlb_ps()just check CSR_PWCL.PTBASE bits and CSR_STLBPS.PS bits. | 40 | 3.check_tlb_ps()just check CSR_PWCL.PTBASE bits and CSR_STLBPS.PS bits. |
41 | don't check all tlb->misc. | 41 | don't check all tlb->misc. |
42 | 42 | ||
43 | v3: | 43 | v3: |
44 | remove some tlb instruction chek MMU on PG model, because on DA model | 44 | remove some tlb instruction chek MMU on PG model, because on DA model |
45 | also can use tlb instructions. | 45 | also can use tlb instructions. |
46 | 46 | ||
47 | v2: | 47 | v2: |
48 | check-tlb_ps when write CSR_PWCL and CSR_STLBPS; | 48 | check-tlb_ps when write CSR_PWCL and CSR_STLBPS; |
49 | some tlb instructions check CRMD PG model when clear/read/write the tlb. | 49 | some tlb instructions check CRMD PG model when clear/read/write the tlb. |
50 | link to patch: https://patchew.org/QEMU/20250220012226.2182174-1-gaosong@loongson.cn/ | 50 | link to patch: https://patchew.org/QEMU/20250220012226.2182174-1-gaosong@loongson.cn/ |
51 | 51 | ||
52 | Thanks. | 52 | Thanks. |
53 | Song Gao | 53 | Song Gao |
54 | 54 | ||
55 | Song Gao (2): | 55 | Song Gao (2): |
56 | target/loongarch: fix 'make check-functional' failed | 56 | target/loongarch: fix 'make check-functional' failed |
57 | target/loongarch: check tlb_ps | 57 | target/loongarch: check tlb_ps |
58 | 58 | ||
59 | target/loongarch/cpu.c | 10 +++- | 59 | target/loongarch/cpu.c | 10 +++- |
60 | target/loongarch/cpu_helper.c | 8 ++- | 60 | target/loongarch/cpu_helper.c | 8 ++- |
61 | target/loongarch/helper.h | 1 + | 61 | target/loongarch/helper.h | 1 + |
62 | target/loongarch/internals.h | 2 + | 62 | target/loongarch/internals.h | 2 + |
63 | target/loongarch/tcg/csr_helper.c | 30 +++++++++- | 63 | target/loongarch/tcg/csr_helper.c | 30 +++++++++- |
64 | .../tcg/insn_trans/trans_privileged.c.inc | 1 + | 64 | .../tcg/insn_trans/trans_privileged.c.inc | 1 + |
65 | target/loongarch/tcg/tlb_helper.c | 55 ++++++++++++++++++- | 65 | target/loongarch/tcg/tlb_helper.c | 55 ++++++++++++++++++- |
66 | 7 files changed, 99 insertions(+), 8 deletions(-) | 66 | 7 files changed, 99 insertions(+), 8 deletions(-) |
67 | 67 | ||
68 | -- | 68 | -- |
69 | 2.34.1 | 69 | 2.34.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | some tlb instructions get the tlb_ps from tlb->misc but the | ||
2 | value may has been initialized to 0,just check the tlb_ps skip | ||
3 | the function and write a log. | ||
1 | 4 | ||
5 | Signed-off-by: Song Gao <gaosong@loongson.cn> | ||
6 | Reviewed-by: Bibo Mao <maobibo@loongson.cn> | ||
7 | --- | ||
8 | target/loongarch/tcg/tlb_helper.c | 12 ++++++++++++ | ||
9 | 1 file changed, 12 insertions(+) | ||
10 | |||
11 | diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/target/loongarch/tcg/tlb_helper.c | ||
14 | +++ b/target/loongarch/tcg/tlb_helper.c | ||
15 | @@ -XXX,XX +XXX,XX @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) | ||
16 | uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V); | ||
17 | uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V); | ||
18 | uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); | ||
19 | + uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); | ||
20 | |||
21 | + if (!tlb_e) { | ||
22 | + return; | ||
23 | + } | ||
24 | if (index >= LOONGARCH_STLB) { | ||
25 | tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); | ||
26 | } else { | ||
27 | @@ -XXX,XX +XXX,XX @@ void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info, | ||
28 | uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); | ||
29 | uint64_t vpn, tlb_vppn; | ||
30 | uint8_t tlb_ps, compare_shift; | ||
31 | + uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); | ||
32 | |||
33 | + if (!tlb_e) { | ||
34 | + continue; | ||
35 | + } | ||
36 | if (i >= LOONGARCH_STLB) { | ||
37 | tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); | ||
38 | } else { | ||
39 | @@ -XXX,XX +XXX,XX @@ void helper_invtlb_page_asid_or_g(CPULoongArchState *env, | ||
40 | uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); | ||
41 | uint64_t vpn, tlb_vppn; | ||
42 | uint8_t tlb_ps, compare_shift; | ||
43 | + uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); | ||
44 | |||
45 | + if (!tlb_e) { | ||
46 | + continue; | ||
47 | + } | ||
48 | if (i >= LOONGARCH_STLB) { | ||
49 | tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); | ||
50 | } else { | ||
51 | -- | ||
52 | 2.34.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | For LoongArch th min tlb_ps is 12(4KB), for TLB code, | ||
2 | the tlb_ps may be 0,this may case UndefinedBehavior | ||
3 | Add a check-tlb_ps fuction to check tlb_ps, | ||
4 | to make sure the tlb_ps is avalablie. we check tlb_ps | ||
5 | when get the tlb_ps from tlb->misc or CSR bits. | ||
6 | 1. cpu reset | ||
7 | set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits a default value | ||
8 | from CSR_PRCFG2; | ||
9 | 2. tlb instructions. | ||
10 | some tlb instructions get the tlb_ps from tlb->misc but the | ||
11 | value may has been initialized to 0. we need just check the tlb_ps | ||
12 | skip the function and write a guest log. | ||
13 | 3. csrwr instructions. | ||
14 | to make sure CSR_PWCL.PTBASE and CSR_STLBPS.PS bits are avalable, | ||
15 | cheke theses bits and set a default value from CSR_PRCFG2. | ||
1 | 16 | ||
17 | Signed-off-by: Song Gao <gaosong@loongson.cn> | ||
18 | --- | ||
19 | target/loongarch/cpu.c | 11 +++++--- | ||
20 | target/loongarch/helper.h | 1 + | ||
21 | target/loongarch/internals.h | 2 ++ | ||
22 | target/loongarch/tcg/csr_helper.c | 27 +++++++++++++++++-- | ||
23 | .../tcg/insn_trans/trans_privileged.c.inc | 1 + | ||
24 | target/loongarch/tcg/tlb_helper.c | 23 ++++++++++++++-- | ||
25 | 6 files changed, 58 insertions(+), 7 deletions(-) | ||
26 | |||
27 | diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/target/loongarch/cpu.c | ||
30 | +++ b/target/loongarch/cpu.c | ||
31 | @@ -XXX,XX +XXX,XX @@ static void loongarch_max_initfn(Object *obj) | ||
32 | |||
33 | static void loongarch_cpu_reset_hold(Object *obj, ResetType type) | ||
34 | { | ||
35 | + uint8_t tlb_ps; | ||
36 | CPUState *cs = CPU(obj); | ||
37 | LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj); | ||
38 | CPULoongArchState *env = cpu_env(cs); | ||
39 | @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type) | ||
40 | */ | ||
41 | env->CSR_PGDH = 0; | ||
42 | env->CSR_PGDL = 0; | ||
43 | - env->CSR_PWCL = 0; | ||
44 | env->CSR_PWCH = 0; | ||
45 | - env->CSR_STLBPS = 0; | ||
46 | env->CSR_EENTRY = 0; | ||
47 | env->CSR_TLBRENTRY = 0; | ||
48 | env->CSR_MERRENTRY = 0; | ||
49 | - | ||
50 | + /* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */ | ||
51 | + if (env->CSR_PRCFG2 == 0) { | ||
52 | + env->CSR_PRCFG2 = 0x3fffff000; | ||
53 | + } | ||
54 | + tlb_ps = ctz32(env->CSR_PRCFG2); | ||
55 | + env->CSR_STLBPS = FIELD_DP64(env->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps); | ||
56 | + env->CSR_PWCL = FIELD_DP64(env->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps); | ||
57 | for (n = 0; n < 4; n++) { | ||
58 | env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0); | ||
59 | env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0); | ||
60 | diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h | ||
61 | index XXXXXXX..XXXXXXX 100644 | ||
62 | --- a/target/loongarch/helper.h | ||
63 | +++ b/target/loongarch/helper.h | ||
64 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(rdtime_d, i64, env) | ||
65 | DEF_HELPER_1(csrrd_pgd, i64, env) | ||
66 | DEF_HELPER_1(csrrd_cpuid, i64, env) | ||
67 | DEF_HELPER_1(csrrd_tval, i64, env) | ||
68 | +DEF_HELPER_2(csrwr_stlbps, i64, env, tl) | ||
69 | DEF_HELPER_2(csrwr_estat, i64, env, tl) | ||
70 | DEF_HELPER_2(csrwr_asid, i64, env, tl) | ||
71 | DEF_HELPER_2(csrwr_tcfg, i64, env, tl) | ||
72 | diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h | ||
73 | index XXXXXXX..XXXXXXX 100644 | ||
74 | --- a/target/loongarch/internals.h | ||
75 | +++ b/target/loongarch/internals.h | ||
76 | @@ -XXX,XX +XXX,XX @@ enum { | ||
77 | TLBRET_PE = 7, | ||
78 | }; | ||
79 | |||
80 | +bool check_ps(CPULoongArchState *ent, int ps); | ||
81 | + | ||
82 | extern const VMStateDescription vmstate_loongarch_cpu; | ||
83 | |||
84 | void loongarch_cpu_set_irq(void *opaque, int irq, int level); | ||
85 | diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/target/loongarch/tcg/csr_helper.c | ||
88 | +++ b/target/loongarch/tcg/csr_helper.c | ||
89 | @@ -XXX,XX +XXX,XX @@ | ||
90 | #include "hw/irq.h" | ||
91 | #include "cpu-csr.h" | ||
92 | |||
93 | +target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) | ||
94 | +{ | ||
95 | + int64_t old_v = env->CSR_STLBPS; | ||
96 | + | ||
97 | + /* | ||
98 | + * The real hardware only supports the min tlb_ps is 12 | ||
99 | + * tlb_ps=0 may cause undefined-behavior. | ||
100 | + */ | ||
101 | + uint8_t tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); | ||
102 | + if (!check_ps(env, tlb_ps)) { | ||
103 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
104 | + "Attempted set ps %d\n", tlb_ps); | ||
105 | + return old_v; | ||
106 | + } | ||
107 | + return old_v; | ||
108 | +} | ||
109 | + | ||
110 | target_ulong helper_csrrd_pgd(CPULoongArchState *env) | ||
111 | { | ||
112 | int64_t v; | ||
113 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val) | ||
114 | |||
115 | target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) | ||
116 | { | ||
117 | - int shift; | ||
118 | + int shift, ptbase; | ||
119 | int64_t old_v = env->CSR_PWCL; | ||
120 | |||
121 | /* | ||
122 | @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) | ||
123 | * treated as illegal. | ||
124 | */ | ||
125 | shift = FIELD_EX64(val, CSR_PWCL, PTEWIDTH); | ||
126 | + ptbase = FIELD_EX64(val, CSR_PWCL, PTBASE); | ||
127 | if (shift) { | ||
128 | qemu_log_mask(LOG_GUEST_ERROR, | ||
129 | "Attempted set pte width with %d bit\n", 64 << shift); | ||
130 | val = FIELD_DP64(val, CSR_PWCL, PTEWIDTH, 0); | ||
131 | } | ||
132 | + env->CSR_PWCL =val; | ||
133 | + if (!check_ps(env, ptbase)) { | ||
134 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
135 | + "Attrmpted set ptbase 2^%d\n", ptbase); | ||
136 | + return old_v; | ||
137 | + } | ||
138 | |||
139 | - env->CSR_PWCL = val; | ||
140 | return old_v; | ||
141 | } | ||
142 | diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc | ||
143 | index XXXXXXX..XXXXXXX 100644 | ||
144 | --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc | ||
145 | +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc | ||
146 | @@ -XXX,XX +XXX,XX @@ static bool set_csr_trans_func(unsigned int csr_num, GenCSRRead readfn, | ||
147 | |||
148 | void loongarch_csr_translate_init(void) | ||
149 | { | ||
150 | + SET_CSR_FUNC(STLBPS, NULL, gen_helper_csrwr_stlbps); | ||
151 | SET_CSR_FUNC(ESTAT, NULL, gen_helper_csrwr_estat); | ||
152 | SET_CSR_FUNC(ASID, NULL, gen_helper_csrwr_asid); | ||
153 | SET_CSR_FUNC(PGD, gen_helper_csrrd_pgd, NULL); | ||
154 | diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c | ||
155 | index XXXXXXX..XXXXXXX 100644 | ||
156 | --- a/target/loongarch/tcg/tlb_helper.c | ||
157 | +++ b/target/loongarch/tcg/tlb_helper.c | ||
158 | @@ -XXX,XX +XXX,XX @@ | ||
159 | #include "exec/log.h" | ||
160 | #include "cpu-csr.h" | ||
161 | |||
162 | +bool check_ps(CPULoongArchState *env, int tlb_ps) | ||
163 | +{ | ||
164 | + if (tlb_ps > 64) { | ||
165 | + return false; | ||
166 | + } | ||
167 | + return BIT_ULL(tlb_ps) & (env->CSR_PRCFG2); | ||
168 | +} | ||
169 | + | ||
170 | void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, | ||
171 | uint64_t *dir_width, target_ulong level) | ||
172 | { | ||
173 | @@ -XXX,XX +XXX,XX @@ static void fill_tlb_entry(CPULoongArchState *env, int index) | ||
174 | lo1 = env->CSR_TLBELO1; | ||
175 | } | ||
176 | |||
177 | - if (csr_ps == 0) { | ||
178 | - qemu_log_mask(CPU_LOG_MMU, "page size is 0\n"); | ||
179 | + /*check csr_ps */ | ||
180 | + if (!check_ps(env, csr_ps)) { | ||
181 | + qemu_log_mask(LOG_GUEST_ERROR, "csr_ps %d is illegal\n", csr_ps); | ||
182 | + return; | ||
183 | } | ||
184 | |||
185 | /* Only MTLB has the ps fields */ | ||
186 | @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) | ||
187 | pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); | ||
188 | } | ||
189 | |||
190 | + if (!check_ps(env, pagesize)) { | ||
191 | + qemu_log_mask(LOG_GUEST_ERROR, "pagesize %d is illegal\n", pagesize); | ||
192 | + return; | ||
193 | + } | ||
194 | + | ||
195 | stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); | ||
196 | + if (!check_ps(env, stlb_ps)) { | ||
197 | + qemu_log_mask(LOG_GUEST_ERROR, "stlb_ps %d is illegal\n", stlb_ps); | ||
198 | + return; | ||
199 | + } | ||
200 | |||
201 | if (pagesize == stlb_ps) { | ||
202 | /* Only write into STLB bits [47:13] */ | ||
203 | -- | ||
204 | 2.34.1 | diff view generated by jsdifflib |