OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [vm.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _VM_C_
23
#define _VM_C_
24
 
25
#if 0
26
#include "basics.h"
27
#include "registers.h"
28
#include "device.h"
29
#include "corefile.h"
30
#include "vm.h"
31
#include "interrupts.h"
32
#include "mon.h"
33
#endif
34
 
35
#include "cpu.h"
36
 
37
/* OEA vs VEA
38
 
39
   For the VEA model, the VM layer is almost transparent.  It's only
40
   purpose is to maintain separate core_map's for the instruction
41
   and data address spaces.  This being so that writes to instruction
42
   space or execution of a data space is prevented.
43
 
44
   For the OEA model things are more complex.  The reason for separate
45
   instruction and data models becomes crucial.  The OEA model is
46
   built out of three parts.  An instruction map, a data map and an
47
   underlying structure that provides access to the VM data kept in
48
   main memory. */
49
 
50
 
51
/* OEA data structures:
52
 
53
   The OEA model maintains internal data structures that shadow the
54
   semantics of the various OEA VM registers (BAT, SR, etc).  This
55
   allows a simple efficient model of the VM to be implemented.
56
 
57
   Consistency between OEA registers and this model's internal data
58
   structures is maintained by updating the structures at
59
   `synchronization' points.  Of particular note is that (at the time
60
   of writing) the memory data types for BAT registers are rebuilt
61
   when ever the processor moves between problem and system states.
62
 
63
   Unpacked values are stored in the OEA so that they correctly align
64
   to where they will be needed by the PTE address. */
65
 
66
 
67
/* Protection table:
68
 
69
   Matrix of processor state, type of access and validity */
70
 
71
typedef enum {
72
  om_supervisor_state,
73
  om_problem_state,
74
  nr_om_modes
75
} om_processor_modes;
76
 
77
typedef enum {
78
  om_data_read, om_data_write,
79
  om_instruction_read, om_access_any,
80
  nr_om_access_types
81
} om_access_types;
82
 
83
static int om_valid_access[2][4][nr_om_access_types] = {
84
  /* read, write, instruction, any */
85
  /* K bit == 0 */
86
  { /*r  w  i  a       pp */
87
    { 1, 1, 1, 1 }, /* 00 */
88
    { 1, 1, 1, 1 }, /* 01 */
89
    { 1, 1, 1, 1 }, /* 10 */
90
    { 1, 0, 1, 1 }, /* 11 */
91
  },
92
  /* K bit == 1  or P bit valid */
93
  { /*r  w  i  a       pp */
94
    { 0, 0, 0, 0 }, /* 00 */
95
    { 1, 0, 1, 1 }, /* 01 */
96
    { 1, 1, 1, 1 }, /* 10 */
97
    { 1, 0, 1, 1 }, /* 11 */
98
  }
99
};
100
 
101
 
102
/* Bat translation:
103
 
104
   The bat data structure only contains information on valid BAT
105
   translations for the current processor mode and type of access. */
106
 
107
typedef struct _om_bat {
108
  unsigned_word block_effective_page_index;
109
  unsigned_word block_effective_page_index_mask;
110
  unsigned_word block_length_mask;
111
  unsigned_word block_real_page_number;
112
  int protection_bits;
113
} om_bat;
114
 
115
enum _nr_om_bat_registers {
116
  nr_om_bat_registers = 4
117
};
118
 
119
typedef struct _om_bats {
120
  int nr_valid_bat_registers;
121
  om_bat bat[nr_om_bat_registers];
122
} om_bats;
123
 
124
 
125
/* Segment TLB:
126
 
127
   In this model the 32 and 64 bit segment tables are treated in very
128
   similar ways.  The 32bit segment registers are treated as a
129
   simplification of the 64bit segment tlb */
130
 
131
enum _om_segment_tlb_constants {
132
#if (WITH_TARGET_WORD_BITSIZE == 64)
133
  sizeof_segment_table_entry_group = 128,
134
  sizeof_segment_table_entry = 16,
135
#endif
136
  om_segment_tlb_index_start_bit = 32,
137
  om_segment_tlb_index_stop_bit = 35,
138
  nr_om_segment_tlb_entries = 16,
139
  nr_om_segment_tlb_constants
140
};
141
 
142
typedef struct _om_segment_tlb_entry {
143
  int key[nr_om_modes];
144
  om_access_types invalid_access; /* set to instruction if no_execute bit */
145
  unsigned_word masked_virtual_segment_id; /* aligned ready for pte group addr */
146
#if (WITH_TARGET_WORD_BITSIZE == 64)
147
  int is_valid;
148
  unsigned_word masked_effective_segment_id;
149
#endif
150
} om_segment_tlb_entry;
151
 
152
typedef struct _om_segment_tlb {
153
  om_segment_tlb_entry entry[nr_om_segment_tlb_entries];
154
} om_segment_tlb;
155
 
156
 
157
/* Page TLB:
158
 
159
   This OEA model includes a small direct map Page TLB.  The tlb is to
160
   cut down on the need for the OEA to perform walks of the page hash
161
   table. */
162
 
163
enum _om_page_tlb_constants {
164
  om_page_tlb_index_start_bit = 46,
165
  om_page_tlb_index_stop_bit = 51,
166
  nr_om_page_tlb_entries = 64,
167
#if (WITH_TARGET_WORD_BITSIZE == 64)
168
  sizeof_pte_group = 128,
169
  sizeof_pte = 16,
170
#endif
171
#if (WITH_TARGET_WORD_BITSIZE == 32)
172
  sizeof_pte_group = 64,
173
  sizeof_pte = 8,
174
#endif
175
  nr_om_page_tlb_constants
176
};
177
 
178
typedef struct _om_page_tlb_entry {
179
  int protection;
180
  int changed;
181
  unsigned_word real_address_of_pte_1;
182
  unsigned_word masked_virtual_segment_id;
183
  unsigned_word masked_page;
184
  unsigned_word masked_real_page_number;
185
} om_page_tlb_entry;
186
 
187
typedef struct _om_page_tlb {
188
  om_page_tlb_entry entry[nr_om_page_tlb_entries];
189
} om_page_tlb;
190
 
191
 
192
/* memory translation:
193
 
194
   OEA memory translation possibly involves BAT, SR, TLB and HTAB
195
   information*/
196
 
197
typedef struct _om_map {
198
 
199
  /* local cache of register values */
200
  int is_relocate;
201
  int is_problem_state;
202
 
203
  /* block address translation */
204
  om_bats *bat_registers;
205
 
206
  /* failing that, translate ea to va using segment tlb */
207
#if (WITH_TARGET_WORD_BITSIZE == 64)
208
  unsigned_word real_address_of_segment_table;
209
#endif
210
  om_segment_tlb *segment_tlb;
211
 
212
  /* then va to ra using hashed page table and tlb */
213
  unsigned_word real_address_of_page_table;
214
  unsigned_word page_table_hash_mask;
215
  om_page_tlb *page_tlb;
216
 
217
  /* physical memory for fetching page table entries */
218
  core_map *physical;
219
 
220
  /* address xor for PPC endian */
221
  unsigned xor[WITH_XOR_ENDIAN];
222
 
223
} om_map;
224
 
225
 
226
/* VM objects:
227
 
228
   External objects defined by vm.h */
229
 
230
struct _vm_instruction_map {
231
  /* real memory for last part */
232
  core_map *code;
233
  /* translate effective to real */
234
  om_map translation;
235
};
236
 
237
struct _vm_data_map {
238
  /* translate effective to real */
239
  om_map translation;
240
  /* real memory for translated address */
241
  core_map *read;
242
  core_map *write;
243
};
244
 
245
 
246
/* VM:
247
 
248
   Underlying memory object.  For the VEA this is just the
249
   core_map. For OEA it is the instruction and data memory
250
   translation's */
251
 
252
struct _vm {
253
 
254
  /* OEA: base address registers */
255
  om_bats ibats;
256
  om_bats dbats;
257
 
258
  /* OEA: segment registers */
259
  om_segment_tlb segment_tlb;
260
 
261
  /* OEA: translation lookaside buffers */
262
  om_page_tlb instruction_tlb;
263
  om_page_tlb data_tlb;
264
 
265
  /* real memory */
266
  core *physical;
267
 
268
  /* memory maps */
269
  vm_instruction_map instruction_map;
270
  vm_data_map data_map;
271
 
272
};
273
 
274
 
275
/* OEA Support procedures */
276
 
277
 
278
STATIC_INLINE_VM\
279
(unsigned_word)
280
om_segment_tlb_index(unsigned_word ea)
281
{
282
  unsigned_word index = EXTRACTED(ea,
283
                                  om_segment_tlb_index_start_bit,
284
                                  om_segment_tlb_index_stop_bit);
285
  return index;
286
}
287
 
288
STATIC_INLINE_VM\
289
(unsigned_word)
290
om_page_tlb_index(unsigned_word ea)
291
{
292
  unsigned_word index = EXTRACTED(ea,
293
                                  om_page_tlb_index_start_bit,
294
                                  om_page_tlb_index_stop_bit);
295
  return index;
296
}
297
 
298
STATIC_INLINE_VM\
299
(unsigned_word)
300
om_hash_page(unsigned_word masked_vsid,
301
             unsigned_word ea)
302
{
303
  unsigned_word extracted_ea = EXTRACTED(ea, 36, 51);
304
#if (WITH_TARGET_WORD_BITSIZE == 32)
305
  unsigned_word masked_ea = INSERTED32(extracted_ea, 7, 31-6);
306
  unsigned_word hash = masked_vsid ^ masked_ea;
307
#endif
308
#if (WITH_TARGET_WORD_BITSIZE == 64)
309
  unsigned_word masked_ea = INSERTED64(extracted_ea, 18, 63-7);
310
  unsigned_word hash = masked_vsid ^ masked_ea;
311
#endif
312
  TRACE(trace_vm, ("ea=0x%lx - masked-vsid=0x%lx masked-ea=0x%lx hash=0x%lx\n",
313
                   (unsigned long)ea,
314
                   (unsigned long)masked_vsid,
315
                   (unsigned long)masked_ea,
316
                   (unsigned long)hash));
317
  return hash;
318
}
319
 
320
STATIC_INLINE_VM\
321
(unsigned_word)
322
om_pte_0_api(unsigned_word pte_0)
323
{
324
#if (WITH_TARGET_WORD_BITSIZE == 32)
325
  return EXTRACTED32(pte_0, 26, 31);
326
#endif
327
#if (WITH_TARGET_WORD_BITSIZE == 64)
328
  return EXTRACTED64(pte_0, 52, 56);
329
#endif
330
}
331
 
332
STATIC_INLINE_VM\
333
(unsigned_word)
334
om_pte_0_hash(unsigned_word pte_0)
335
{
336
#if (WITH_TARGET_WORD_BITSIZE == 32)
337
  return EXTRACTED32(pte_0, 25, 25);
338
#endif
339
#if (WITH_TARGET_WORD_BITSIZE == 64)
340
  return EXTRACTED64(pte_0, 62, 62);
341
#endif
342
}
343
 
344
STATIC_INLINE_VM\
345
(int)
346
om_pte_0_valid(unsigned_word pte_0)
347
{
348
#if (WITH_TARGET_WORD_BITSIZE == 32)
349
  return MASKED32(pte_0, 0, 0) != 0;
350
#endif
351
#if (WITH_TARGET_WORD_BITSIZE == 64)
352
  return MASKED64(pte_0, 63, 63) != 0;
353
#endif
354
}
355
 
356
STATIC_INLINE_VM\
357
(unsigned_word)
358
om_ea_masked_page(unsigned_word ea)
359
{
360
  return MASKED(ea, 36, 51);
361
}
362
 
363
STATIC_INLINE_VM\
364
(unsigned_word)
365
om_ea_masked_byte(unsigned_word ea)
366
{
367
  return MASKED(ea, 52, 63);
368
}
369
 
370
/* return the VSID aligned for pte group addr */
371
STATIC_INLINE_VM\
372
(unsigned_word)
373
om_pte_0_masked_vsid(unsigned_word pte_0)
374
{
375
#if (WITH_TARGET_WORD_BITSIZE == 32)
376
  return INSERTED32(EXTRACTED32(pte_0, 1, 24), 31-6-24+1, 31-6);
377
#endif
378
#if (WITH_TARGET_WORD_BITSIZE == 64)
379
  return INSERTED64(EXTRACTED64(pte_0, 0, 51), 63-7-52+1, 63-7);
380
#endif
381
}
382
 
383
STATIC_INLINE_VM\
384
(unsigned_word)
385
om_pte_1_pp(unsigned_word pte_1)
386
{
387
  return MASKED(pte_1, 62, 63); /*PP*/
388
}
389
 
390
STATIC_INLINE_VM\
391
(int)
392
om_pte_1_referenced(unsigned_word pte_1)
393
{
394
  return EXTRACTED(pte_1, 55, 55);
395
}
396
 
397
STATIC_INLINE_VM\
398
(int)
399
om_pte_1_changed(unsigned_word pte_1)
400
{
401
  return EXTRACTED(pte_1, 56, 56);
402
}
403
 
404
STATIC_INLINE_VM\
405
(int)
406
om_pte_1_masked_rpn(unsigned_word pte_1)
407
{
408
  return MASKED(pte_1, 0, 51); /*RPN*/
409
}
410
 
411
STATIC_INLINE_VM\
412
(unsigned_word)
413
om_ea_api(unsigned_word ea)
414
{
415
  return EXTRACTED(ea, 36, 41);
416
}
417
 
418
 
419
/* Page and Segment table read/write operators, these need to still
420
   account for the PPC's XOR operation */
421
 
422
STATIC_INLINE_VM\
423
(unsigned_word)
424
om_read_word(om_map *map,
425
             unsigned_word ra,
426
             cpu *processor,
427
             unsigned_word cia)
428
{
429
  if (WITH_XOR_ENDIAN)
430
    ra ^= map->xor[sizeof(instruction_word) - 1];
431
  return core_map_read_word(map->physical, ra, processor, cia);
432
}
433
 
434
STATIC_INLINE_VM\
435
(void)
436
om_write_word(om_map *map,
437
              unsigned_word ra,
438
              unsigned_word val,
439
              cpu *processor,
440
              unsigned_word cia)
441
{
442
  if (WITH_XOR_ENDIAN)
443
    ra ^= map->xor[sizeof(instruction_word) - 1];
444
  core_map_write_word(map->physical, ra, val, processor, cia);
445
}
446
 
447
 
448
/* Bring things into existance */
449
 
450
INLINE_VM\
451
(vm *)
452
vm_create(core *physical)
453
{
454
  vm *virtual;
455
 
456
  /* internal checks */
457
  if (nr_om_segment_tlb_entries
458
      != (1 << (om_segment_tlb_index_stop_bit
459
                - om_segment_tlb_index_start_bit + 1)))
460
    error("internal error - vm_create - problem with om_segment constants\n");
461
  if (nr_om_page_tlb_entries
462
      != (1 << (om_page_tlb_index_stop_bit
463
                - om_page_tlb_index_start_bit + 1)))
464
    error("internal error - vm_create - problem with om_page constants\n");
465
 
466
  /* create the new vm register file */
467
  virtual = ZALLOC(vm);
468
 
469
  /* set up core */
470
  virtual->physical = physical;
471
 
472
  /* set up the address decoders */
473
  virtual->instruction_map.translation.bat_registers = &virtual->ibats;
474
  virtual->instruction_map.translation.segment_tlb = &virtual->segment_tlb;
475
  virtual->instruction_map.translation.page_tlb = &virtual->instruction_tlb;
476
  virtual->instruction_map.translation.is_relocate = 0;
477
  virtual->instruction_map.translation.is_problem_state = 0;
478
  virtual->instruction_map.translation.physical = core_readable(physical);
479
  virtual->instruction_map.code = core_readable(physical);
480
 
481
  virtual->data_map.translation.bat_registers = &virtual->dbats;
482
  virtual->data_map.translation.segment_tlb = &virtual->segment_tlb;
483
  virtual->data_map.translation.page_tlb = &virtual->data_tlb;
484
  virtual->data_map.translation.is_relocate = 0;
485
  virtual->data_map.translation.is_problem_state = 0;
486
  virtual->data_map.translation.physical = core_readable(physical);
487
  virtual->data_map.read = core_readable(physical);
488
  virtual->data_map.write = core_writeable(physical);
489
 
490
  return virtual;
491
}
492
 
493
 
494
STATIC_INLINE_VM\
495
(om_bat *)
496
om_effective_to_bat(om_map *map,
497
                    unsigned_word ea)
498
{
499
  int curr_bat = 0;
500
  om_bats *bats = map->bat_registers;
501
  int nr_bats = bats->nr_valid_bat_registers;
502
 
503
  for (curr_bat = 0; curr_bat < nr_bats; curr_bat++) {
504
    om_bat *bat = bats->bat + curr_bat;
505
    if ((ea & bat->block_effective_page_index_mask)
506
        != bat->block_effective_page_index)
507
      continue;
508
    return bat;
509
  }
510
 
511
  return NULL;
512
}
513
 
514
 
515
STATIC_INLINE_VM\
516
(om_segment_tlb_entry *)
517
om_effective_to_virtual(om_map *map,
518
                        unsigned_word ea,
519
                        cpu *processor,
520
                        unsigned_word cia)
521
{
522
  /* first try the segment tlb */
523
  om_segment_tlb_entry *segment_tlb_entry = (map->segment_tlb->entry
524
                                             + om_segment_tlb_index(ea));
525
 
526
#if (WITH_TARGET_WORD_BITSIZE == 32)
527
  TRACE(trace_vm, ("ea=0x%lx - sr[%ld] - masked-vsid=0x%lx va=0x%lx%07lx\n",
528
                   (unsigned long)ea,
529
                   (long)om_segment_tlb_index(ea),
530
                   (unsigned long)segment_tlb_entry->masked_virtual_segment_id,
531
                   (unsigned long)EXTRACTED32(segment_tlb_entry->masked_virtual_segment_id, 31-6-24+1, 31-6),
532
                   (unsigned long)EXTRACTED32(ea, 4, 31)));
533
  return segment_tlb_entry;
534
#endif
535
 
536
#if (WITH_TARGET_WORD_BITSIZE == 64)
537
  if (segment_tlb_entry->is_valid
538
      && (segment_tlb_entry->masked_effective_segment_id == MASKED(ea, 0, 35))) {
539
    error("fixme - is there a need to update any bits\n");
540
    return segment_tlb_entry;
541
  }
542
 
543
  /* drats, segment tlb missed */
544
  {
545
    unsigned_word segment_id_hash = ea;
546
    int current_hash = 0;
547
    for (current_hash = 0; current_hash < 2; current_hash += 1) {
548
      unsigned_word segment_table_entry_group =
549
        (map->real_address_of_segment_table
550
         | (MASKED64(segment_id_hash, 31, 35) >> (56-35)));
551
      unsigned_word segment_table_entry;
552
      for (segment_table_entry = segment_table_entry_group;
553
           segment_table_entry < (segment_table_entry_group
554
                                  + sizeof_segment_table_entry_group);
555
           segment_table_entry += sizeof_segment_table_entry) {
556
        /* byte order? */
557
        unsigned_word segment_table_entry_dword_0 =
558
          om_read_word(map->physical, segment_table_entry, processor, cia);
559
        unsigned_word segment_table_entry_dword_1 =
560
          om_read_word(map->physical, segment_table_entry + 8,
561
                       processor, cia);
562
        int is_valid = MASKED64(segment_table_entry_dword_0, 56, 56) != 0;
563
        unsigned_word masked_effective_segment_id =
564
          MASKED64(segment_table_entry_dword_0, 0, 35);
565
        if (is_valid && masked_effective_segment_id == MASKED64(ea, 0, 35)) {
566
          /* don't permit some things */
567
          if (MASKED64(segment_table_entry_dword_0, 57, 57))
568
            error("om_effective_to_virtual() - T=1 in STE not supported\n");
569
          /* update segment tlb */
570
          segment_tlb_entry->is_valid = is_valid;
571
          segment_tlb_entry->masked_effective_segment_id =
572
            masked_effective_segment_id;
573
          segment_tlb_entry->key[om_supervisor_state] =
574
            EXTRACTED64(segment_table_entry_dword_0, 58, 58);
575
          segment_tlb_entry->key[om_problem_state] =
576
            EXTRACTED64(segment_table_entry_dword_0, 59, 59);
577
          segment_tlb_entry->invalid_access =
578
            (MASKED64(segment_table_entry_dword_0, 60, 60)
579
             ? om_instruction_read
580
             : om_access_any);
581
          segment_tlb_entry->masked_virtual_segment_id =
582
            INSERTED64(EXTRACTED64(segment_table_entry_dword_1, 0, 51),
583
                       18-13, 63-7); /* aligned ready for pte group addr */
584
          return segment_tlb_entry;
585
        }
586
      }
587
      segment_id_hash = ~segment_id_hash;
588
    }
589
  }
590
  return NULL;
591
#endif
592
}
593
 
594
 
595
 
596
STATIC_INLINE_VM\
597
(om_page_tlb_entry *)
598
om_virtual_to_real(om_map *map,
599
                   unsigned_word ea,
600
                   om_segment_tlb_entry *segment_tlb_entry,
601
                   om_access_types access,
602
                   cpu *processor,
603
                   unsigned_word cia)
604
{
605
  om_page_tlb_entry *page_tlb_entry = (map->page_tlb->entry
606
                                       + om_page_tlb_index(ea));
607
 
608
  /* is it a tlb hit? */
609
  if ((page_tlb_entry->masked_virtual_segment_id
610
       == segment_tlb_entry->masked_virtual_segment_id)
611
      && (page_tlb_entry->masked_page
612
          == om_ea_masked_page(ea))) {
613
    TRACE(trace_vm, ("ea=0x%lx - tlb hit - tlb=0x%lx\n",
614
               (long)ea, (long)page_tlb_entry));
615
    return page_tlb_entry;
616
  }
617
 
618
  /* drats, it is a tlb miss */
619
  {
620
    unsigned_word page_hash =
621
      om_hash_page(segment_tlb_entry->masked_virtual_segment_id, ea);
622
    int current_hash;
623
    for (current_hash = 0; current_hash < 2; current_hash += 1) {
624
      unsigned_word real_address_of_pte_group =
625
        (map->real_address_of_page_table
626
         | (page_hash & map->page_table_hash_mask));
627
      unsigned_word real_address_of_pte_0;
628
      TRACE(trace_vm,
629
            ("ea=0x%lx - htab search %d - htab=0x%lx hash=0x%lx mask=0x%lx pteg=0x%lx\n",
630
             (long)ea, current_hash,
631
             map->real_address_of_page_table,
632
             page_hash,
633
             map->page_table_hash_mask,
634
             (long)real_address_of_pte_group));
635
      for (real_address_of_pte_0 = real_address_of_pte_group;
636
           real_address_of_pte_0 < (real_address_of_pte_group
637
                                    + sizeof_pte_group);
638
           real_address_of_pte_0 += sizeof_pte) {
639
        unsigned_word pte_0 = om_read_word(map,
640
                                           real_address_of_pte_0,
641
                                           processor, cia);
642
        /* did we hit? */
643
        if (om_pte_0_valid(pte_0)
644
            && (current_hash == om_pte_0_hash(pte_0))
645
            && (segment_tlb_entry->masked_virtual_segment_id
646
                == om_pte_0_masked_vsid(pte_0))
647
            && (om_ea_api(ea) == om_pte_0_api(pte_0))) {
648
          unsigned_word real_address_of_pte_1 = (real_address_of_pte_0
649
                                                 + sizeof_pte / 2);
650
          unsigned_word pte_1 = om_read_word(map,
651
                                             real_address_of_pte_1,
652
                                             processor, cia);
653
          page_tlb_entry->protection = om_pte_1_pp(pte_1);
654
          page_tlb_entry->changed = om_pte_1_changed(pte_1);
655
          page_tlb_entry->masked_virtual_segment_id = segment_tlb_entry->masked_virtual_segment_id;
656
          page_tlb_entry->masked_page = om_ea_masked_page(ea);
657
          page_tlb_entry->masked_real_page_number = om_pte_1_masked_rpn(pte_1);
658
          page_tlb_entry->real_address_of_pte_1 = real_address_of_pte_1;
659
          if (!om_pte_1_referenced(pte_1)) {
660
            om_write_word(map,
661
                          real_address_of_pte_1,
662
                          pte_1 | BIT(55),
663
                          processor, cia);
664
            TRACE(trace_vm,
665
                  ("ea=0x%lx - htab hit - set ref - tlb=0x%lx &pte1=0x%lx\n",
666
                   (long)ea, (long)page_tlb_entry, (long)real_address_of_pte_1));
667
          }
668
          else {
669
            TRACE(trace_vm,
670
                  ("ea=0x%lx - htab hit - tlb=0x%lx &pte1=0x%lx\n",
671
                   (long)ea, (long)page_tlb_entry, (long)real_address_of_pte_1));
672
          }
673
          return page_tlb_entry;
674
        }
675
      }
676
      page_hash = ~page_hash; /*???*/
677
    }
678
  }
679
  return NULL;
680
}
681
 
682
 
683
STATIC_INLINE_VM\
684
(void)
685
om_interrupt(cpu *processor,
686
             unsigned_word cia,
687
             unsigned_word ea,
688
             om_access_types access,
689
             storage_interrupt_reasons reason)
690
{
691
  switch (access) {
692
  case om_data_read:
693
    data_storage_interrupt(processor, cia, ea, reason, 0/*!is_store*/);
694
    break;
695
  case om_data_write:
696
    data_storage_interrupt(processor, cia, ea, reason, 1/*is_store*/);
697
    break;
698
  case om_instruction_read:
699
    instruction_storage_interrupt(processor, cia, reason);
700
    break;
701
  default:
702
    error("internal error - om_interrupt - unexpected access type %d", access);
703
  }
704
}
705
 
706
 
707
STATIC_INLINE_VM\
708
(unsigned_word)
709
om_translate_effective_to_real(om_map *map,
710
                               unsigned_word ea,
711
                               om_access_types access,
712
                               cpu *processor,
713
                               unsigned_word cia,
714
                               int abort)
715
{
716
  om_bat *bat = NULL;
717
  om_segment_tlb_entry *segment_tlb_entry = NULL;
718
  om_page_tlb_entry *page_tlb_entry = NULL;
719
  unsigned_word ra;
720
 
721
  if (!map->is_relocate) {
722
    ra = ea;
723
    TRACE(trace_vm, ("ea=0x%lx - direct map - ra=0x%lx\n",
724
                     (long)ea, (long)ra));
725
    return ra;
726
  }
727
 
728
  /* match with BAT? */
729
  bat = om_effective_to_bat(map, ea);
730
  if (bat != NULL) {
731
    if (!om_valid_access[1][bat->protection_bits][access]) {
732
      TRACE(trace_vm, ("ea=0x%lx - bat access violation\n", (long)ea));
733
      if (abort)
734
        om_interrupt(processor, cia, ea, access,
735
                     protection_violation_storage_interrupt);
736
      else
737
        return MASK(0, 63);
738
    }
739
 
740
    ra = ((ea & bat->block_length_mask) | bat->block_real_page_number);
741
    TRACE(trace_vm, ("ea=0x%lx - bat translation - ra=0x%lx\n",
742
                     (long)ea, (long)ra));
743
    return ra;
744
  }
745
 
746
  /* translate ea to va using segment map */
747
  segment_tlb_entry = om_effective_to_virtual(map, ea, processor, cia);
748
#if (WITH_TARGET_WORD_BITSIZE == 64)
749
  if (segment_tlb_entry == NULL) {
750
    TRACE(trace_vm, ("ea=0x%lx - segment tlb miss\n", (long)ea));
751
    if (abort)
752
      om_interrupt(processor, cia, ea, access,
753
                   segment_table_miss_storage_interrupt);
754
    else
755
      return MASK(0, 63);
756
  }
757
#endif
758
  /* check for invalid segment access type */
759
  if (segment_tlb_entry->invalid_access == access) {
760
    TRACE(trace_vm, ("ea=0x%lx - segment access invalid\n", (long)ea));
761
    if (abort)
762
      om_interrupt(processor, cia, ea, access,
763
                   protection_violation_storage_interrupt);
764
    else
765
      return MASK(0, 63);
766
  }
767
 
768
  /* lookup in PTE */
769
  page_tlb_entry = om_virtual_to_real(map, ea, segment_tlb_entry,
770
                                      access,
771
                                      processor, cia);
772
  if (page_tlb_entry == NULL) {
773
    TRACE(trace_vm, ("ea=0x%lx - page tlb miss\n", (long)ea));
774
    if (abort)
775
      om_interrupt(processor, cia, ea, access,
776
                   hash_table_miss_storage_interrupt);
777
    else
778
      return MASK(0, 63);
779
  }
780
  if (!(om_valid_access
781
        [segment_tlb_entry->key[map->is_problem_state]]
782
        [page_tlb_entry->protection]
783
        [access])) {
784
    TRACE(trace_vm, ("ea=0x%lx - page tlb access violation\n", (long)ea));
785
    if (abort)
786
      om_interrupt(processor, cia, ea, access,
787
                   protection_violation_storage_interrupt);
788
    else
789
      return MASK(0, 63);
790
  }
791
 
792
  /* update change bit as needed */
793
  if (access == om_data_write &&!page_tlb_entry->changed) {
794
    unsigned_word pte_1 = om_read_word(map,
795
                                       page_tlb_entry->real_address_of_pte_1,
796
                                       processor, cia);
797
    om_write_word(map,
798
                  page_tlb_entry->real_address_of_pte_1,
799
                  pte_1 | BIT(56),
800
                  processor, cia);
801
    TRACE(trace_vm, ("ea=0x%lx - set change bit - tlb=0x%lx &pte1=0x%lx\n",
802
                     (long)ea, (long)page_tlb_entry,
803
                     (long)page_tlb_entry->real_address_of_pte_1));
804
  }
805
 
806
  ra = (page_tlb_entry->masked_real_page_number | om_ea_masked_byte(ea));
807
  TRACE(trace_vm, ("ea=0x%lx - page translation - ra=0x%lx\n",
808
                   (long)ea, (long)ra));
809
  return ra;
810
}
811
 
812
 
813
/*
814
 * Definition of operations for memory management
815
 */
816
 
817
 
818
/* rebuild all the relevant bat information */
819
STATIC_INLINE_VM\
820
(void)
821
om_unpack_bat(om_bat *bat,
822
              spreg ubat,
823
              spreg lbat)
824
{
825
  /* for extracting out the offset within a page */
826
  bat->block_length_mask = ((MASKED(ubat, 51, 61) << (17-2))
827
                            | MASK(63-17+1, 63));
828
 
829
  /* for checking the effective page index */
830
  bat->block_effective_page_index = MASKED(ubat, 0, 46);
831
  bat->block_effective_page_index_mask = ~bat->block_length_mask;
832
 
833
  /* protection information */
834
  bat->protection_bits = EXTRACTED(lbat, 62, 63);
835
  bat->block_real_page_number = MASKED(lbat, 0, 46);
836
}
837
 
838
 
839
/* rebuild the given bat table */
840
STATIC_INLINE_VM\
841
(void)
842
om_unpack_bats(om_bats *bats,
843
               spreg *raw_bats,
844
               msreg msr)
845
{
846
  int i;
847
  bats->nr_valid_bat_registers = 0;
848
  for (i = 0; i < nr_om_bat_registers*2; i += 2) {
849
    spreg ubat = raw_bats[i];
850
    spreg lbat = raw_bats[i+1];
851
    if ((msr & msr_problem_state)
852
        ? EXTRACTED(ubat, 63, 63)
853
        : EXTRACTED(ubat, 62, 62)) {
854
      om_unpack_bat(&bats->bat[bats->nr_valid_bat_registers],
855
                    ubat, lbat);
856
      bats->nr_valid_bat_registers += 1;
857
    }
858
  }
859
}
860
 
861
 
862
#if (WITH_TARGET_WORD_BITSIZE == 32)
863
STATIC_INLINE_VM\
864
(void)
865
om_unpack_sr(vm *virtual,
866
             sreg *srs,
867
             int which_sr,
868
             cpu *processor,
869
             unsigned_word cia)
870
{
871
  om_segment_tlb_entry *segment_tlb_entry = 0;
872
  sreg new_sr_value = 0;
873
 
874
  /* check register in range */
875
  ASSERT(which_sr >= 0 && which_sr < nr_om_segment_tlb_entries);
876
 
877
  /* get the working values */
878
  segment_tlb_entry = &virtual->segment_tlb.entry[which_sr];
879
  new_sr_value = srs[which_sr];
880
 
881
  /* do we support this */
882
  if (MASKED32(new_sr_value, 0, 0))
883
    cpu_error(processor, cia, "unsupported value of T in segment register %d",
884
              which_sr);
885
 
886
  /* update info */
887
  segment_tlb_entry->key[om_supervisor_state] = EXTRACTED32(new_sr_value, 1, 1);
888
  segment_tlb_entry->key[om_problem_state] = EXTRACTED32(new_sr_value, 2, 2);
889
  segment_tlb_entry->invalid_access = (MASKED32(new_sr_value, 3, 3)
890
                                       ? om_instruction_read
891
                                       : om_access_any);
892
  segment_tlb_entry->masked_virtual_segment_id =
893
    INSERTED32(EXTRACTED32(new_sr_value, 8, 31),
894
               31-6-24+1, 31-6); /* aligned ready for pte group addr */
895
}
896
#endif
897
 
898
 
899
#if (WITH_TARGET_WORD_BITSIZE == 32)
900
STATIC_INLINE_VM\
901
(void)
902
om_unpack_srs(vm *virtual,
903
              sreg *srs,
904
              cpu *processor,
905
              unsigned_word cia)
906
{
907
  int which_sr;
908
  for (which_sr = 0; which_sr < nr_om_segment_tlb_entries; which_sr++) {
909
    om_unpack_sr(virtual, srs, which_sr,
910
                 processor, cia);
911
  }
912
}
913
#endif
914
 
915
 
916
/* Rebuild all the data structures for the new context as specifed by
917
   the passed registers */
918
INLINE_VM\
919
(void)
920
vm_synchronize_context(vm *virtual,
921
                       spreg *sprs,
922
                       sreg *srs,
923
                       msreg msr,
924
                       /**/
925
                       cpu *processor,
926
                       unsigned_word cia)
927
{
928
 
929
  /* enable/disable translation */
930
  int problem_state = (msr & msr_problem_state) != 0;
931
  int data_relocate = (msr & msr_data_relocate) != 0;
932
  int instruction_relocate = (msr & msr_instruction_relocate) != 0;
933
  int little_endian = (msr & msr_little_endian_mode) != 0;
934
 
935
  unsigned_word page_table_hash_mask;
936
  unsigned_word real_address_of_page_table;
937
 
938
  /* update current processor mode */
939
  virtual->instruction_map.translation.is_relocate = instruction_relocate;
940
  virtual->instruction_map.translation.is_problem_state = problem_state;
941
  virtual->data_map.translation.is_relocate = data_relocate;
942
  virtual->data_map.translation.is_problem_state = problem_state;
943
 
944
  /* update bat registers for the new context */
945
  om_unpack_bats(&virtual->ibats, &sprs[spr_ibat0u], msr);
946
  om_unpack_bats(&virtual->dbats, &sprs[spr_dbat0u], msr);
947
 
948
  /* unpack SDR1 - the storage description register 1 */
949
#if (WITH_TARGET_WORD_BITSIZE == 64)
950
  real_address_of_page_table = MASKED64(sprs[spr_sdr1], 0, 45);
951
  page_table_hash_mask = MASK64(18+28-EXTRACTED64(sprs[spr_sdr1], 59, 63),
952
                                63-7);
953
#endif
954
#if (WITH_TARGET_WORD_BITSIZE == 32)
955
  real_address_of_page_table = MASKED32(sprs[spr_sdr1], 0, 15);
956
  page_table_hash_mask = (INSERTED32(EXTRACTED32(sprs[spr_sdr1], 23, 31),
957
                                     7, 7+9-1)
958
                          | MASK32(7+9, 31-6));
959
#endif
960
  virtual->instruction_map.translation.real_address_of_page_table = real_address_of_page_table;
961
  virtual->instruction_map.translation.page_table_hash_mask = page_table_hash_mask;
962
  virtual->data_map.translation.real_address_of_page_table = real_address_of_page_table;
963
  virtual->data_map.translation.page_table_hash_mask = page_table_hash_mask;
964
 
965
 
966
  /* unpack the segment tlb registers */
967
#if (WITH_TARGET_WORD_BITSIZE == 32)
968
  om_unpack_srs(virtual, srs,
969
                processor, cia);
970
#endif
971
 
972
  /* set up the XOR registers if the current endian mode conflicts
973
     with what is in the MSR */
974
  if (WITH_XOR_ENDIAN) {
975
    int i = 1;
976
    unsigned mask;
977
    if ((little_endian && CURRENT_TARGET_BYTE_ORDER == LITTLE_ENDIAN)
978
        || (!little_endian && CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN))
979
      mask = 0;
980
    else
981
      mask = WITH_XOR_ENDIAN - 1;
982
    while (i - 1 < WITH_XOR_ENDIAN) {
983
      virtual->instruction_map.translation.xor[i-1] = mask;
984
      virtual->data_map.translation.xor[i-1] =  mask;
985
      mask = (mask << 1) & (WITH_XOR_ENDIAN - 1);
986
      i = i * 2;
987
    }
988
  }
989
  else {
990
    /* don't allow the processor to change endian modes */
991
    if ((little_endian && CURRENT_TARGET_BYTE_ORDER != LITTLE_ENDIAN)
992
        || (!little_endian && CURRENT_TARGET_BYTE_ORDER != BIG_ENDIAN))
993
      cpu_error(processor, cia, "attempt to change hardwired byte order");
994
  }
995
}
996
 
997
/* update vm data structures due to a TLB operation */
998
 
999
INLINE_VM\
1000
(void)
1001
vm_page_tlb_invalidate_entry(vm *memory,
1002
                             unsigned_word ea)
1003
{
1004
  int i = om_page_tlb_index(ea);
1005
  memory->instruction_tlb.entry[i].masked_virtual_segment_id = MASK(0, 63);
1006
  memory->data_tlb.entry[i].masked_virtual_segment_id = MASK(0, 63);
1007
  TRACE(trace_vm, ("ea=0x%lx - tlb invalidate entry\n", (long)ea));
1008
}
1009
 
1010
INLINE_VM\
1011
(void)
1012
vm_page_tlb_invalidate_all(vm *memory)
1013
{
1014
  int i;
1015
  for (i = 0; i < nr_om_page_tlb_entries; i++) {
1016
    memory->instruction_tlb.entry[i].masked_virtual_segment_id = MASK(0, 63);
1017
    memory->data_tlb.entry[i].masked_virtual_segment_id = MASK(0, 63);
1018
  }
1019
  TRACE(trace_vm, ("tlb invalidate all\n"));
1020
}
1021
 
1022
 
1023
 
1024
INLINE_VM\
1025
(vm_data_map *)
1026
vm_create_data_map(vm *memory)
1027
{
1028
  return &memory->data_map;
1029
}
1030
 
1031
 
1032
INLINE_VM\
1033
(vm_instruction_map *)
1034
vm_create_instruction_map(vm *memory)
1035
{
1036
  return &memory->instruction_map;
1037
}
1038
 
1039
 
1040
STATIC_INLINE_VM\
1041
(unsigned_word)
1042
vm_translate(om_map *map,
1043
             unsigned_word ea,
1044
             om_access_types access,
1045
             cpu *processor,
1046
             unsigned_word cia,
1047
             int abort)
1048
{
1049
  switch (CURRENT_ENVIRONMENT) {
1050
  case USER_ENVIRONMENT:
1051
  case VIRTUAL_ENVIRONMENT:
1052
    return ea;
1053
  case OPERATING_ENVIRONMENT:
1054
    return om_translate_effective_to_real(map, ea, access,
1055
                                          processor, cia,
1056
                                          abort);
1057
  default:
1058
    error("internal error - vm_translate - bad switch");
1059
    return 0;
1060
  }
1061
}
1062
 
1063
 
1064
INLINE_VM\
1065
(unsigned_word)
1066
vm_real_data_addr(vm_data_map *map,
1067
                  unsigned_word ea,
1068
                  int is_read,
1069
                  cpu *processor,
1070
                  unsigned_word cia)
1071
{
1072
  return vm_translate(&map->translation,
1073
                      ea,
1074
                      is_read ? om_data_read : om_data_write,
1075
                      processor,
1076
                      cia,
1077
                      1); /*abort*/
1078
}
1079
 
1080
 
1081
INLINE_VM\
1082
(unsigned_word)
1083
vm_real_instruction_addr(vm_instruction_map *map,
1084
                         cpu *processor,
1085
                         unsigned_word cia)
1086
{
1087
  return vm_translate(&map->translation,
1088
                      cia,
1089
                      om_instruction_read,
1090
                      processor,
1091
                      cia,
1092
                      1); /*abort*/
1093
}
1094
 
1095
INLINE_VM\
1096
(instruction_word)
1097
vm_instruction_map_read(vm_instruction_map *map,
1098
                        cpu *processor,
1099
                        unsigned_word cia)
1100
{
1101
  unsigned_word ra = vm_real_instruction_addr(map, processor, cia);
1102
  ASSERT((cia & 0x3) == 0); /* always aligned */
1103
  if (WITH_XOR_ENDIAN)
1104
    ra ^= map->translation.xor[sizeof(instruction_word) - 1];
1105
  return core_map_read_4(map->code, ra, processor, cia);
1106
}
1107
 
1108
 
1109
INLINE_VM\
1110
(int)
1111
vm_data_map_read_buffer(vm_data_map *map,
1112
                        void *target,
1113
                        unsigned_word addr,
1114
                        unsigned nr_bytes,
1115
                        cpu *processor,
1116
                        unsigned_word cia)
1117
{
1118
  unsigned count;
1119
  for (count = 0; count < nr_bytes; count++) {
1120
    unsigned_1 byte;
1121
    unsigned_word ea = addr + count;
1122
    unsigned_word ra = vm_translate(&map->translation,
1123
                                    ea, om_data_read,
1124
                                    processor, /*processor*/
1125
                                    cia, /*cia*/
1126
                                    processor != NULL); /*abort?*/
1127
    if (ra == MASK(0, 63))
1128
      break;
1129
    if (WITH_XOR_ENDIAN)
1130
      ra ^= map->translation.xor[0];
1131
    if (core_map_read_buffer(map->read, &byte, ra, sizeof(byte))
1132
        != sizeof(byte))
1133
      break;
1134
    ((unsigned_1*)target)[count] = T2H_1(byte);
1135
  }
1136
  return count;
1137
}
1138
 
1139
 
1140
INLINE_VM\
1141
(int)
1142
vm_data_map_write_buffer(vm_data_map *map,
1143
                         const void *source,
1144
                         unsigned_word addr,
1145
                         unsigned nr_bytes,
1146
                         int violate_read_only_section,
1147
                         cpu *processor,
1148
                         unsigned_word cia)
1149
{
1150
  unsigned count;
1151
  unsigned_1 byte;
1152
  for (count = 0; count < nr_bytes; count++) {
1153
    unsigned_word ea = addr + count;
1154
    unsigned_word ra = vm_translate(&map->translation,
1155
                                    ea, om_data_write,
1156
                                    processor,
1157
                                    cia,
1158
                                    processor != NULL); /*abort?*/
1159
    if (ra == MASK(0, 63))
1160
      break;
1161
    if (WITH_XOR_ENDIAN)
1162
      ra ^= map->translation.xor[0];
1163
    byte = T2H_1(((unsigned_1*)source)[count]);
1164
    if (core_map_write_buffer((violate_read_only_section
1165
                               ? map->read
1166
                               : map->write),
1167
                              &byte, ra, sizeof(byte)) != sizeof(byte))
1168
      break;
1169
  }
1170
  return count;
1171
}
1172
 
1173
 
1174
/* define the read/write 1/2/4/8/word functions */
1175
 
1176
#define N 1
1177
#include "vm_n.h"
1178
#undef N
1179
 
1180
#define N 2
1181
#include "vm_n.h"
1182
#undef N
1183
 
1184
#define N 4
1185
#include "vm_n.h"
1186
#undef N
1187
 
1188
#define N 8
1189
#include "vm_n.h"
1190
#undef N
1191
 
1192
#define N word
1193
#include "vm_n.h"
1194
#undef N
1195
 
1196
 
1197
 
1198
#endif /* _VM_C_ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.