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