📄 vm.c
字号:
return EXTRACTED(pte_1, 56, 56);}STATIC_INLINE_VM\(int)om_pte_1_masked_rpn(unsigned_word pte_1){ return MASKED(pte_1, 0, 51); /*RPN*/}STATIC_INLINE_VM\(unsigned_word)om_ea_api(unsigned_word ea){ return EXTRACTED(ea, 36, 41);}/* Page and Segment table read/write operators, these need to still account for the PPC's XOR operation */STATIC_INLINE_VM\(unsigned_word)om_read_word(om_map *map, unsigned_word ra, cpu *processor, unsigned_word cia){ if (WITH_XOR_ENDIAN) ra ^= map->xor[sizeof(instruction_word) - 1]; return core_map_read_word(map->physical, ra, processor, cia);}STATIC_INLINE_VM\(void)om_write_word(om_map *map, unsigned_word ra, unsigned_word val, cpu *processor, unsigned_word cia){ if (WITH_XOR_ENDIAN) ra ^= map->xor[sizeof(instruction_word) - 1]; core_map_write_word(map->physical, ra, val, processor, cia);}/* Bring things into existance */INLINE_VM\(vm *)vm_create(core *physical){ vm *virtual; /* internal checks */ if (nr_om_segment_tlb_entries != (1 << (om_segment_tlb_index_stop_bit - om_segment_tlb_index_start_bit + 1))) error("internal error - vm_create - problem with om_segment constants\n"); if (nr_om_page_tlb_entries != (1 << (om_page_tlb_index_stop_bit - om_page_tlb_index_start_bit + 1))) error("internal error - vm_create - problem with om_page constants\n"); /* create the new vm register file */ virtual = ZALLOC(vm); /* set up core */ virtual->physical = physical; /* set up the address decoders */ virtual->instruction_map.translation.bat_registers = &virtual->ibats; virtual->instruction_map.translation.segment_tlb = &virtual->segment_tlb; virtual->instruction_map.translation.page_tlb = &virtual->instruction_tlb; virtual->instruction_map.translation.is_relocate = 0; virtual->instruction_map.translation.is_problem_state = 0; virtual->instruction_map.translation.physical = core_readable(physical); virtual->instruction_map.code = core_readable(physical); virtual->data_map.translation.bat_registers = &virtual->dbats; virtual->data_map.translation.segment_tlb = &virtual->segment_tlb; virtual->data_map.translation.page_tlb = &virtual->data_tlb; virtual->data_map.translation.is_relocate = 0; virtual->data_map.translation.is_problem_state = 0; virtual->data_map.translation.physical = core_readable(physical); virtual->data_map.read = core_readable(physical); virtual->data_map.write = core_writeable(physical); return virtual;}STATIC_INLINE_VM\(om_bat *)om_effective_to_bat(om_map *map, unsigned_word ea){ int curr_bat = 0; om_bats *bats = map->bat_registers; int nr_bats = bats->nr_valid_bat_registers; for (curr_bat = 0; curr_bat < nr_bats; curr_bat++) { om_bat *bat = bats->bat + curr_bat; if ((ea & bat->block_effective_page_index_mask) != bat->block_effective_page_index) continue; return bat; } return NULL;}STATIC_INLINE_VM\(om_segment_tlb_entry *)om_effective_to_virtual(om_map *map, unsigned_word ea, cpu *processor, unsigned_word cia){ /* first try the segment tlb */ om_segment_tlb_entry *segment_tlb_entry = (map->segment_tlb->entry + om_segment_tlb_index(ea));#if (WITH_TARGET_WORD_BITSIZE == 32) TRACE(trace_vm, ("ea=0x%lx - sr[%ld] - masked-vsid=0x%lx va=0x%lx%07lx\n", (unsigned long)ea, (long)om_segment_tlb_index(ea), (unsigned long)segment_tlb_entry->masked_virtual_segment_id, (unsigned long)EXTRACTED32(segment_tlb_entry->masked_virtual_segment_id, 31-6-24+1, 31-6), (unsigned long)EXTRACTED32(ea, 4, 31))); return segment_tlb_entry;#endif#if (WITH_TARGET_WORD_BITSIZE == 64) if (segment_tlb_entry->is_valid && (segment_tlb_entry->masked_effective_segment_id == MASKED(ea, 0, 35))) { error("fixme - is there a need to update any bits\n"); return segment_tlb_entry; } /* drats, segment tlb missed */ { unsigned_word segment_id_hash = ea; int current_hash = 0; for (current_hash = 0; current_hash < 2; current_hash += 1) { unsigned_word segment_table_entry_group = (map->real_address_of_segment_table | (MASKED64(segment_id_hash, 31, 35) >> (56-35))); unsigned_word segment_table_entry; for (segment_table_entry = segment_table_entry_group; segment_table_entry < (segment_table_entry_group + sizeof_segment_table_entry_group); segment_table_entry += sizeof_segment_table_entry) { /* byte order? */ unsigned_word segment_table_entry_dword_0 = om_read_word(map->physical, segment_table_entry, processor, cia); unsigned_word segment_table_entry_dword_1 = om_read_word(map->physical, segment_table_entry + 8, processor, cia); int is_valid = MASKED64(segment_table_entry_dword_0, 56, 56) != 0; unsigned_word masked_effective_segment_id = MASKED64(segment_table_entry_dword_0, 0, 35); if (is_valid && masked_effective_segment_id == MASKED64(ea, 0, 35)) { /* don't permit some things */ if (MASKED64(segment_table_entry_dword_0, 57, 57)) error("om_effective_to_virtual() - T=1 in STE not supported\n"); /* update segment tlb */ segment_tlb_entry->is_valid = is_valid; segment_tlb_entry->masked_effective_segment_id = masked_effective_segment_id; segment_tlb_entry->key[om_supervisor_state] = EXTRACTED64(segment_table_entry_dword_0, 58, 58); segment_tlb_entry->key[om_problem_state] = EXTRACTED64(segment_table_entry_dword_0, 59, 59); segment_tlb_entry->invalid_access = (MASKED64(segment_table_entry_dword_0, 60, 60) ? om_instruction_read : om_access_any); segment_tlb_entry->masked_virtual_segment_id = INSERTED64(EXTRACTED64(segment_table_entry_dword_1, 0, 51), 18-13, 63-7); /* aligned ready for pte group addr */ return segment_tlb_entry; } } segment_id_hash = ~segment_id_hash; } } return NULL;#endif}STATIC_INLINE_VM\(om_page_tlb_entry *)om_virtual_to_real(om_map *map, unsigned_word ea, om_segment_tlb_entry *segment_tlb_entry, om_access_types access, cpu *processor, unsigned_word cia){ om_page_tlb_entry *page_tlb_entry = (map->page_tlb->entry + om_page_tlb_index(ea)); /* is it a tlb hit? */ if ((page_tlb_entry->masked_virtual_segment_id == segment_tlb_entry->masked_virtual_segment_id) && (page_tlb_entry->masked_page == om_ea_masked_page(ea))) { TRACE(trace_vm, ("ea=0x%lx - tlb hit - tlb=0x%lx\n", (long)ea, (long)page_tlb_entry)); return page_tlb_entry; } /* drats, it is a tlb miss */ { unsigned_word page_hash = om_hash_page(segment_tlb_entry->masked_virtual_segment_id, ea); int current_hash; for (current_hash = 0; current_hash < 2; current_hash += 1) { unsigned_word real_address_of_pte_group = (map->real_address_of_page_table | (page_hash & map->page_table_hash_mask)); unsigned_word real_address_of_pte_0; TRACE(trace_vm, ("ea=0x%lx - htab search %d - htab=0x%lx hash=0x%lx mask=0x%lx pteg=0x%lx\n", (long)ea, current_hash, map->real_address_of_page_table, page_hash, map->page_table_hash_mask, (long)real_address_of_pte_group)); for (real_address_of_pte_0 = real_address_of_pte_group; real_address_of_pte_0 < (real_address_of_pte_group + sizeof_pte_group); real_address_of_pte_0 += sizeof_pte) { unsigned_word pte_0 = om_read_word(map, real_address_of_pte_0, processor, cia); /* did we hit? */ if (om_pte_0_valid(pte_0) && (current_hash == om_pte_0_hash(pte_0)) && (segment_tlb_entry->masked_virtual_segment_id == om_pte_0_masked_vsid(pte_0)) && (om_ea_api(ea) == om_pte_0_api(pte_0))) { unsigned_word real_address_of_pte_1 = (real_address_of_pte_0 + sizeof_pte / 2); unsigned_word pte_1 = om_read_word(map, real_address_of_pte_1, processor, cia); page_tlb_entry->protection = om_pte_1_pp(pte_1); page_tlb_entry->changed = om_pte_1_changed(pte_1); page_tlb_entry->masked_virtual_segment_id = segment_tlb_entry->masked_virtual_segment_id; page_tlb_entry->masked_page = om_ea_masked_page(ea); page_tlb_entry->masked_real_page_number = om_pte_1_masked_rpn(pte_1); page_tlb_entry->real_address_of_pte_1 = real_address_of_pte_1; if (!om_pte_1_referenced(pte_1)) { om_write_word(map, real_address_of_pte_1, pte_1 | BIT(55), processor, cia); TRACE(trace_vm, ("ea=0x%lx - htab hit - set ref - tlb=0x%lx &pte1=0x%lx\n", (long)ea, (long)page_tlb_entry, (long)real_address_of_pte_1)); } else { TRACE(trace_vm, ("ea=0x%lx - htab hit - tlb=0x%lx &pte1=0x%lx\n", (long)ea, (long)page_tlb_entry, (long)real_address_of_pte_1)); } return page_tlb_entry; } } page_hash = ~page_hash; /*???*/ } } return NULL;}STATIC_INLINE_VM\(void)om_interrupt(cpu *processor, unsigned_word cia, unsigned_word ea, om_access_types access, storage_interrupt_reasons reason){ switch (access) { case om_data_read: data_storage_interrupt(processor, cia, ea, reason, 0/*!is_store*/); break; case om_data_write: data_storage_interrupt(processor, cia, ea, reason, 1/*is_store*/); break; case om_instruction_read: instruction_storage_interrupt(processor, cia, reason); break; default: error("internal error - om_interrupt - unexpected access type %d", access); }}STATIC_INLINE_VM\(unsigned_word)om_translate_effective_to_real(om_map *map, unsigned_word ea, om_access_types access, cpu *processor, unsigned_word cia, int abort){ om_bat *bat = NULL; om_segment_tlb_entry *segment_tlb_entry = NULL; om_page_tlb_entry *page_tlb_entry = NULL; unsigned_word ra; if (!map->is_relocate) { ra = ea; TRACE(trace_vm, ("ea=0x%lx - direct map - ra=0x%lx\n", (long)ea, (long)ra)); return ra; } /* match with BAT? */ bat = om_effective_to_bat(map, ea); if (bat != NULL) { if (!om_valid_access[1][bat->protection_bits][access]) { TRACE(trace_vm, ("ea=0x%lx - bat access violation\n", (long)ea)); if (abort) om_interrupt(processor, cia, ea, access, protection_violation_storage_interrupt); else return MASK(0, 63); } ra = ((ea & bat->block_length_mask) | bat->block_real_page_number); TRACE(trace_vm, ("ea=0x%lx - bat translation - ra=0x%lx\n", (long)ea, (long)ra)); return ra; } /* translate ea to va using segment map */ segment_tlb_entry = om_effective_to_virtual(map, ea, processor, cia);#if (WITH_TARGET_WORD_BITSIZE == 64) if (segment_tlb_entry == NULL) { TRACE(trace_vm, ("ea=0x%lx - segment tlb miss\n", (long)ea)); if (abort) om_interrupt(processor, cia, ea, access, segment_table_miss_storage_interrupt); else return MASK(0, 63); }#endif /* check for invalid segment access type */ if (segment_tlb_entry->invalid_access == access) { TRACE(trace_vm, ("ea=0x%lx - segment access invalid\n", (long)ea)); if (abort) om_interrupt(processor, cia, ea, access, protection_violation_storage_interrupt); else return MASK(0, 63); } /* lookup in PTE */ page_tlb_entry = om_virtual_to_real(map, ea, segment_tlb_entry, access, processor, cia); if (page_tlb_entry == NULL) { TRACE(trace_vm, ("ea=0x%lx - page tlb miss\n", (long)ea)); if (abort) om_interrupt(processor, cia, ea, access, hash_table_miss_storage_interrupt); else return MASK(0, 63); } if (!(om_valid_access [segment_tlb_entry->key[map->is_problem_state]] [page_tlb_entry->protection] [access])) { TRACE(trace_vm, ("ea=0x%lx - page tlb access violation\n", (long)ea)); if (abort) om_interrupt(processor, cia, ea, access, protection_violation_storage_interrupt); else return MASK(0, 63); } /* update change bit as needed */ if (access == om_data_write &&!page_tlb_entry->changed) { unsigned_word pte_1 = om_read_word(map, page_tlb_entry->real_address_of_pte_1, processor, cia); om_write_word(map, page_tlb_entry->real_address_of_pte_1, pte_1 | BIT(56), processor, cia);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -