--- tme/machine/sun2/sun2-mmu.c 2018/04/24 16:37:52 1.1 +++ tme/machine/sun2/sun2-mmu.c 2018/04/24 16:41:34 1.1.1.4 @@ -1,4 +1,4 @@ -/* $Id: sun2-mmu.c,v 1.1 2018/04/24 16:37:52 root Exp $ */ +/* $Id: sun2-mmu.c,v 1.1.1.4 2018/04/24 16:41:34 root Exp $ */ /* machine/sun2/sun2-mmu.c - implementation of Sun 2 MMU emulation: */ @@ -34,7 +34,7 @@ */ #include -_TME_RCSID("$Id: sun2-mmu.c,v 1.1 2018/04/24 16:37:52 root Exp $"); +_TME_RCSID("$Id: sun2-mmu.c,v 1.1.1.4 2018/04/24 16:41:34 root Exp $"); /* includes: */ #include "sun2-impl.h" @@ -79,6 +79,9 @@ _tme_sun2_bus_fault_log(struct tme_sun2 tme_bus_addr_t physical_address; int rc; + /* this silences gcc -Wuninitialized: */ + bus_name = NULL; + /* recover the virtual address used: */ virtual_address = cycle->tme_bus_cycle_address - tlb->tme_bus_tlb_addr_offset; @@ -289,8 +292,8 @@ _tme_sun2_m68k_tlb_fill(struct tme_m68k_ tme_bus_tlb_initialize(tlb); /* we cover the entire address space: */ - TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0); - TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, -1); + tlb->tme_bus_tlb_addr_first = 0; + tlb->tme_bus_tlb_addr_last = ((tme_bus_addr_t) 0) - 1; /* we allow reading and writing: */ tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; @@ -364,18 +367,62 @@ _tme_sun2_bus_tlb_fill(struct tme_bus_co tme_uint32_t address, unsigned int cycles) { struct tme_sun2 *sun2; + struct tme_sun2_bus_connection *conn_sun2; + tme_uint32_t base, size; + struct tme_bus_tlb tlb_bus; /* recover our sun2: */ sun2 = (struct tme_sun2 *) conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; + /* recover the sun2 internal mainbus connection: */ + conn_sun2 = (struct tme_sun2_bus_connection *) conn_bus; + + /* turn the bus address into a DVMA address: */ + switch (conn_sun2->tme_sun2_bus_connection_which) { + + /* obio devices can actually see the whole address space: */ + case TME_SUN2_BUS_OBIO: + base = 0x000000; + size = 0x1000000; + break; + + case TME_SUN2_BUS_MBMEM: + base = 0xf00000; + size = TME_SUN2_DVMA_SIZE_MBMEM; + break; + + case TME_SUN2_BUS_VME: + base = 0xf00000; + size = TME_SUN2_DVMA_SIZE_VME; + break; + + default: abort(); + } + + assert (!(address & base) + && (address < size)); + /* fill this TLB entry from the MMU: */ tme_sun_mmu_tlb_fill(sun2->tme_sun2_mmu, tlb, sun2->tme_sun2_context_system, - address, + address | base, ((cycles & TME_BUS_CYCLE_WRITE) ? TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW) : TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO))); + + /* create the mapping TLB entry. we do this even if base == 0, + because the TLB entry as currently filled may cover more address + space than DVMA space on this machine is supposed to cover: */ + tlb_bus.tme_bus_tlb_addr_first = 0; + tlb_bus.tme_bus_tlb_addr_last = size - 1; + tlb_bus.tme_bus_tlb_cycles_ok + = (TME_BUS_CYCLE_READ + | TME_BUS_CYCLE_WRITE); + + /* map the filled TLB entry: */ + tme_bus_tlb_map(tlb, address | base, &tlb_bus, address); + return (TME_OK); } @@ -513,6 +560,9 @@ _tme_sun2_mmu_pte_set(struct tme_sun2 *s const char *bus_name; tme_bus_addr_t physical_address; + /* this silences gcc -Wuninitialized: */ + bus_name = NULL; + /* log this setting: */ physical_address = ((pte_sun2 & TME_SUN2_PTE_PGFRAME) << TME_SUN2_PAGE_SIZE_LOG2); switch ((pte_sun2 & TME_SUN2_PTE_PGTYPE) / (TME_SUN2_PTE_PGTYPE / TME_SUN2_PTE_PGTYPE_MASK)) { @@ -625,6 +675,7 @@ _tme_sun2_mmu_pte_set(struct tme_sun2 *s /* with this protection, the system gets a protection error, and the user can read and write: */ case 0x3c000000: + case 0x0c000000: pte_flags |= (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_ERROR) | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW)); @@ -682,7 +733,8 @@ _tme_sun2_mmu_context_user_set(struct tm int _tme_sun2_mmu_tlb_set_allocate(struct tme_bus_connection *conn_bus_asker, unsigned int count, unsigned int sizeof_one, - TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb **) _tlbs) + struct tme_bus_tlb * tme_shared * _tlbs, + tme_rwlock_t *_tlbs_rwlock) { struct tme_sun2 *sun2; int rc; @@ -691,7 +743,7 @@ _tme_sun2_mmu_tlb_set_allocate(struct tm sun2 = (struct tme_sun2 *) conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private; /* get the MMU to allocate the TLB set: */ - rc = tme_sun_mmu_tlb_set_allocate(sun2->tme_sun2_mmu, count, sizeof_one, _tlbs); + rc = tme_sun_mmu_tlb_set_allocate(sun2->tme_sun2_mmu, count, sizeof_one, _tlbs, _tlbs_rwlock); /* if this is the TLB set for our CPU, remember where the context zero TLBs are, and try to reset the MMU now: */ @@ -701,7 +753,7 @@ _tme_sun2_mmu_tlb_set_allocate(struct tm && conn_bus_asker->tme_bus_connection.tme_connection_type == TME_CONNECTION_BUS_M68K && sun2->tme_sun2_reset_tlbs == NULL) { assert(sizeof_one == sizeof(struct tme_m68k_tlb)); - sun2->tme_sun2_reset_tlbs = (struct tme_m68k_tlb *) TME_ATOMIC_READ(struct tme_bus_tlb *, *_tlbs); + sun2->tme_sun2_reset_tlbs = (struct tme_m68k_tlb *) tme_memory_atomic_pointer_read(struct tme_bus_tlb *, *_tlbs, _tlbs_rwlock); sun2->tme_sun2_reset_tlb_count = count; _tme_sun2_mmu_reset(sun2); } @@ -755,7 +807,7 @@ _tme_sun2_reset_cycle(void *_sun2, struc return (rc); } -/* this initialize the context zero part of the CPU's TLB set to +/* this initializes the context zero part of the CPU's TLB set to support four slow 16-bit reads from ROM at addresses 0, 2, 4, 6, respectively. this emulates how the Sun-2 behaves as it comes out of reset: */ @@ -774,7 +826,10 @@ _tme_sun2_mmu_reset(struct tme_sun2 *sun return (TME_OK); } sun2->tme_sun2_reset_tlbs = NULL; + /* XXX FIXME - this is not thread-safe: */ tlb = &tlb_m68k->tme_m68k_tlb_bus_tlb; + tme_bus_tlb_busy(tlb); + tme_bus_tlb_unbusy_fill(tlb); /* fill the TLB entry: */ (*sun2->tme_sun2_obmem->tme_bus_tlb_fill) @@ -784,16 +839,16 @@ _tme_sun2_mmu_reset(struct tme_sun2 *sun TME_BUS_CYCLE_READ); /* map the TLB entry: */ - TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_first, 0); - TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_last, 7); + tlb_virtual.tme_bus_tlb_addr_first = 0; + tlb_virtual.tme_bus_tlb_addr_last = 7; tlb_virtual.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ; tme_bus_tlb_map(tlb, TME_SUN2_PROM_BASE, &tlb_virtual, 0); /* this TLB entry must allow slow reads from exactly the reset range: */ if (!(tlb->tme_bus_tlb_cycles_ok & TME_BUS_CYCLE_READ) - || TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first) != 0 - || TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last) != 7) { + || tlb->tme_bus_tlb_addr_first != 0 + || tlb->tme_bus_tlb_addr_last != 7) { abort(); } @@ -824,13 +879,13 @@ _tme_sun2_mmu_new(struct tme_sun2 *sun2) { struct tme_sun_mmu_info mmu_info; + memset(&mmu_info, 0, sizeof(mmu_info)); mmu_info.tme_sun_mmu_info_element = sun2->tme_sun2_element; mmu_info.tme_sun_mmu_info_address_bits = 24; mmu_info.tme_sun_mmu_info_pgoffset_bits = TME_SUN2_PAGE_SIZE_LOG2; mmu_info.tme_sun_mmu_info_pteindex_bits = 4; mmu_info.tme_sun_mmu_info_contexts = 8; mmu_info.tme_sun_mmu_info_pmegs = 256; - mmu_info.tme_sun_mmu_info_seginv = 255; mmu_info.tme_sun_mmu_info_tlb_fill_private = sun2; mmu_info.tme_sun_mmu_info_tlb_fill = _tme_sun2_tlb_fill_mmu; mmu_info.tme_sun_mmu_info_proterr_private = sun2;