Revision 352e48b0

b/Makefile.target
376 376

  
377 377
obj-s390x-y = s390-virtio-bus.o s390-virtio.o
378 378

  
379
obj-alpha-y = alpha_palcode.o
379
obj-alpha-y =
380 380

  
381 381
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
382 382

  
/dev/null
1
/*
2
 *  Alpha emulation - PALcode emulation for qemu.
3
 *
4
 *  Copyright (c) 2007 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

  
20
#include <stdint.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23

  
24
#include "cpu.h"
25
#include "exec-all.h"
26

  
27
/* Shared handlers */
28
static void pal_reset (CPUState *env);
29
/* Console handlers */
30
static void pal_console_call (CPUState *env, uint32_t palcode);
31
/* OpenVMS handlers */
32
static void pal_openvms_call (CPUState *env, uint32_t palcode);
33
/* UNIX / Linux handlers */
34
static void pal_unix_call (CPUState *env, uint32_t palcode);
35

  
36
pal_handler_t pal_handlers[] = {
37
    /* Console handler */
38
    {
39
        .reset = &pal_reset,
40
        .call_pal = &pal_console_call,
41
    },
42
    /* OpenVMS handler */
43
    {
44
        .reset = &pal_reset,
45
        .call_pal = &pal_openvms_call,
46
    },
47
    /* UNIX / Linux handler */
48
    {
49
        .reset = &pal_reset,
50
        .call_pal = &pal_unix_call,
51
    },
52
};
53

  
54
#if 0
55
/* One must explicitly check that the TB is valid and the FOE bit is reset */
56
static void update_itb (void)
57
{
58
    /* This writes into a temp register, not the actual one */
59
    mtpr(TB_TAG);
60
    mtpr(TB_CTL);
61
    /* This commits the TB update */
62
    mtpr(ITB_PTE);
63
}
64

  
65
static void update_dtb (void);
66
{
67
    mtpr(TB_CTL);
68
    /* This write into a temp register, not the actual one */
69
    mtpr(TB_TAG);
70
    /* This commits the TB update */
71
    mtpr(DTB_PTE);
72
}
73
#endif
74

  
75
static void pal_reset (CPUState *env)
76
{
77
}
78

  
79
static void do_swappal (CPUState *env, uint64_t palid)
80
{
81
    pal_handler_t *pal_handler;
82

  
83
    switch (palid) {
84
    case 0 ... 2:
85
        pal_handler = &pal_handlers[palid];
86
        env->pal_handler = pal_handler;
87
        env->ipr[IPR_PAL_BASE] = -1ULL;
88
        (*pal_handler->reset)(env);
89
        break;
90
    case 3 ... 255:
91
        /* Unknown identifier */
92
        env->ir[0] = 1;
93
        return;
94
    default:
95
        /* We were given the entry point address */
96
        env->pal_handler = NULL;
97
        env->ipr[IPR_PAL_BASE] = palid;
98
        env->pc = env->ipr[IPR_PAL_BASE];
99
        cpu_loop_exit();
100
    }
101
}
102

  
103
static void pal_console_call (CPUState *env, uint32_t palcode)
104
{
105
    uint64_t palid;
106

  
107
    if (palcode < 0x00000080) {
108
        /* Privileged palcodes */
109
        if (!(env->ps >> 3)) {
110
            /* TODO: generate privilege exception */
111
        }
112
    }
113
    switch (palcode) {
114
    case 0x00000000:
115
        /* HALT */
116
        /* REQUIRED */
117
        break;
118
    case 0x00000001:
119
        /* CFLUSH */
120
        break;
121
    case 0x00000002:
122
        /* DRAINA */
123
        /* REQUIRED */
124
        /* Implemented as no-op */
125
        break;
126
    case 0x00000009:
127
        /* CSERVE */
128
        /* REQUIRED */
129
        break;
130
    case 0x0000000A:
131
        /* SWPPAL */
132
        /* REQUIRED */
133
        palid = env->ir[16];
134
        do_swappal(env, palid);
135
        break;
136
    case 0x00000080:
137
        /* BPT */
138
        /* REQUIRED */
139
        break;
140
    case 0x00000081:
141
        /* BUGCHK */
142
        /* REQUIRED */
143
        break;
144
    case 0x00000086:
145
        /* IMB */
146
        /* REQUIRED */
147
        /* Implemented as no-op */
148
        break;
149
    case 0x0000009E:
150
        /* RDUNIQUE */
151
        /* REQUIRED */
152
        break;
153
    case 0x0000009F:
154
        /* WRUNIQUE */
155
        /* REQUIRED */
156
        break;
157
    case 0x000000AA:
158
        /* GENTRAP */
159
        /* REQUIRED */
160
        break;
161
    default:
162
        break;
163
    }
164
}
165

  
166
static void pal_openvms_call (CPUState *env, uint32_t palcode)
167
{
168
    uint64_t palid, val, oldval;
169

  
170
    if (palcode < 0x00000080) {
171
        /* Privileged palcodes */
172
        if (!(env->ps >> 3)) {
173
            /* TODO: generate privilege exception */
174
        }
175
    }
176
    switch (palcode) {
177
    case 0x00000000:
178
        /* HALT */
179
        /* REQUIRED */
180
        break;
181
    case 0x00000001:
182
        /* CFLUSH */
183
        break;
184
    case 0x00000002:
185
        /* DRAINA */
186
        /* REQUIRED */
187
        /* Implemented as no-op */
188
        break;
189
    case 0x00000003:
190
        /* LDQP */
191
        break;
192
    case 0x00000004:
193
        /* STQP */
194
        break;
195
    case 0x00000005:
196
        /* SWPCTX */
197
        break;
198
    case 0x00000006:
199
        /* MFPR_ASN */
200
        if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
201
            env->ir[0] = val;
202
        break;
203
    case 0x00000007:
204
        /* MTPR_ASTEN */
205
        val = env->ir[16];
206
        if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
207
            env->ir[0] = val;
208
        break;
209
    case 0x00000008:
210
        /* MTPR_ASTSR */
211
        val = env->ir[16];
212
        if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
213
            env->ir[0] = val;
214
        break;
215
    case 0x00000009:
216
        /* CSERVE */
217
        /* REQUIRED */
218
        break;
219
    case 0x0000000A:
220
        /* SWPPAL */
221
        /* REQUIRED */
222
        palid = env->ir[16];
223
        do_swappal(env, palid);
224
        break;
225
    case 0x0000000B:
226
        /* MFPR_FEN */
227
        if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
228
            env->ir[0] = val;
229
        break;
230
    case 0x0000000C:
231
        /* MTPR_FEN */
232
        val = env->ir[16];
233
        if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
234
            env->ir[0] = val;
235
        break;
236
    case 0x0000000D:
237
        /* MTPR_IPIR */
238
        val = env->ir[16];
239
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
240
            env->ir[0] = val;
241
        break;
242
    case 0x0000000E:
243
        /* MFPR_IPL */
244
        if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
245
            env->ir[0] = val;
246
        break;
247
    case 0x0000000F:
248
        /* MTPR_IPL */
249
        val = env->ir[16];
250
        if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
251
            env->ir[0] = val;
252
        break;
253
    case 0x00000010:
254
        /* MFPR_MCES */
255
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
256
            env->ir[0] = val;
257
        break;
258
    case 0x00000011:
259
        /* MTPR_MCES */
260
        val = env->ir[16];
261
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
262
            env->ir[0] = val;
263
        break;
264
    case 0x00000012:
265
        /* MFPR_PCBB */
266
        if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
267
            env->ir[0] = val;
268
        break;
269
    case 0x00000013:
270
        /* MFPR_PRBR */
271
        if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
272
            env->ir[0] = val;
273
        break;
274
    case 0x00000014:
275
        /* MTPR_PRBR */
276
        val = env->ir[16];
277
        if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
278
            env->ir[0] = val;
279
        break;
280
    case 0x00000015:
281
        /* MFPR_PTBR */
282
        if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
283
            env->ir[0] = val;
284
        break;
285
    case 0x00000016:
286
        /* MFPR_SCBB */
287
        if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
288
            env->ir[0] = val;
289
        break;
290
    case 0x00000017:
291
        /* MTPR_SCBB */
292
        val = env->ir[16];
293
        if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
294
            env->ir[0] = val;
295
        break;
296
    case 0x00000018:
297
        /* MTPR_SIRR */
298
        val = env->ir[16];
299
        if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
300
            env->ir[0] = val;
301
        break;
302
    case 0x00000019:
303
        /* MFPR_SISR */
304
        if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
305
            env->ir[0] = val;
306
        break;
307
    case 0x0000001A:
308
        /* MFPR_TBCHK */
309
        if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
310
            env->ir[0] = val;
311
        break;
312
    case 0x0000001B:
313
        /* MTPR_TBIA */
314
        val = env->ir[16];
315
        if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
316
            env->ir[0] = val;
317
        break;
318
    case 0x0000001C:
319
        /* MTPR_TBIAP */
320
        val = env->ir[16];
321
        if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
322
            env->ir[0] = val;
323
        break;
324
    case 0x0000001D:
325
        /* MTPR_TBIS */
326
        val = env->ir[16];
327
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
328
            env->ir[0] = val;
329
        break;
330
    case 0x0000001E:
331
        /* MFPR_ESP */
332
        if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
333
            env->ir[0] = val;
334
        break;
335
    case 0x0000001F:
336
        /* MTPR_ESP */
337
        val = env->ir[16];
338
        if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
339
            env->ir[0] = val;
340
        break;
341
    case 0x00000020:
342
        /* MFPR_SSP */
343
        if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
344
            env->ir[0] = val;
345
        break;
346
    case 0x00000021:
347
        /* MTPR_SSP */
348
        val = env->ir[16];
349
        if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
350
            env->ir[0] = val;
351
        break;
352
    case 0x00000022:
353
        /* MFPR_USP */
354
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
355
            env->ir[0] = val;
356
        break;
357
    case 0x00000023:
358
        /* MTPR_USP */
359
        val = env->ir[16];
360
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
361
            env->ir[0] = val;
362
        break;
363
    case 0x00000024:
364
        /* MTPR_TBISD */
365
        val = env->ir[16];
366
        if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
367
            env->ir[0] = val;
368
        break;
369
    case 0x00000025:
370
        /* MTPR_TBISI */
371
        val = env->ir[16];
372
        if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
373
            env->ir[0] = val;
374
        break;
375
    case 0x00000026:
376
        /* MFPR_ASTEN */
377
        if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
378
            env->ir[0] = val;
379
        break;
380
    case 0x00000027:
381
        /* MFPR_ASTSR */
382
        if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
383
            env->ir[0] = val;
384
        break;
385
    case 0x00000029:
386
        /* MFPR_VPTB */
387
        if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
388
            env->ir[0] = val;
389
        break;
390
    case 0x0000002A:
391
        /* MTPR_VPTB */
392
        val = env->ir[16];
393
        if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
394
            env->ir[0] = val;
395
        break;
396
    case 0x0000002B:
397
        /* MTPR_PERFMON */
398
        val = env->ir[16];
399
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
400
            env->ir[0] = val;
401
        break;
402
    case 0x0000002E:
403
        /* MTPR_DATFX */
404
        val = env->ir[16];
405
        if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
406
            env->ir[0] = val;
407
        break;
408
    case 0x0000003E:
409
        /* WTINT */
410
        break;
411
    case 0x0000003F:
412
        /* MFPR_WHAMI */
413
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
414
            env->ir[0] = val;
415
        break;
416
    case 0x00000080:
417
        /* BPT */
418
        /* REQUIRED */
419
        break;
420
    case 0x00000081:
421
        /* BUGCHK */
422
        /* REQUIRED */
423
        break;
424
    case 0x00000082:
425
        /* CHME */
426
        break;
427
    case 0x00000083:
428
        /* CHMK */
429
        break;
430
    case 0x00000084:
431
        /* CHMS */
432
        break;
433
    case 0x00000085:
434
        /* CHMU */
435
        break;
436
    case 0x00000086:
437
        /* IMB */
438
        /* REQUIRED */
439
        /* Implemented as no-op */
440
        break;
441
    case 0x00000087:
442
        /* INSQHIL */
443
        break;
444
    case 0x00000088:
445
        /* INSQTIL */
446
        break;
447
    case 0x00000089:
448
        /* INSQHIQ */
449
        break;
450
    case 0x0000008A:
451
        /* INSQTIQ */
452
        break;
453
    case 0x0000008B:
454
        /* INSQUEL */
455
        break;
456
    case 0x0000008C:
457
        /* INSQUEQ */
458
        break;
459
    case 0x0000008D:
460
        /* INSQUEL/D */
461
        break;
462
    case 0x0000008E:
463
        /* INSQUEQ/D */
464
        break;
465
    case 0x0000008F:
466
        /* PROBER */
467
        break;
468
    case 0x00000090:
469
        /* PROBEW */
470
        break;
471
    case 0x00000091:
472
        /* RD_PS */
473
        break;
474
    case 0x00000092:
475
        /* REI */
476
        break;
477
    case 0x00000093:
478
        /* REMQHIL */
479
        break;
480
    case 0x00000094:
481
        /* REMQTIL */
482
        break;
483
    case 0x00000095:
484
        /* REMQHIQ */
485
        break;
486
    case 0x00000096:
487
        /* REMQTIQ */
488
        break;
489
    case 0x00000097:
490
        /* REMQUEL */
491
        break;
492
    case 0x00000098:
493
        /* REMQUEQ */
494
        break;
495
    case 0x00000099:
496
        /* REMQUEL/D */
497
        break;
498
    case 0x0000009A:
499
        /* REMQUEQ/D */
500
        break;
501
    case 0x0000009B:
502
        /* SWASTEN */
503
        break;
504
    case 0x0000009C:
505
        /* WR_PS_SW */
506
        break;
507
    case 0x0000009D:
508
        /* RSCC */
509
        break;
510
    case 0x0000009E:
511
        /* READ_UNQ */
512
        /* REQUIRED */
513
        break;
514
    case 0x0000009F:
515
        /* WRITE_UNQ */
516
        /* REQUIRED */
517
        break;
518
    case 0x000000A0:
519
        /* AMOVRR */
520
        break;
521
    case 0x000000A1:
522
        /* AMOVRM */
523
        break;
524
    case 0x000000A2:
525
        /* INSQHILR */
526
        break;
527
    case 0x000000A3:
528
        /* INSQTILR */
529
        break;
530
    case 0x000000A4:
531
        /* INSQHIQR */
532
        break;
533
    case 0x000000A5:
534
        /* INSQTIQR */
535
        break;
536
    case 0x000000A6:
537
        /* REMQHILR */
538
        break;
539
    case 0x000000A7:
540
        /* REMQTILR */
541
        break;
542
    case 0x000000A8:
543
        /* REMQHIQR */
544
        break;
545
    case 0x000000A9:
546
        /* REMQTIQR */
547
        break;
548
    case 0x000000AA:
549
        /* GENTRAP */
550
        /* REQUIRED */
551
        break;
552
    case 0x000000AE:
553
        /* CLRFEN */
554
        break;
555
    default:
556
        break;
557
    }
558
}
559

  
560
static void pal_unix_call (CPUState *env, uint32_t palcode)
561
{
562
    uint64_t palid, val, oldval;
563

  
564
    if (palcode < 0x00000080) {
565
        /* Privileged palcodes */
566
        if (!(env->ps >> 3)) {
567
            /* TODO: generate privilege exception */
568
        }
569
    }
570
    switch (palcode) {
571
    case 0x00000000:
572
        /* HALT */
573
        /* REQUIRED */
574
        break;
575
    case 0x00000001:
576
        /* CFLUSH */
577
        break;
578
    case 0x00000002:
579
        /* DRAINA */
580
        /* REQUIRED */
581
        /* Implemented as no-op */
582
        break;
583
    case 0x00000009:
584
        /* CSERVE */
585
        /* REQUIRED */
586
        break;
587
    case 0x0000000A:
588
        /* SWPPAL */
589
        /* REQUIRED */
590
        palid = env->ir[16];
591
        do_swappal(env, palid);
592
        break;
593
    case 0x0000000D:
594
        /* WRIPIR */
595
        val = env->ir[16];
596
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
597
            env->ir[0] = val;
598
        break;
599
    case 0x00000010:
600
        /* RDMCES */
601
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
602
            env->ir[0] = val;
603
        break;
604
    case 0x00000011:
605
        /* WRMCES */
606
        val = env->ir[16];
607
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
608
            env->ir[0] = val;
609
        break;
610
    case 0x0000002B:
611
        /* WRFEN */
612
        val = env->ir[16];
613
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
614
            env->ir[0] = val;
615
        break;
616
    case 0x0000002D:
617
        /* WRVPTPTR */
618
        break;
619
    case 0x00000030:
620
        /* SWPCTX */
621
        break;
622
    case 0x00000031:
623
        /* WRVAL */
624
        break;
625
    case 0x00000032:
626
        /* RDVAL */
627
        break;
628
    case 0x00000033:
629
        /* TBI */
630
        val = env->ir[16];
631
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
632
            env->ir[0] = val;
633
        break;
634
    case 0x00000034:
635
        /* WRENT */
636
        break;
637
    case 0x00000035:
638
        /* SWPIPL */
639
        break;
640
    case 0x00000036:
641
        /* RDPS */
642
        break;
643
    case 0x00000037:
644
        /* WRKGP */
645
        break;
646
    case 0x00000038:
647
        /* WRUSP */
648
        val = env->ir[16];
649
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
650
            env->ir[0] = val;
651
        break;
652
    case 0x00000039:
653
        /* WRPERFMON */
654
        val = env->ir[16];
655
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
656
            env->ir[0] = val;
657
        break;
658
    case 0x0000003A:
659
        /* RDUSP */
660
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
661
            env->ir[0] = val;
662
        break;
663
    case 0x0000003C:
664
        /* WHAMI */
665
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
666
            env->ir[0] = val;
667
        break;
668
    case 0x0000003D:
669
        /* RETSYS */
670
        break;
671
    case 0x0000003E:
672
        /* WTINT */
673
        break;
674
    case 0x0000003F:
675
        /* RTI */
676
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
677
            env->ir[0] = val;
678
        break;
679
    case 0x00000080:
680
        /* BPT */
681
        /* REQUIRED */
682
        break;
683
    case 0x00000081:
684
        /* BUGCHK */
685
        /* REQUIRED */
686
        break;
687
    case 0x00000083:
688
        /* CALLSYS */
689
        break;
690
    case 0x00000086:
691
        /* IMB */
692
        /* REQUIRED */
693
        /* Implemented as no-op */
694
        break;
695
    case 0x00000092:
696
        /* URTI */
697
        break;
698
    case 0x0000009E:
699
        /* RDUNIQUE */
700
        /* REQUIRED */
701
        break;
702
    case 0x0000009F:
703
        /* WRUNIQUE */
704
        /* REQUIRED */
705
        break;
706
    case 0x000000AA:
707
        /* GENTRAP */
708
        /* REQUIRED */
709
        break;
710
    case 0x000000AE:
711
        /* CLRFEN */
712
        break;
713
    default:
714
        break;
715
    }
716
}
717

  
718
void call_pal (CPUState *env)
719
{
720
    pal_handler_t *pal_handler = env->pal_handler;
721

  
722
    switch (env->exception_index) {
723
    case EXCP_RESET:
724
        (*pal_handler->reset)(env);
725
        break;
726
    case EXCP_MCHK:
727
        (*pal_handler->machine_check)(env);
728
        break;
729
    case EXCP_ARITH:
730
        (*pal_handler->arithmetic)(env);
731
        break;
732
    case EXCP_INTERRUPT:
733
        (*pal_handler->interrupt)(env);
734
        break;
735
    case EXCP_DFAULT:
736
        (*pal_handler->dfault)(env);
737
        break;
738
    case EXCP_DTB_MISS_PAL:
739
        (*pal_handler->dtb_miss_pal)(env);
740
        break;
741
    case EXCP_DTB_MISS_NATIVE:
742
        (*pal_handler->dtb_miss_native)(env);
743
        break;
744
    case EXCP_UNALIGN:
745
        (*pal_handler->unalign)(env);
746
        break;
747
    case EXCP_ITB_MISS:
748
        (*pal_handler->itb_miss)(env);
749
        break;
750
    case EXCP_ITB_ACV:
751
        (*pal_handler->itb_acv)(env);
752
        break;
753
    case EXCP_OPCDEC:
754
        (*pal_handler->opcdec)(env);
755
        break;
756
    case EXCP_FEN:
757
        (*pal_handler->fen)(env);
758
        break;
759
    default:
760
        if (env->exception_index >= EXCP_CALL_PAL &&
761
            env->exception_index < EXCP_CALL_PALP) {
762
            /* Unprivileged PAL call */
763
            (*pal_handler->call_pal)
764
                (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
765
        } else if (env->exception_index >= EXCP_CALL_PALP &&
766
                   env->exception_index < EXCP_CALL_PALE) {
767
            /* Privileged PAL call */
768
            (*pal_handler->call_pal)
769
                (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
770
        } else {
771
            /* Should never happen */
772
        }
773
        break;
774
    }
775
    env->ipr[IPR_EXC_ADDR] &= ~1;
776
}
777

  
778
void pal_init (CPUState *env)
779
{
780
    do_swappal(env, 0);
781
}
782

  
783
#if 0
784
static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
785
{
786
    uint64_t virbnd, ptbr;
787

  
788
    if ((env->features & FEATURE_VIRBND)) {
789
        cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
790
        if (vaddr >= virbnd)
791
            cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
792
        else
793
            cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
794
    } else {
795
        cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
796
    }
797

  
798
    return ptbr;
799
}
800

  
801
static int get_page_bits (CPUState *env)
802
{
803
    /* XXX */
804
    return 13;
805
}
806

  
807
static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
808
                    uint64_t ptebase, int page_bits, uint64_t level,
809
                    int mmu_idx, int rw)
810
{
811
    uint64_t pteaddr, pte, pfn;
812
    uint8_t gh;
813
    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
814

  
815
    /* XXX: TOFIX */
816
    is_user = mmu_idx == MMU_USER_IDX;
817
    pteaddr = (ptebase << page_bits) + (8 * level);
818
    pte = ldq_raw(pteaddr);
819
    /* Decode all interresting PTE fields */
820
    pfn = pte >> 32;
821
    uwe = (pte >> 13) & 1;
822
    kwe = (pte >> 12) & 1;
823
    ure = (pte >> 9) & 1;
824
    kre = (pte >> 8) & 1;
825
    gh = (pte >> 5) & 3;
826
    foE = (pte >> 3) & 1;
827
    foW = (pte >> 2) & 1;
828
    foR = (pte >> 1) & 1;
829
    v = pte & 1;
830
    ret = 0;
831
    if (!v)
832
        ret = 0x1;
833
    /* Check access rights */
834
    ar = 0;
835
    if (is_user) {
836
        if (ure)
837
            ar |= PAGE_READ;
838
        if (uwe)
839
            ar |= PAGE_WRITE;
840
        if (rw == 1 && !uwe)
841
            ret |= 0x2;
842
        if (rw != 1 && !ure)
843
            ret |= 0x2;
844
    } else {
845
        if (kre)
846
            ar |= PAGE_READ;
847
        if (kwe)
848
            ar |= PAGE_WRITE;
849
        if (rw == 1 && !kwe)
850
            ret |= 0x2;
851
        if (rw != 1 && !kre)
852
            ret |= 0x2;
853
    }
854
    if (rw == 0 && foR)
855
        ret |= 0x4;
856
    if (rw == 2 && foE)
857
        ret |= 0x8;
858
    if (rw == 1 && foW)
859
        ret |= 0xC;
860
    *pfnp = pfn;
861
    if (zbitsp != NULL)
862
        *zbitsp = page_bits + (3 * gh);
863
    if (protp != NULL)
864
        *protp = ar;
865

  
866
    return ret;
867
}
868

  
869
static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
870
                           uint64_t ptebase, int page_bits,
871
                           uint64_t vaddr, int mmu_idx, int rw)
872
{
873
    uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
874
    int lvl_bits, ret;
875

  
876
    page_mask = (1ULL << page_bits) - 1ULL;
877
    lvl_bits = page_bits - 3;
878
    lvl_mask = (1ULL << lvl_bits) - 1ULL;
879
    level3 = (vaddr >> page_bits) & lvl_mask;
880
    level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
881
    level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
882
    /* Level 1 PTE */
883
    ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
884
    switch (ret) {
885
    case 3:
886
        /* Access violation */
887
        return 2;
888
    case 2:
889
        /* translation not valid */
890
        return 1;
891
    default:
892
        /* OK */
893
        break;
894
    }
895
    /* Level 2 PTE */
896
    ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
897
    switch (ret) {
898
    case 3:
899
        /* Access violation */
900
        return 2;
901
    case 2:
902
        /* translation not valid */
903
        return 1;
904
    default:
905
        /* OK */
906
        break;
907
    }
908
    /* Level 3 PTE */
909
    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
910
    if (ret & 0x1) {
911
        /* Translation not valid */
912
        ret = 1;
913
    } else if (ret & 2) {
914
        /* Access violation */
915
        ret = 2;
916
    } else {
917
        switch (ret & 0xC) {
918
        case 0:
919
            /* OK */
920
            ret = 0;
921
            break;
922
        case 0x4:
923
            /* Fault on read */
924
            ret = 3;
925
            break;
926
        case 0x8:
927
            /* Fault on execute */
928
            ret = 4;
929
            break;
930
        case 0xC:
931
            /* Fault on write */
932
            ret = 5;
933
            break;
934
        }
935
    }
936
    *paddr = (pfn << page_bits) | (vaddr & page_mask);
937

  
938
    return 0;
939
}
940

  
941
static int virtual_to_physical (CPUState *env, uint64_t *physp,
942
                                int *zbitsp, int *protp,
943
                                uint64_t virtual, int mmu_idx, int rw)
944
{
945
    uint64_t sva, ptebase;
946
    int seg, page_bits, ret;
947

  
948
    sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
949
    if (sva != virtual)
950
        seg = -1;
951
    else
952
        seg = sva >> (VA_BITS - 2);
953
    virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
954
    ptebase = get_ptebase(env, virtual);
955
    page_bits = get_page_bits(env);
956
    ret = 0;
957
    switch (seg) {
958
    case 0:
959
        /* seg1: 3 levels of PTE */
960
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
961
                             virtual, mmu_idx, rw);
962
        break;
963
    case 1:
964
        /* seg1: 2 levels of PTE */
965
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
966
                             virtual, mmu_idx, rw);
967
        break;
968
    case 2:
969
        /* kernel segment */
970
        if (mmu_idx != 0) {
971
            ret = 2;
972
        } else {
973
            *physp = virtual;
974
        }
975
        break;
976
    case 3:
977
        /* seg1: TB mapped */
978
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
979
                             virtual, mmu_idx, rw);
980
        break;
981
    default:
982
        ret = 1;
983
        break;
984
    }
985

  
986
    return ret;
987
}
988

  
989
/* XXX: code provision */
990
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
991
                              int mmu_idx, int is_softmmu)
992
{
993
    uint64_t physical, page_size, end;
994
    int prot, zbits, ret;
995

  
996
    ret = virtual_to_physical(env, &physical, &zbits, &prot,
997
                              address, mmu_idx, rw);
998

  
999
    switch (ret) {
1000
    case 0:
1001
        /* No fault */
1002
        page_size = 1ULL << zbits;
1003
        address &= ~(page_size - 1);
1004
        /* FIXME: page_size should probably be passed to tlb_set_page,
1005
           and this loop removed.   */
1006
        for (end = physical + page_size; physical < end; physical += 0x1000) {
1007
            tlb_set_page(env, address, physical, prot, mmu_idx,
1008
                         TARGET_PAGE_SIZE);
1009
            address += 0x1000;
1010
        }
1011
        ret = 0;
1012
        break;
1013
#if 0
1014
    case 1:
1015
        env->exception_index = EXCP_DFAULT;
1016
        env->ipr[IPR_EXC_ADDR] = address;
1017
        ret = 1;
1018
        break;
1019
    case 2:
1020
        env->exception_index = EXCP_ACCESS_VIOLATION;
1021
        env->ipr[IPR_EXC_ADDR] = address;
1022
        ret = 1;
1023
        break;
1024
    case 3:
1025
        env->exception_index = EXCP_FAULT_ON_READ;
1026
        env->ipr[IPR_EXC_ADDR] = address;
1027
        ret = 1;
1028
        break;
1029
    case 4:
1030
        env->exception_index = EXCP_FAULT_ON_EXECUTE;
1031
        env->ipr[IPR_EXC_ADDR] = address;
1032
        ret = 1;
1033
    case 5:
1034
        env->exception_index = EXCP_FAULT_ON_WRITE;
1035
        env->ipr[IPR_EXC_ADDR] = address;
1036
        ret = 1;
1037
#endif
1038
    default:
1039
        /* Should never happen */
1040
        env->exception_index = EXCP_MCHK;
1041
        env->ipr[IPR_EXC_ADDR] = address;
1042
        ret = 1;
1043
        break;
1044
    }
1045

  
1046
    return ret;
1047
}
1048
#endif
b/target-alpha/cpu.h
319 319

  
320 320
typedef struct CPUAlphaState CPUAlphaState;
321 321

  
322
typedef struct pal_handler_t pal_handler_t;
323
struct pal_handler_t {
324
    /* Reset */
325
    void (*reset)(CPUAlphaState *env);
326
    /* Uncorrectable hardware error */
327
    void (*machine_check)(CPUAlphaState *env);
328
    /* Arithmetic exception */
329
    void (*arithmetic)(CPUAlphaState *env);
330
    /* Interrupt / correctable hardware error */
331
    void (*interrupt)(CPUAlphaState *env);
332
    /* Data fault */
333
    void (*dfault)(CPUAlphaState *env);
334
    /* DTB miss pal */
335
    void (*dtb_miss_pal)(CPUAlphaState *env);
336
    /* DTB miss native */
337
    void (*dtb_miss_native)(CPUAlphaState *env);
338
    /* Unaligned access */
339
    void (*unalign)(CPUAlphaState *env);
340
    /* ITB miss */
341
    void (*itb_miss)(CPUAlphaState *env);
342
    /* Instruction stream access violation */
343
    void (*itb_acv)(CPUAlphaState *env);
344
    /* Reserved or privileged opcode */
345
    void (*opcdec)(CPUAlphaState *env);
346
    /* Floating point exception */
347
    void (*fen)(CPUAlphaState *env);
348
    /* Call pal instruction */
349
    void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
350
};
351

  
352 322
#define NB_MMU_MODES 4
353 323

  
354 324
struct CPUAlphaState {
......
393 363
    uint32_t features;
394 364
    uint32_t amask;
395 365
    int implver;
396
    pal_handler_t *pal_handler;
397 366
};
398 367

  
399 368
#define cpu_init cpu_alpha_init
......
506 475
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
507 476
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
508 477
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
509
#if !defined (CONFIG_USER_ONLY)
510
void pal_init (CPUState *env);
511
void call_pal (CPUState *env);
512
#endif
513 478

  
514 479
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
515 480
                                        target_ulong *cs_base, int *flags)
b/target-alpha/helper.c
528 528
        env->pc = env->ipr[IPR_PAL_BASE] + excp;
529 529
    } else {
530 530
        /* We use emulated PALcode */
531
        call_pal(env);
531
        abort();
532 532
        /* Emulate REI */
533 533
        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
534 534
        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
b/target-alpha/translate.c
3335 3335
    env->ps |= 1 << 3;
3336 3336
    cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
3337 3337
                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
3338
#else
3339
    pal_init(env);
3340 3338
#endif
3341 3339
    env->lock_addr = -1;
3342 3340

  

Also available in: Unified diff