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