Revision a3d0abae hw/spapr_hcall.c
b/hw/spapr_hcall.c | ||
---|---|---|
174 | 174 |
return H_SUCCESS; |
175 | 175 |
} |
176 | 176 |
|
177 |
static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr, |
|
178 |
target_ulong opcode, target_ulong *args) |
|
177 |
enum { |
|
178 |
REMOVE_SUCCESS = 0, |
|
179 |
REMOVE_NOT_FOUND = 1, |
|
180 |
REMOVE_PARM = 2, |
|
181 |
REMOVE_HW = 3, |
|
182 |
}; |
|
183 |
|
|
184 |
static target_ulong remove_hpte(CPUState *env, target_ulong ptex, |
|
185 |
target_ulong avpn, |
|
186 |
target_ulong flags, |
|
187 |
target_ulong *vp, target_ulong *rp) |
|
179 | 188 |
{ |
180 |
target_ulong flags = args[0]; |
|
181 |
target_ulong pte_index = args[1]; |
|
182 |
target_ulong avpn = args[2]; |
|
183 | 189 |
uint8_t *hpte; |
184 | 190 |
target_ulong v, r, rb; |
185 | 191 |
|
186 |
if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
|
187 |
return H_PARAMETER;
|
|
192 |
if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) { |
|
193 |
return REMOVE_PARM;
|
|
188 | 194 |
} |
189 | 195 |
|
190 |
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
|
196 |
hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64); |
|
191 | 197 |
while (!lock_hpte(hpte, HPTE_V_HVLOCK)) { |
192 | 198 |
/* We have no real concurrency in qemu soft-emulation, so we |
193 | 199 |
* will never actually have a contested lock */ |
... | ... | |
202 | 208 |
((flags & H_ANDCOND) && (v & avpn) != 0)) { |
203 | 209 |
stq_p(hpte, v & ~HPTE_V_HVLOCK); |
204 | 210 |
assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); |
205 |
return H_NOT_FOUND;
|
|
211 |
return REMOVE_NOT_FOUND;
|
|
206 | 212 |
} |
207 |
args[0] = v & ~HPTE_V_HVLOCK;
|
|
208 |
args[1] = r;
|
|
213 |
*vp = v & ~HPTE_V_HVLOCK;
|
|
214 |
*rp = r;
|
|
209 | 215 |
stq_p(hpte, 0); |
210 |
rb = compute_tlbie_rb(v, r, pte_index);
|
|
216 |
rb = compute_tlbie_rb(v, r, ptex); |
|
211 | 217 |
ppc_tlb_invalidate_one(env, rb); |
212 | 218 |
assert(!(ldq_p(hpte) & HPTE_V_HVLOCK)); |
219 |
return REMOVE_SUCCESS; |
|
220 |
} |
|
221 |
|
|
222 |
static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr, |
|
223 |
target_ulong opcode, target_ulong *args) |
|
224 |
{ |
|
225 |
target_ulong flags = args[0]; |
|
226 |
target_ulong pte_index = args[1]; |
|
227 |
target_ulong avpn = args[2]; |
|
228 |
int ret; |
|
229 |
|
|
230 |
ret = remove_hpte(env, pte_index, avpn, flags, |
|
231 |
&args[0], &args[1]); |
|
232 |
|
|
233 |
switch (ret) { |
|
234 |
case REMOVE_SUCCESS: |
|
235 |
return H_SUCCESS; |
|
236 |
|
|
237 |
case REMOVE_NOT_FOUND: |
|
238 |
return H_NOT_FOUND; |
|
239 |
|
|
240 |
case REMOVE_PARM: |
|
241 |
return H_PARAMETER; |
|
242 |
|
|
243 |
case REMOVE_HW: |
|
244 |
return H_HARDWARE; |
|
245 |
} |
|
246 |
|
|
247 |
assert(0); |
|
248 |
} |
|
249 |
|
|
250 |
#define H_BULK_REMOVE_TYPE 0xc000000000000000ULL |
|
251 |
#define H_BULK_REMOVE_REQUEST 0x4000000000000000ULL |
|
252 |
#define H_BULK_REMOVE_RESPONSE 0x8000000000000000ULL |
|
253 |
#define H_BULK_REMOVE_END 0xc000000000000000ULL |
|
254 |
#define H_BULK_REMOVE_CODE 0x3000000000000000ULL |
|
255 |
#define H_BULK_REMOVE_SUCCESS 0x0000000000000000ULL |
|
256 |
#define H_BULK_REMOVE_NOT_FOUND 0x1000000000000000ULL |
|
257 |
#define H_BULK_REMOVE_PARM 0x2000000000000000ULL |
|
258 |
#define H_BULK_REMOVE_HW 0x3000000000000000ULL |
|
259 |
#define H_BULK_REMOVE_RC 0x0c00000000000000ULL |
|
260 |
#define H_BULK_REMOVE_FLAGS 0x0300000000000000ULL |
|
261 |
#define H_BULK_REMOVE_ABSOLUTE 0x0000000000000000ULL |
|
262 |
#define H_BULK_REMOVE_ANDCOND 0x0100000000000000ULL |
|
263 |
#define H_BULK_REMOVE_AVPN 0x0200000000000000ULL |
|
264 |
#define H_BULK_REMOVE_PTEX 0x00ffffffffffffffULL |
|
265 |
|
|
266 |
#define H_BULK_REMOVE_MAX_BATCH 4 |
|
267 |
|
|
268 |
static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr, |
|
269 |
target_ulong opcode, target_ulong *args) |
|
270 |
{ |
|
271 |
int i; |
|
272 |
|
|
273 |
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { |
|
274 |
target_ulong *tsh = &args[i*2]; |
|
275 |
target_ulong tsl = args[i*2 + 1]; |
|
276 |
target_ulong v, r, ret; |
|
277 |
|
|
278 |
if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) { |
|
279 |
break; |
|
280 |
} else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) { |
|
281 |
return H_PARAMETER; |
|
282 |
} |
|
283 |
|
|
284 |
*tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS; |
|
285 |
*tsh |= H_BULK_REMOVE_RESPONSE; |
|
286 |
|
|
287 |
if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) { |
|
288 |
*tsh |= H_BULK_REMOVE_PARM; |
|
289 |
return H_PARAMETER; |
|
290 |
} |
|
291 |
|
|
292 |
ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl, |
|
293 |
(*tsh & H_BULK_REMOVE_FLAGS) >> 26, |
|
294 |
&v, &r); |
|
295 |
|
|
296 |
*tsh |= ret << 60; |
|
297 |
|
|
298 |
switch (ret) { |
|
299 |
case REMOVE_SUCCESS: |
|
300 |
*tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43; |
|
301 |
break; |
|
302 |
|
|
303 |
case REMOVE_PARM: |
|
304 |
return H_PARAMETER; |
|
305 |
|
|
306 |
case REMOVE_HW: |
|
307 |
return H_HARDWARE; |
|
308 |
} |
|
309 |
} |
|
310 |
|
|
213 | 311 |
return H_SUCCESS; |
214 | 312 |
} |
215 | 313 |
|
... | ... | |
581 | 679 |
spapr_register_hypercall(H_REMOVE, h_remove); |
582 | 680 |
spapr_register_hypercall(H_PROTECT, h_protect); |
583 | 681 |
|
682 |
/* hcall-bulk */ |
|
683 |
spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove); |
|
684 |
|
|
584 | 685 |
/* hcall-dabr */ |
585 | 686 |
spapr_register_hypercall(H_SET_DABR, h_set_dabr); |
586 | 687 |
|
Also available in: Unified diff