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