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