]> Git Repo - qemu.git/blob - hw/spapr_hcall.c
cpus: Pass CPUState to [qemu_]cpu_has_work()
[qemu.git] / hw / spapr_hcall.c
1 #include "sysemu.h"
2 #include "cpu.h"
3 #include "qemu-char.h"
4 #include "sysemu.h"
5 #include "qemu-char.h"
6 #include "helper_regs.h"
7 #include "hw/spapr.h"
8
9 #define HPTES_PER_GROUP 8
10
11 #define HPTE_V_SSIZE_SHIFT      62
12 #define HPTE_V_AVPN_SHIFT       7
13 #define HPTE_V_AVPN             0x3fffffffffffff80ULL
14 #define HPTE_V_AVPN_VAL(x)      (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
15 #define HPTE_V_COMPARE(x, y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
16 #define HPTE_V_BOLTED           0x0000000000000010ULL
17 #define HPTE_V_LOCK             0x0000000000000008ULL
18 #define HPTE_V_LARGE            0x0000000000000004ULL
19 #define HPTE_V_SECONDARY        0x0000000000000002ULL
20 #define HPTE_V_VALID            0x0000000000000001ULL
21
22 #define HPTE_R_PP0              0x8000000000000000ULL
23 #define HPTE_R_TS               0x4000000000000000ULL
24 #define HPTE_R_KEY_HI           0x3000000000000000ULL
25 #define HPTE_R_RPN_SHIFT        12
26 #define HPTE_R_RPN              0x3ffffffffffff000ULL
27 #define HPTE_R_FLAGS            0x00000000000003ffULL
28 #define HPTE_R_PP               0x0000000000000003ULL
29 #define HPTE_R_N                0x0000000000000004ULL
30 #define HPTE_R_G                0x0000000000000008ULL
31 #define HPTE_R_M                0x0000000000000010ULL
32 #define HPTE_R_I                0x0000000000000020ULL
33 #define HPTE_R_W                0x0000000000000040ULL
34 #define HPTE_R_WIMG             0x0000000000000078ULL
35 #define HPTE_R_C                0x0000000000000080ULL
36 #define HPTE_R_R                0x0000000000000100ULL
37 #define HPTE_R_KEY_LO           0x0000000000000e00ULL
38
39 #define HPTE_V_1TB_SEG          0x4000000000000000ULL
40 #define HPTE_V_VRMA_MASK        0x4001ffffff000000ULL
41
42 static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
43                                      target_ulong pte_index)
44 {
45     target_ulong rb, va_low;
46
47     rb = (v & ~0x7fULL) << 16; /* AVA field */
48     va_low = pte_index >> 3;
49     if (v & HPTE_V_SECONDARY) {
50         va_low = ~va_low;
51     }
52     /* xor vsid from AVA */
53     if (!(v & HPTE_V_1TB_SEG)) {
54         va_low ^= v >> 12;
55     } else {
56         va_low ^= v >> 24;
57     }
58     va_low &= 0x7ff;
59     if (v & HPTE_V_LARGE) {
60         rb |= 1;                         /* L field */
61 #if 0 /* Disable that P7 specific bit for now */
62         if (r & 0xff000) {
63             /* non-16MB large page, must be 64k */
64             /* (masks depend on page size) */
65             rb |= 0x1000;                /* page encoding in LP field */
66             rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
67             rb |= (va_low & 0xfe);       /* AVAL field */
68         }
69 #endif
70     } else {
71         /* 4kB page */
72         rb |= (va_low & 0x7ff) << 12;   /* remaining 11b of AVA */
73     }
74     rb |= (v >> 54) & 0x300;            /* B field */
75     return rb;
76 }
77
78 static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
79                             target_ulong opcode, target_ulong *args)
80 {
81     CPUPPCState *env = &cpu->env;
82     target_ulong flags = args[0];
83     target_ulong pte_index = args[1];
84     target_ulong pteh = args[2];
85     target_ulong ptel = args[3];
86     target_ulong page_shift = 12;
87     target_ulong raddr;
88     target_ulong i;
89     uint8_t *hpte;
90
91     /* only handle 4k and 16M pages for now */
92     if (pteh & HPTE_V_LARGE) {
93 #if 0 /* We don't support 64k pages yet */
94         if ((ptel & 0xf000) == 0x1000) {
95             /* 64k page */
96         } else
97 #endif
98         if ((ptel & 0xff000) == 0) {
99             /* 16M page */
100             page_shift = 24;
101             /* lowest AVA bit must be 0 for 16M pages */
102             if (pteh & 0x80) {
103                 return H_PARAMETER;
104             }
105         } else {
106             return H_PARAMETER;
107         }
108     }
109
110     raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
111
112     if (raddr < spapr->ram_limit) {
113         /* Regular RAM - should have WIMG=0010 */
114         if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
115             return H_PARAMETER;
116         }
117     } else {
118         /* Looks like an IO address */
119         /* FIXME: What WIMG combinations could be sensible for IO?
120          * For now we allow WIMG=010x, but are there others? */
121         /* FIXME: Should we check against registered IO addresses? */
122         if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
123             return H_PARAMETER;
124         }
125     }
126
127     pteh &= ~0x60ULL;
128
129     if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
130         return H_PARAMETER;
131     }
132     if (likely((flags & H_EXACT) == 0)) {
133         pte_index &= ~7ULL;
134         hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
135         for (i = 0; ; ++i) {
136             if (i == 8) {
137                 return H_PTEG_FULL;
138             }
139             if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
140                 break;
141             }
142             hpte += HASH_PTE_SIZE_64;
143         }
144     } else {
145         i = 0;
146         hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
147         if (ldq_p(hpte) & HPTE_V_VALID) {
148             return H_PTEG_FULL;
149         }
150     }
151     stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
152     /* eieio();  FIXME: need some sort of barrier for smp? */
153     stq_p(hpte, pteh);
154
155     args[0] = pte_index + i;
156     return H_SUCCESS;
157 }
158
159 enum {
160     REMOVE_SUCCESS = 0,
161     REMOVE_NOT_FOUND = 1,
162     REMOVE_PARM = 2,
163     REMOVE_HW = 3,
164 };
165
166 static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
167                                 target_ulong avpn,
168                                 target_ulong flags,
169                                 target_ulong *vp, target_ulong *rp)
170 {
171     uint8_t *hpte;
172     target_ulong v, r, rb;
173
174     if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
175         return REMOVE_PARM;
176     }
177
178     hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
179
180     v = ldq_p(hpte);
181     r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
182
183     if ((v & HPTE_V_VALID) == 0 ||
184         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
185         ((flags & H_ANDCOND) && (v & avpn) != 0)) {
186         return REMOVE_NOT_FOUND;
187     }
188     *vp = v;
189     *rp = r;
190     stq_p(hpte, 0);
191     rb = compute_tlbie_rb(v, r, ptex);
192     ppc_tlb_invalidate_one(env, rb);
193     return REMOVE_SUCCESS;
194 }
195
196 static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
197                              target_ulong opcode, target_ulong *args)
198 {
199     CPUPPCState *env = &cpu->env;
200     target_ulong flags = args[0];
201     target_ulong pte_index = args[1];
202     target_ulong avpn = args[2];
203     int ret;
204
205     ret = remove_hpte(env, pte_index, avpn, flags,
206                       &args[0], &args[1]);
207
208     switch (ret) {
209     case REMOVE_SUCCESS:
210         return H_SUCCESS;
211
212     case REMOVE_NOT_FOUND:
213         return H_NOT_FOUND;
214
215     case REMOVE_PARM:
216         return H_PARAMETER;
217
218     case REMOVE_HW:
219         return H_HARDWARE;
220     }
221
222     assert(0);
223 }
224
225 #define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
226 #define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
227 #define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
228 #define   H_BULK_REMOVE_END            0xc000000000000000ULL
229 #define H_BULK_REMOVE_CODE             0x3000000000000000ULL
230 #define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
231 #define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
232 #define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
233 #define   H_BULK_REMOVE_HW             0x3000000000000000ULL
234 #define H_BULK_REMOVE_RC               0x0c00000000000000ULL
235 #define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
236 #define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
237 #define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
238 #define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
239 #define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
240
241 #define H_BULK_REMOVE_MAX_BATCH        4
242
243 static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
244                                   target_ulong opcode, target_ulong *args)
245 {
246     CPUPPCState *env = &cpu->env;
247     int i;
248
249     for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
250         target_ulong *tsh = &args[i*2];
251         target_ulong tsl = args[i*2 + 1];
252         target_ulong v, r, ret;
253
254         if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
255             break;
256         } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
257             return H_PARAMETER;
258         }
259
260         *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
261         *tsh |= H_BULK_REMOVE_RESPONSE;
262
263         if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
264             *tsh |= H_BULK_REMOVE_PARM;
265             return H_PARAMETER;
266         }
267
268         ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
269                           (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
270                           &v, &r);
271
272         *tsh |= ret << 60;
273
274         switch (ret) {
275         case REMOVE_SUCCESS:
276             *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
277             break;
278
279         case REMOVE_PARM:
280             return H_PARAMETER;
281
282         case REMOVE_HW:
283             return H_HARDWARE;
284         }
285     }
286
287     return H_SUCCESS;
288 }
289
290 static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
291                               target_ulong opcode, target_ulong *args)
292 {
293     CPUPPCState *env = &cpu->env;
294     target_ulong flags = args[0];
295     target_ulong pte_index = args[1];
296     target_ulong avpn = args[2];
297     uint8_t *hpte;
298     target_ulong v, r, rb;
299
300     if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
301         return H_PARAMETER;
302     }
303
304     hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
305
306     v = ldq_p(hpte);
307     r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
308
309     if ((v & HPTE_V_VALID) == 0 ||
310         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
311         return H_NOT_FOUND;
312     }
313
314     r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
315            HPTE_R_KEY_HI | HPTE_R_KEY_LO);
316     r |= (flags << 55) & HPTE_R_PP0;
317     r |= (flags << 48) & HPTE_R_KEY_HI;
318     r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
319     rb = compute_tlbie_rb(v, r, pte_index);
320     stq_p(hpte, v & ~HPTE_V_VALID);
321     ppc_tlb_invalidate_one(env, rb);
322     stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
323     /* Don't need a memory barrier, due to qemu's global lock */
324     stq_p(hpte, v);
325     return H_SUCCESS;
326 }
327
328 static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
329                                target_ulong opcode, target_ulong *args)
330 {
331     /* FIXME: actually implement this */
332     return H_HARDWARE;
333 }
334
335 #define FLAGS_REGISTER_VPA         0x0000200000000000ULL
336 #define FLAGS_REGISTER_DTL         0x0000400000000000ULL
337 #define FLAGS_REGISTER_SLBSHADOW   0x0000600000000000ULL
338 #define FLAGS_DEREGISTER_VPA       0x0000a00000000000ULL
339 #define FLAGS_DEREGISTER_DTL       0x0000c00000000000ULL
340 #define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL
341
342 #define VPA_MIN_SIZE           640
343 #define VPA_SIZE_OFFSET        0x4
344 #define VPA_SHARED_PROC_OFFSET 0x9
345 #define VPA_SHARED_PROC_VAL    0x2
346
347 static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
348 {
349     uint16_t size;
350     uint8_t tmp;
351
352     if (vpa == 0) {
353         hcall_dprintf("Can't cope with registering a VPA at logical 0\n");
354         return H_HARDWARE;
355     }
356
357     if (vpa % env->dcache_line_size) {
358         return H_PARAMETER;
359     }
360     /* FIXME: bounds check the address */
361
362     size = lduw_be_phys(vpa + 0x4);
363
364     if (size < VPA_MIN_SIZE) {
365         return H_PARAMETER;
366     }
367
368     /* VPA is not allowed to cross a page boundary */
369     if ((vpa / 4096) != ((vpa + size - 1) / 4096)) {
370         return H_PARAMETER;
371     }
372
373     env->vpa_addr = vpa;
374
375     tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
376     tmp |= VPA_SHARED_PROC_VAL;
377     stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
378
379     return H_SUCCESS;
380 }
381
382 static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
383 {
384     if (env->slb_shadow_addr) {
385         return H_RESOURCE;
386     }
387
388     if (env->dtl_addr) {
389         return H_RESOURCE;
390     }
391
392     env->vpa_addr = 0;
393     return H_SUCCESS;
394 }
395
396 static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
397 {
398     uint32_t size;
399
400     if (addr == 0) {
401         hcall_dprintf("Can't cope with SLB shadow at logical 0\n");
402         return H_HARDWARE;
403     }
404
405     size = ldl_be_phys(addr + 0x4);
406     if (size < 0x8) {
407         return H_PARAMETER;
408     }
409
410     if ((addr / 4096) != ((addr + size - 1) / 4096)) {
411         return H_PARAMETER;
412     }
413
414     if (!env->vpa_addr) {
415         return H_RESOURCE;
416     }
417
418     env->slb_shadow_addr = addr;
419     env->slb_shadow_size = size;
420
421     return H_SUCCESS;
422 }
423
424 static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
425 {
426     env->slb_shadow_addr = 0;
427     env->slb_shadow_size = 0;
428     return H_SUCCESS;
429 }
430
431 static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
432 {
433     uint32_t size;
434
435     if (addr == 0) {
436         hcall_dprintf("Can't cope with DTL at logical 0\n");
437         return H_HARDWARE;
438     }
439
440     size = ldl_be_phys(addr + 0x4);
441
442     if (size < 48) {
443         return H_PARAMETER;
444     }
445
446     if (!env->vpa_addr) {
447         return H_RESOURCE;
448     }
449
450     env->dtl_addr = addr;
451     env->dtl_size = size;
452
453     return H_SUCCESS;
454 }
455
456 static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
457 {
458     env->dtl_addr = 0;
459     env->dtl_size = 0;
460
461     return H_SUCCESS;
462 }
463
464 static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
465                                    target_ulong opcode, target_ulong *args)
466 {
467     target_ulong flags = args[0];
468     target_ulong procno = args[1];
469     target_ulong vpa = args[2];
470     target_ulong ret = H_PARAMETER;
471     CPUPPCState *tenv;
472
473     for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) {
474         if (tenv->cpu_index == procno) {
475             break;
476         }
477     }
478
479     if (!tenv) {
480         return H_PARAMETER;
481     }
482
483     switch (flags) {
484     case FLAGS_REGISTER_VPA:
485         ret = register_vpa(tenv, vpa);
486         break;
487
488     case FLAGS_DEREGISTER_VPA:
489         ret = deregister_vpa(tenv, vpa);
490         break;
491
492     case FLAGS_REGISTER_SLBSHADOW:
493         ret = register_slb_shadow(tenv, vpa);
494         break;
495
496     case FLAGS_DEREGISTER_SLBSHADOW:
497         ret = deregister_slb_shadow(tenv, vpa);
498         break;
499
500     case FLAGS_REGISTER_DTL:
501         ret = register_dtl(tenv, vpa);
502         break;
503
504     case FLAGS_DEREGISTER_DTL:
505         ret = deregister_dtl(tenv, vpa);
506         break;
507     }
508
509     return ret;
510 }
511
512 static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
513                            target_ulong opcode, target_ulong *args)
514 {
515     CPUPPCState *env = &cpu->env;
516
517     env->msr |= (1ULL << MSR_EE);
518     hreg_compute_hflags(env);
519     if (!cpu_has_work(CPU(cpu))) {
520         env->halted = 1;
521         env->exception_index = EXCP_HLT;
522         env->exit_request = 1;
523     }
524     return H_SUCCESS;
525 }
526
527 static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
528                            target_ulong opcode, target_ulong *args)
529 {
530     target_ulong rtas_r3 = args[0];
531     uint32_t token = ldl_be_phys(rtas_r3);
532     uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
533     uint32_t nret = ldl_be_phys(rtas_r3 + 8);
534
535     return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
536                            nret, rtas_r3 + 12 + 4*nargs);
537 }
538
539 static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
540                                    target_ulong opcode, target_ulong *args)
541 {
542     target_ulong size = args[0];
543     target_ulong addr = args[1];
544
545     switch (size) {
546     case 1:
547         args[0] = ldub_phys(addr);
548         return H_SUCCESS;
549     case 2:
550         args[0] = lduw_phys(addr);
551         return H_SUCCESS;
552     case 4:
553         args[0] = ldl_phys(addr);
554         return H_SUCCESS;
555     case 8:
556         args[0] = ldq_phys(addr);
557         return H_SUCCESS;
558     }
559     return H_PARAMETER;
560 }
561
562 static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
563                                     target_ulong opcode, target_ulong *args)
564 {
565     target_ulong size = args[0];
566     target_ulong addr = args[1];
567     target_ulong val  = args[2];
568
569     switch (size) {
570     case 1:
571         stb_phys(addr, val);
572         return H_SUCCESS;
573     case 2:
574         stw_phys(addr, val);
575         return H_SUCCESS;
576     case 4:
577         stl_phys(addr, val);
578         return H_SUCCESS;
579     case 8:
580         stq_phys(addr, val);
581         return H_SUCCESS;
582     }
583     return H_PARAMETER;
584 }
585
586 static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
587                                     target_ulong opcode, target_ulong *args)
588 {
589     target_ulong dst   = args[0]; /* Destination address */
590     target_ulong src   = args[1]; /* Source address */
591     target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
592     target_ulong count = args[3]; /* Element count */
593     target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
594     uint64_t tmp;
595     unsigned int mask = (1 << esize) - 1;
596     int step = 1 << esize;
597
598     if (count > 0x80000000) {
599         return H_PARAMETER;
600     }
601
602     if ((dst & mask) || (src & mask) || (op > 1)) {
603         return H_PARAMETER;
604     }
605
606     if (dst >= src && dst < (src + (count << esize))) {
607             dst = dst + ((count - 1) << esize);
608             src = src + ((count - 1) << esize);
609             step = -step;
610     }
611
612     while (count--) {
613         switch (esize) {
614         case 0:
615             tmp = ldub_phys(src);
616             break;
617         case 1:
618             tmp = lduw_phys(src);
619             break;
620         case 2:
621             tmp = ldl_phys(src);
622             break;
623         case 3:
624             tmp = ldq_phys(src);
625             break;
626         default:
627             return H_PARAMETER;
628         }
629         if (op == 1) {
630             tmp = ~tmp;
631         }
632         switch (esize) {
633         case 0:
634             stb_phys(dst, tmp);
635             break;
636         case 1:
637             stw_phys(dst, tmp);
638             break;
639         case 2:
640             stl_phys(dst, tmp);
641             break;
642         case 3:
643             stq_phys(dst, tmp);
644             break;
645         }
646         dst = dst + step;
647         src = src + step;
648     }
649
650     return H_SUCCESS;
651 }
652
653 static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
654                                    target_ulong opcode, target_ulong *args)
655 {
656     /* Nothing to do on emulation, KVM will trap this in the kernel */
657     return H_SUCCESS;
658 }
659
660 static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
661                                    target_ulong opcode, target_ulong *args)
662 {
663     /* Nothing to do on emulation, KVM will trap this in the kernel */
664     return H_SUCCESS;
665 }
666
667 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
668 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
669
670 void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
671 {
672     spapr_hcall_fn *slot;
673
674     if (opcode <= MAX_HCALL_OPCODE) {
675         assert((opcode & 0x3) == 0);
676
677         slot = &papr_hypercall_table[opcode / 4];
678     } else {
679         assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
680
681         slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
682     }
683
684     assert(!(*slot));
685     *slot = fn;
686 }
687
688 target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
689                              target_ulong *args)
690 {
691     if ((opcode <= MAX_HCALL_OPCODE)
692         && ((opcode & 0x3) == 0)) {
693         spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
694
695         if (fn) {
696             return fn(cpu, spapr, opcode, args);
697         }
698     } else if ((opcode >= KVMPPC_HCALL_BASE) &&
699                (opcode <= KVMPPC_HCALL_MAX)) {
700         spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
701
702         if (fn) {
703             return fn(cpu, spapr, opcode, args);
704         }
705     }
706
707     hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
708     return H_FUNCTION;
709 }
710
711 static void hypercall_register_types(void)
712 {
713     /* hcall-pft */
714     spapr_register_hypercall(H_ENTER, h_enter);
715     spapr_register_hypercall(H_REMOVE, h_remove);
716     spapr_register_hypercall(H_PROTECT, h_protect);
717
718     /* hcall-bulk */
719     spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
720
721     /* hcall-dabr */
722     spapr_register_hypercall(H_SET_DABR, h_set_dabr);
723
724     /* hcall-splpar */
725     spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
726     spapr_register_hypercall(H_CEDE, h_cede);
727
728     /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
729      * here between the "CI" and the "CACHE" variants, they will use whatever
730      * mapping attributes qemu is using. When using KVM, the kernel will
731      * enforce the attributes more strongly
732      */
733     spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
734     spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
735     spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
736     spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
737     spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
738     spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
739     spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
740
741     /* qemu/KVM-PPC specific hcalls */
742     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
743 }
744
745 type_init(hypercall_register_types)
This page took 0.062734 seconds and 4 git commands to generate.