vmem: no more 4GB vmem mode. only map elan RAM in naomi2 mode

Do not attempt to reserve 4GM of virtual space on 64-bit hosts. Use
512MB everywhere.
Don't map elan RAM if not needed and dont protect/unprotect it in
memwatch.
This commit is contained in:
Flyinghead 2022-12-09 17:37:49 +01:00
parent 9069a49145
commit 32e3e7d9c5
13 changed files with 99 additions and 404 deletions

View File

@ -373,6 +373,7 @@ static void setPlatform(int platform)
{
if (VRAM_SIZE != 0)
_vmem_unprotect_vram(0, VRAM_SIZE);
elan::ERAM_SIZE = 0;
switch (platform)
{
case DC_PLATFORM_DREAMCAST:
@ -395,6 +396,7 @@ static void setPlatform(int platform)
settings.platform.aram_size = 8 * 1024 * 1024;
settings.platform.bios_size = 2 * 1024 * 1024;
settings.platform.flash_size = 32 * 1024; // battery-backed ram
elan::ERAM_SIZE = 32 * 1024 * 1024;
break;
case DC_PLATFORM_ATOMISWAVE:
settings.platform.ram_size = 16 * 1024 * 1024;

View File

@ -361,8 +361,7 @@ void _vmem_term()
}
u8* virt_ram_base;
bool vmem_4gb_space;
static VMemType vmemstatus = MemTypeError;
static bool vmemAvailable = false;
static void *malloc_pages(size_t size)
{
@ -410,45 +409,24 @@ bool BM_LockedWrite(u8* address) {
}
#endif
static void _vmem_set_p0_mappings()
{
const vmem_mapping mem_mappings[] = {
// P0/U0
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
{0x01000000, 0x02800000, 0, 0, false}, // unused
{0x02800000, 0x03000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
{0x03000000, 0x04000000, 0, 0, false}, // unused
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0x10000000, 0x80000000, 0, 0, false}, // Area 4-7 (unused)
};
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
}
bool _vmem_reserve()
{
static_assert((sizeof(Sh4RCB) % PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of PAGE_SIZE");
if (vmemstatus != MemTypeError)
if (vmemAvailable)
return true;
// Use vmem only if settings mandate so, and if we have proper exception handlers.
#if !defined(TARGET_NO_EXCEPTIONS)
if (!settings.dynarec.disable_nvmem)
vmemstatus = vmem_platform_init((void**)&virt_ram_base, (void**)&p_sh4rcb, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + elan::ELAN_RAM_SIZE);
vmemAvailable = vmem_platform_init((void**)&virt_ram_base, (void**)&p_sh4rcb, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + elan::ERAM_SIZE_MAX);
#endif
return true;
}
static void _vmem_term_mappings()
{
if (vmemstatus == MemTypeError)
if (!vmemAvailable)
{
free_pages(p_sh4rcb);
p_sh4rcb = nullptr;
@ -467,7 +445,7 @@ void _vmem_init_mappings()
{
_vmem_term_mappings();
// Fallback to statically allocated buffers, this results in slow-ops being generated.
if (vmemstatus == MemTypeError)
if (!vmemAvailable)
{
WARN_LOG(VMEM, "Warning! nvmem is DISABLED (due to failure or not being built-in");
virt_ram_base = nullptr;
@ -488,94 +466,34 @@ void _vmem_init_mappings()
aica_ram.size = ARAM_SIZE;
aica_ram.data = (u8*)malloc_pages(ARAM_SIZE);
elan::RAM = (u8*)malloc_pages(elan::ELAN_RAM_SIZE);
elan::RAM = (u8*)malloc_pages(elan::ERAM_SIZE);
}
else {
NOTICE_LOG(VMEM, "Info: nvmem is enabled, with addr space of size %s", vmemstatus == MemType4GB ? "4GB" : "512MB");
NOTICE_LOG(VMEM, "Info: nvmem is enabled");
INFO_LOG(VMEM, "Info: p_sh4rcb: %p virt_ram_base: %p", p_sh4rcb, virt_ram_base);
// Map the different parts of the memory file into the new memory range we got.
if (vmemstatus == MemType512MB)
{
const vmem_mapping mem_mappings[] = {
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, false}, // Aica
{0x01000000, 0x04000000, 0, 0, false}, // More unused
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0x10000000, 0x20000000, 0, 0, false}, // Area 4-7 (unused)
// This is outside of the 512MB addr space. We map 8MB in all cases to help some games read past the end of aica ram
{0x20000000, 0x20800000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // writable aica ram
};
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
const vmem_mapping mem_mappings[] = {
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, false}, // Aica
{0x01000000, 0x04000000, 0, 0, false}, // More unused
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ERAM_SIZE, true}, // Area 2 (Elan RAM)
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0x10000000, 0x20000000, 0, 0, false}, // Area 4-7 (unused)
// This is outside of the 512MB addr space. We map 8MB in all cases to help some games read past the end of aica ram
{0x20000000, 0x20800000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // writable aica ram
};
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
// Point buffers to actual data pointers
aica_ram.data = &virt_ram_base[0x20000000]; // Points to the writable AICA addrspace
vram.data = &virt_ram_base[0x04000000]; // Points to first vram mirror (writable and lockable)
mem_b.data = &virt_ram_base[0x0C000000]; // Main memory, first mirror
elan::RAM = &virt_ram_base[0x0A000000];
}
else
{
_vmem_set_p0_mappings();
const vmem_mapping mem_mappings[] = {
// P1
{0x80000000, 0x80800000, 0, 0, false}, // Area 0 -> unused
{0x80800000, 0x81000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
{0x81000000, 0x82800000, 0, 0, false}, // unused
{0x82800000, 0x83000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
{0x83000000, 0x84000000, 0, 0, false}, // unused
{0x84000000, 0x85000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0x85000000, 0x86000000, 0, 0, false}, // 32 bit path (unused)
{0x86000000, 0x87000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0x87000000, 0x88000000, 0, 0, false}, // 32 bit path (unused) mirror
{0x88000000, 0x8A000000, 0, 0, false}, // Area 2
{0x8A000000, 0x8C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
{0x8C000000, 0x90000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0x90000000, 0xA0000000, 0, 0, false}, // Area 4-7 (unused)
// P2
{0xA0000000, 0xA0800000, 0, 0, false}, // Area 0 -> unused
{0xA0800000, 0xA1000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
{0xA1000000, 0xA2800000, 0, 0, false}, // unused
{0xA2800000, 0xA3000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
{0xA3000000, 0xA4000000, 0, 0, false}, // unused
{0xA4000000, 0xA5000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0xA5000000, 0xA6000000, 0, 0, false}, // 32 bit path (unused)
{0xA6000000, 0xA7000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0xA7000000, 0xA8000000, 0, 0, false}, // 32 bit path (unused) mirror
{0xA8000000, 0xAA000000, 0, 0, false}, // Area 2
{0xAA000000, 0xAC000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
{0xAC000000, 0xB0000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0xB0000000, 0xC0000000, 0, 0, false}, // Area 4-7 (unused)
// P3
{0xC0000000, 0xC0800000, 0, 0, false}, // Area 0 -> unused
{0xC0800000, 0xC1000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
{0xC1000000, 0xC2800000, 0, 0, false}, // unused
{0xC2800000, 0xC3000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
{0xC3000000, 0xC4000000, 0, 0, false}, // unused
{0xC4000000, 0xC5000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
{0xC5000000, 0xC6000000, 0, 0, false}, // 32 bit path (unused)
{0xC6000000, 0xC7000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
{0xC7000000, 0xC8000000, 0, 0, false}, // 32 bit path (unused) mirror
{0xC8000000, 0xCA000000, 0, 0, false}, // Area 2
{0xCA000000, 0xCC000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
{0xCC000000, 0xD0000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
{0xD0000000, 0x100000000L, 0, 0, false}, // Area 4-7 (unused)
};
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
// Point buffers to actual data pointers
aica_ram.data = &virt_ram_base[0x80800000]; // Points to the first AICA addrspace in P1
vram.data = &virt_ram_base[0x84000000]; // Points to first vram mirror (writable and lockable) in P1
mem_b.data = &virt_ram_base[0x8C000000]; // Main memory, first mirror in P1
elan::RAM = &virt_ram_base[0x8A000000];
vmem_4gb_space = true;
}
// Point buffers to actual data pointers
aica_ram.data = &virt_ram_base[0x20000000]; // Points to the writable AICA addrspace
vram.data = &virt_ram_base[0x04000000]; // Points to first vram mirror (writable and lockable)
mem_b.data = &virt_ram_base[0x0C000000]; // Main memory, first mirror
elan::RAM = &virt_ram_base[0x0A000000];
aica_ram.size = ARAM_SIZE;
vram.size = VRAM_SIZE;
@ -605,7 +523,7 @@ void _vmem_release()
_vmem_unprotect_vram(0, VRAM_SIZE);
_vmem_term_mappings();
}
vmemstatus = MemTypeError;
vmemAvailable = false;
}
void _vmem_protect_vram(u32 addr, u32 size)
@ -621,25 +539,6 @@ void _vmem_protect_vram(u32 addr, u32 size)
mem_region_lock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
//mem_region_lock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
}
if (_nvmem_4gb_space())
{
mem_region_lock(virt_ram_base + 0x84000000 + addr, size); // P1
//mem_region_lock(virt_ram_base + 0x86000000 + addr, size); // P1 - mirror
mem_region_lock(virt_ram_base + 0xA4000000 + addr, size); // P2
//mem_region_lock(virt_ram_base + 0xA6000000 + addr, size); // P2 - mirror
// We should also lock P3 and its mirrors, but it doesn't seem to be used...
//mem_region_lock(virt_ram_base + 0xC4000000 + addr, size); // P3
//mem_region_lock(virt_ram_base + 0xC6000000 + addr, size); // P3 - mirror
if (VRAM_SIZE == 0x800000)
{
mem_region_lock(virt_ram_base + 0x84000000 + addr + VRAM_SIZE, size); // P1 wrap
//mem_region_lock(virt_ram_base + 0x86000000 + addr + VRAM_SIZE, size); // P1 - mirror wrap
mem_region_lock(virt_ram_base + 0xA4000000 + addr + VRAM_SIZE, size); // P2 wrap
//mem_region_lock(virt_ram_base + 0xA6000000 + addr + VRAM_SIZE, size); // P2 - mirror wrap
//mem_region_lock(virt_ram_base + 0xC4000000 + addr + VRAM_SIZE, size); // P3 wrap
//mem_region_lock(virt_ram_base + 0xC6000000 + addr + VRAM_SIZE, size); // P3 - mirror wrap
}
}
}
else
{
@ -660,25 +559,6 @@ void _vmem_unprotect_vram(u32 addr, u32 size)
mem_region_unlock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
//mem_region_unlock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
}
if (_nvmem_4gb_space())
{
mem_region_unlock(virt_ram_base + 0x84000000 + addr, size); // P1
//mem_region_unlock(virt_ram_base + 0x86000000 + addr, size); // P1 - mirror
mem_region_unlock(virt_ram_base + 0xA4000000 + addr, size); // P2
//mem_region_unlock(virt_ram_base + 0xA6000000 + addr, size); // P2 - mirror
// We should also lock P3 and its mirrors, but it doesn't seem to be used...
//mem_region_unlock(virt_ram_base + 0xC4000000 + addr, size); // P3
//mem_region_unlock(virt_ram_base + 0xC6000000 + addr, size); // P3 - mirror
if (VRAM_SIZE == 0x800000)
{
mem_region_unlock(virt_ram_base + 0x84000000 + addr + VRAM_SIZE, size); // P1 wrap
//mem_region_unlock(virt_ram_base + 0x86000000 + addr + VRAM_SIZE, size); // P1 - mirror wrap
mem_region_unlock(virt_ram_base + 0xA4000000 + addr + VRAM_SIZE, size); // P2 wrap
//mem_region_unlock(virt_ram_base + 0xA6000000 + addr + VRAM_SIZE, size); // P2 - mirror wrap
//mem_region_unlock(virt_ram_base + 0xC4000000 + addr + VRAM_SIZE, size); // P3 wrap
//mem_region_unlock(virt_ram_base + 0xC6000000 + addr + VRAM_SIZE, size); // P3 - mirror wrap
}
}
}
else
{
@ -691,21 +571,9 @@ u32 _vmem_get_vram_offset(void *addr)
if (_nvmem_enabled())
{
ptrdiff_t offset = (u8*)addr - virt_ram_base;
if (_nvmem_4gb_space())
{
if (offset < 0 || offset >= 0xE0000000)
return -1;
offset &= 0x1FFFFFFF;
}
else
{
if (offset < 0 || offset >= 0x20000000)
return -1;
}
if ((offset >> 24) != 4)
if (offset < 0 || offset >= 0x20000000)
return -1;
if ((((u8*)addr - virt_ram_base) >> 29) != 0 && (((u8*)addr - virt_ram_base) >> 29) != 4 && (((u8*)addr - virt_ram_base) >> 29) != 5)
// other areas aren't mapped atm
if ((offset >> 24) != 4)
return -1;
return offset & VRAM_MASK;

View File

@ -1,12 +1,6 @@
#pragma once
#include "types.h"
enum VMemType {
MemType4GB,
MemType512MB,
MemTypeError
};
struct vmem_mapping {
u64 start_address, end_address;
u64 memoffset, memsize;
@ -15,7 +9,7 @@ struct vmem_mapping {
// Platform specific vmemory API
// To initialize (maybe) the vmem subsystem
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize);
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize);
// To reset the on-demand allocated pages.
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes);
// To handle a fault&allocate an ondemand page.
@ -36,7 +30,7 @@ void vmem_platform_flush_cache(void *icache_start, void *icache_end, void *dcach
void vmem_platform_jit_set_exec(void* code, size_t size, bool enable);
// Note: if you want to disable vmem magic in any given platform, implement the
// above functions as empty functions and make vmem_platform_init return MemTypeError.
// above functions as empty functions and make vmem_platform_init return false.
//Typedef's
//ReadMem
@ -99,14 +93,10 @@ void* _vmem_read_const(u32 addr,bool& ismem,u32 sz);
void* _vmem_write_const(u32 addr,bool& ismem,u32 sz);
extern u8* virt_ram_base;
extern bool vmem_4gb_space;
static inline bool _nvmem_enabled() {
return virt_ram_base != 0;
}
static inline bool _nvmem_4gb_space() {
return vmem_4gb_space;
}
void _vmem_bm_reset();
void _vmem_protect_vram(u32 addr, u32 size);

View File

@ -29,98 +29,30 @@ ElanRamWatcher elanWatcher;
void AicaRamWatcher::protectMem(u32 addr, u32 size)
{
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
if (_nvmem_enabled() && _nvmem_4gb_space()) {
mem_region_lock(virt_ram_base + 0x00800000 + addr, size); // P0
mem_region_lock(virt_ram_base + 0x02800000 + addr, size);// P0 - mirror
mem_region_lock(virt_ram_base + 0x80800000 + addr, size); // P1
//mem_region_lock(virt_ram_base + 0x82800000 + addr, size); // P1 - mirror
mem_region_lock(virt_ram_base + 0xA0800000 + addr, size); // P2
//mem_region_lock(virt_ram_base + 0xA2800000 + addr, size); // P2 - mirror
if (ARAM_SIZE == 2 * 1024 * 1024) {
mem_region_lock(virt_ram_base + 0x00A00000 + addr, size); // P0
mem_region_lock(virt_ram_base + 0x00C00000 + addr, size); // P0
mem_region_lock(virt_ram_base + 0x00E00000 + addr, size); // P0
mem_region_lock(virt_ram_base + 0x02A00000 + addr, size);// P0 - mirror
mem_region_lock(virt_ram_base + 0x02C00000 + addr, size);// P0 - mirror
mem_region_lock(virt_ram_base + 0x02E00000 + addr, size);// P0 - mirror
mem_region_lock(virt_ram_base + 0x80A00000 + addr, size); // P1
mem_region_lock(virt_ram_base + 0x80C00000 + addr, size); // P1
mem_region_lock(virt_ram_base + 0x80E00000 + addr, size); // P1
mem_region_lock(virt_ram_base + 0xA0A00000 + addr, size); // P2
mem_region_lock(virt_ram_base + 0xA0C00000 + addr, size); // P2
mem_region_lock(virt_ram_base + 0xA0E00000 + addr, size); // P2
}
} else {
mem_region_lock(aica_ram.data + addr,
std::min(aica_ram.size - addr, size));
}
mem_region_lock(aica_ram.data + addr,
std::min(aica_ram.size - addr, size));
}
void AicaRamWatcher::unprotectMem(u32 addr, u32 size)
{
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
if (_nvmem_enabled() && _nvmem_4gb_space()) {
mem_region_unlock(virt_ram_base + 0x00800000 + addr, size); // P0
mem_region_unlock(virt_ram_base + 0x02800000 + addr, size); // P0 - mirror
mem_region_unlock(virt_ram_base + 0x80800000 + addr, size); // P1
//mem_region_unlock(virt_ram_base + 0x82800000 + addr, size); // P1 - mirror
mem_region_unlock(virt_ram_base + 0xA0800000 + addr, size); // P2
//mem_region_unlock(virt_ram_base + 0xA2800000 + addr, size); // P2 - mirror
if (ARAM_SIZE == 2 * 1024 * 1024) {
mem_region_unlock(virt_ram_base + 0x00A00000 + addr, size); // P0
mem_region_unlock(virt_ram_base + 0x00C00000 + addr, size); // P0
mem_region_unlock(virt_ram_base + 0x00E00000 + addr, size); // P0
mem_region_unlock(virt_ram_base + 0x02A00000 + addr, size); // P0 - mirror
mem_region_unlock(virt_ram_base + 0x02C00000 + addr, size); // P0 - mirror
mem_region_unlock(virt_ram_base + 0x02E00000 + addr, size); // P0 - mirror
mem_region_unlock(virt_ram_base + 0x80A00000 + addr, size); // P1
mem_region_unlock(virt_ram_base + 0x80C00000 + addr, size); // P1
mem_region_unlock(virt_ram_base + 0x80E00000 + addr, size); // P1
mem_region_unlock(virt_ram_base + 0xA0A00000 + addr, size); // P2
mem_region_unlock(virt_ram_base + 0xA0C00000 + addr, size); // P2
mem_region_unlock(virt_ram_base + 0xA0E00000 + addr, size); // P2
}
} else {
mem_region_unlock(aica_ram.data + addr,
std::min(aica_ram.size - addr, size));
}
mem_region_unlock(aica_ram.data + addr,
std::min(aica_ram.size - addr, size));
}
u32 AicaRamWatcher::getMemOffset(void *p)
{
u32 addr;
if (_nvmem_enabled() && _nvmem_4gb_space()) {
if ((u8*) p < virt_ram_base || (u8*) p >= virt_ram_base + 0x100000000L)
return -1;
addr = (u32) ((u8*) p - virt_ram_base);
u32 area = (addr >> 29) & 7;
if (area != 0 && area != 4 && area != 5)
return -1;
addr &= 0x1fffffff & ~0x02000000;
if (addr < 0x00800000 || addr >= 0x01000000)
return -1;
addr &= ARAM_MASK;
} else {
if ((u8*) p < &aica_ram[0] || (u8*) p >= &aica_ram[ARAM_SIZE])
return -1;
addr = (u32) ((u8*) p - &aica_ram[0]);
}
return addr;
if ((u8 *)p < &aica_ram[0] || (u8 *)p >= &aica_ram[ARAM_SIZE])
return -1;
return (u32)((u8 *)p - &aica_ram[0]);
}
void ElanRamWatcher::protectMem(u32 addr, u32 size)
{
using namespace elan;
size = std::min(ELAN_RAM_SIZE - addr, size) & ~PAGE_MASK;
if (_nvmem_enabled())
if (ERAM_SIZE != 0)
{
mem_region_lock(virt_ram_base + 0x0a000000 + addr, size); // P0
if (_nvmem_4gb_space())
{
mem_region_lock(virt_ram_base + 0x8a000000 + addr, size); // P1
mem_region_lock(virt_ram_base + 0xaa000000 + addr, size); // P2
}
} else {
size = std::min(ERAM_SIZE - addr, size) & ~PAGE_MASK;
mem_region_lock(RAM + addr, size);
}
}
@ -128,16 +60,9 @@ void ElanRamWatcher::protectMem(u32 addr, u32 size)
void ElanRamWatcher::unprotectMem(u32 addr, u32 size)
{
using namespace elan;
size = std::min(ELAN_RAM_SIZE - addr, size) & ~PAGE_MASK;
if (_nvmem_enabled())
if (ERAM_SIZE != 0)
{
mem_region_unlock(virt_ram_base + 0x0a000000 + addr, size); // P0
if (_nvmem_4gb_space())
{
mem_region_unlock(virt_ram_base + 0x8a000000 + addr, size); // P1
mem_region_unlock(virt_ram_base + 0xaa000000 + addr, size); // P2
}
} else {
size = std::min(ERAM_SIZE - addr, size) & ~PAGE_MASK;
mem_region_unlock(RAM + addr, size);
}
}
@ -145,25 +70,9 @@ void ElanRamWatcher::unprotectMem(u32 addr, u32 size)
u32 ElanRamWatcher::getMemOffset(void *p)
{
using namespace elan;
u32 addr;
if (_nvmem_enabled())
{
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x100000000L)
return -1;
addr = (u32)((u8 *)p - virt_ram_base);
u32 area = (addr >> 29) & 7;
if (area != 0 && area != 4 && area != 5) // P0, P1 or P2 only
return -1;
addr &= 0x1fffffff;
if (addr < 0x0a000000 || addr >= 0x0a000000 + ELAN_RAM_SIZE)
return -1;
addr &= ELAN_RAM_MASK;
} else {
if ((u8 *)p < RAM || (u8 *)p >= &RAM[ELAN_RAM_SIZE])
return -1;
addr = (u32)((u8 *)p - RAM);
}
return addr;
if ((u8 *)p < RAM || (u8 *)p >= &RAM[ERAM_SIZE])
return -1;
return (u32)((u8 *)p - RAM);
}
}

View File

@ -69,11 +69,14 @@
namespace elan {
constexpr u32 ELAN_RAM_MASK = ERAM_SIZE_MAX - 1;
static _vmem_handler elanRegHandler;
static _vmem_handler elanCmdHandler;
static _vmem_handler elanRamHandler;
u8 *RAM;
u32 ERAM_SIZE;
static u32 reg10;
static u32 reg74;
@ -478,7 +481,7 @@ struct State
static u32 elanRamAddress(void *p)
{
if ((u8 *)p < RAM || (u8 *)p >= RAM + ELAN_RAM_SIZE)
if ((u8 *)p < RAM || (u8 *)p >= RAM + ERAM_SIZE)
return Null;
else
return (u32)((u8 *)p - RAM);
@ -1441,7 +1444,7 @@ template<bool Active = true>
static void executeCommand(u8 *data, int size)
{
// verify(size >= 0);
// verify(size < (int)ELAN_RAM_SIZE);
// verify(size < (int)ERAM_SIZE);
// if (0x2b00 == (u32)(data - RAM))
// for (int i = 0; i < size; i += 4)
// DEBUG_LOG(PVR, "Elan Parse %08x: %08x", (u32)(&data[i] - RAM), *(u32 *)&data[i]);
@ -1748,7 +1751,7 @@ void reset(bool hard)
{
if (hard)
{
memset(RAM, 0, ELAN_RAM_SIZE);
memset(RAM, 0, ERAM_SIZE);
state.reset();
}
}
@ -1780,7 +1783,7 @@ void serialize(Serializer& ser)
ser << reg74;
ser << elanCmd;
if (!ser.rollback())
ser.serialize(RAM, ELAN_RAM_SIZE);
ser.serialize(RAM, ERAM_SIZE);
state.serialize(ser);
}
@ -1792,7 +1795,7 @@ void deserialize(Deserializer& deser)
deser >> reg74;
deser >> elanCmd;
if (!deser.rollback())
deser.deserialize(RAM, ELAN_RAM_SIZE);
deser.deserialize(RAM, ERAM_SIZE);
state.deserialize(deser);
}

View File

@ -32,6 +32,6 @@ void serialize(Serializer& ser);
void deserialize(Deserializer& deser);
extern u8 *RAM;
constexpr u32 ELAN_RAM_SIZE = 32 * 1024 * 1024;
constexpr u32 ELAN_RAM_MASK = ELAN_RAM_SIZE - 1;
extern u32 ERAM_SIZE;
constexpr u32 ERAM_SIZE_MAX = 32 * 1024 * 1024;
}

View File

@ -235,7 +235,6 @@ void bm_Reset()
{
// Windows cannot lock/unlock a region spanning more than one VirtualAlloc or MapViewOfFile
// so we have to unlock each region individually
// No need for this mess in 4GB mode since windows doesn't use it
if (settings.platform.ram_size == 16 * 1024 * 1024)
{
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
@ -248,11 +247,6 @@ void bm_Reset()
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
mem_region_unlock(virt_ram_base + 0x0E000000, RAM_SIZE);
}
if (_nvmem_4gb_space())
{
mem_region_unlock(virt_ram_base + 0x8C000000u, 0x90000000u - 0x8C000000u);
mem_region_unlock(virt_ram_base + 0xAC000000u, 0xB0000000u - 0xAC000000u);
}
}
else
{
@ -264,38 +258,18 @@ void bm_LockPage(u32 addr, u32 size)
{
addr = addr & (RAM_MASK - PAGE_MASK);
if (_nvmem_enabled())
{
mem_region_lock(virt_ram_base + 0x0C000000 + addr, size);
if (_nvmem_4gb_space())
{
mem_region_lock(virt_ram_base + 0x8C000000 + addr, size);
mem_region_lock(virt_ram_base + 0xAC000000 + addr, size);
// TODO wraps
}
}
else
{
mem_region_lock(&mem_b[addr], size);
}
}
void bm_UnlockPage(u32 addr, u32 size)
{
addr = addr & (RAM_MASK - PAGE_MASK);
if (_nvmem_enabled())
{
mem_region_unlock(virt_ram_base + 0x0C000000 + addr, size);
if (_nvmem_4gb_space())
{
mem_region_unlock(virt_ram_base + 0x8C000000 + addr, size);
mem_region_unlock(virt_ram_base + 0xAC000000 + addr, size);
// TODO wraps
}
}
else
{
mem_region_unlock(&mem_b[addr], size);
}
}
void bm_ResetCache()
@ -618,18 +592,10 @@ u32 bm_getRamOffset(void *p)
{
if (_nvmem_enabled())
{
if (_nvmem_4gb_space())
{
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x100000000L)
return -1;
}
else
{
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x20000000)
return -1;
}
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x20000000)
return -1;
u32 addr = (u8*)p - virt_ram_base;
if (!IsOnRam(addr) || ((addr >> 29) > 0 && (addr >> 29) < 4)) // system RAM is not mapped to 20, 40 and 60 because of laziness
if (!IsOnRam(addr))
return -1;
return addr & RAM_MASK;
}

View File

@ -385,16 +385,7 @@ static void recSh4_Init()
if (_nvmem_enabled())
{
if (!_nvmem_4gb_space())
{
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x0C000000));
}
else
{
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x8C000000));
}
}
verify(mem_b.data == ((u8*)p_sh4rcb->sq_buffer + 512 + 0x0C000000));
// Prepare some pointer to the pre-allocated code cache:
void *candidate_ptr = (void*)(((unat)SH4_TCB + 4095) & ~4095);

View File

@ -118,19 +118,19 @@ static mem_handle_t allocate_shared_filemem(unsigned size)
*/
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
// The function supports allocating 512MB or 4GB addr spaces.
// vmem_base_addr points to an address space of 512MB (or 4GB) that can be used for fast memory ops.
// vmem_base_addr points to an address space of 512MB that can be used for fast memory ops.
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
// can be found. If the platform init returns error, the user is responsible for initializing the
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
{
return MemTypeError;
return false;
#if 0
const unsigned size_aligned = ((RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + PAGE_SIZE) & (~(PAGE_SIZE-1)));
vmem_fd_page = allocate_shared_filemem(size_aligned);
if (vmem_fd_page < 0)
return MemTypeError;
return false;
vmem_fd_codememory = (uintptr_t)virtmemReserve(size_aligned);
@ -141,15 +141,12 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
WARN_LOG(VMEM, "Failed to set perms (platform_int)...");
// Now try to allocate a contiguous piece of memory.
VMemType rv;
if (reserved_base == NULL)
{
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
reserved_base = mem_region_reserve(NULL, reserved_size);
if (!reserved_base)
return MemTypeError;
rv = MemType512MB;
return false;
}
*sh4rcb_addr = reserved_base;
@ -160,7 +157,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
return rv;
return true;
#endif
}

View File

@ -148,39 +148,28 @@ static int allocate_shared_filemem(unsigned size) {
}
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
// The function supports allocating 512MB or 4GB addr spaces.
int vmem_fd = -1;
static int shmem_fd2 = -1;
static void *reserved_base;
static size_t reserved_size;
// vmem_base_addr points to an address space of 512MB (or 4GB) that can be used for fast memory ops.
// vmem_base_addr points to an address space of 512MB that can be used for fast memory ops.
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
// can be found. If the platform init returns error, the user is responsible for initializing the
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize) {
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize) {
// Firt let's try to allocate the shm-backed memory
vmem_fd = allocate_shared_filemem(ramSize);
if (vmem_fd < 0)
return MemTypeError;
return false;
// Now try to allocate a contiguous piece of memory.
VMemType rv;
#if HOST_CPU == CPU_X64 || HOST_CPU == CPU_ARM64
reserved_size = 0x100000000L + sizeof(Sh4RCB) + 0x10000; // 4GB + context size + 64K padding
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
reserved_base = mem_region_reserve(NULL, reserved_size);
rv = MemType4GB;
#endif
if (reserved_base == NULL)
{
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
reserved_base = mem_region_reserve(NULL, reserved_size);
if (!reserved_base) {
close(vmem_fd);
return MemTypeError;
}
rv = MemType512MB;
if (!reserved_base) {
close(vmem_fd);
return false;
}
// Align pointer to 64KB too, some Linaro bug (no idea but let's just be safe I guess).
@ -194,7 +183,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
return rv;
return true;
}
// Just tries to wipe as much as possible in the relevant area.

View File

@ -1825,17 +1825,10 @@ private:
Instruction *start_instruction = GetCursorAddress<Instruction *>();
// WARNING: the rewrite code relies on having 1 or 2 ops before the memory access
// WARNING: the rewrite code relies on having 2 ops before the memory access
// Update ngen_Rewrite (and perhaps read_memory_rewrite_size) if adding or removing code
if (!_nvmem_4gb_space())
{
Ubfx(x1, x0, 0, 29);
Add(x1, x1, sizeof(Sh4Context), LeaveFlags);
}
else
{
Add(x1, x0, sizeof(Sh4Context), LeaveFlags);
}
Ubfx(x1, x0, 0, 29);
Add(x1, x1, sizeof(Sh4Context), LeaveFlags);
u32 size = op.flags & 0x7f;
switch(size)
@ -1998,17 +1991,10 @@ private:
Instruction *start_instruction = GetCursorAddress<Instruction *>();
// WARNING: the rewrite code relies on having 1 or 2 ops before the memory access
// WARNING: the rewrite code relies on having 2 ops before the memory access
// Update ngen_Rewrite (and perhaps write_memory_rewrite_size) if adding or removing code
if (!_nvmem_4gb_space())
{
Ubfx(x7, x0, 0, 29);
Add(x7, x7, sizeof(Sh4Context), LeaveFlags);
}
else
{
Add(x7, x0, sizeof(Sh4Context), LeaveFlags);
}
Ubfx(x7, x0, 0, 29);
Add(x7, x7, sizeof(Sh4Context), LeaveFlags);
u32 size = op.flags & 0x7f;
switch(size)
@ -2279,7 +2265,7 @@ bool ngen_Rewrite(host_context_t &context, void *faultAddress)
verify(found);
// Skip the preceding ops (add, ubfx)
u32 *code_rewrite = code_ptr - 1 - (!_nvmem_4gb_space() ? 1 : 0);
u32 *code_rewrite = code_ptr - 2;
Arm64Assembler *assembler = new Arm64Assembler(code_rewrite);
if (is_read)
assembler->GenReadMemorySlow(size);

View File

@ -741,13 +741,7 @@ public:
//found !
const u8 *start = getCurr();
u32 memAddress = _nvmem_4gb_space() ?
#ifdef _WIN32
context.rcx
#else
context.rdi
#endif
: context.r9;
u32 memAddress = context.r9;
if (op == MemOp::W && size >= MemSize::S32 && (memAddress >> 26) == 0x38)
call(MemHandlers[MemType::StoreQueue][size][MemOp::W]);
else
@ -759,12 +753,11 @@ public:
context.pc = (uintptr_t)(retAddr - 5);
// remove the call from the stack
context.rsp += 8;
if (!_nvmem_4gb_space())
//restore the addr from r9 to arg0 (rcx or rdi) so it's valid again
//restore the addr from r9 to arg0 (rcx or rdi) so it's valid again
#ifdef _WIN32
context.rcx = memAddress;
context.rcx = memAddress;
#else
context.rdi = memAddress;
context.rdi = memAddress;
#endif
return true;
@ -781,6 +774,7 @@ private:
{
if (mmu_enabled())
{
#ifdef FAST_MMU
Xbyak::Label inCache;
Xbyak::Label done;
@ -797,15 +791,18 @@ private:
}
test(eax, eax);
jne(inCache);
#endif
mov(call_regs[1], write);
mov(call_regs[2], block->vaddr + op.guest_offs - (op.delay_slot ? 2 : 0)); // pc
GenCall(mmuDynarecLookup);
mov(call_regs[0], eax);
#ifdef FAST_MMU
jmp(done);
L(inCache);
and_(call_regs[0], 0xFFF);
or_(call_regs[0], eax);
L(done);
#endif
}
}
bool GenReadMemImmediate(const shil_opcode& op, RuntimeBlockInfo* block)
@ -1125,11 +1122,9 @@ private:
if (type == MemType::Fast && _nvmem_enabled())
{
mov(rax, (uintptr_t)virt_ram_base);
if (!_nvmem_4gb_space())
{
mov(r9, call_regs64[0]);
and_(call_regs[0], 0x1FFFFFFF);
}
mov(r9, call_regs64[0]);
and_(call_regs[0], 0x1FFFFFFF);
switch (size)
{
case MemSize::S8:

View File

@ -45,14 +45,13 @@ static std::vector<void *> unmapped_regions;
static std::vector<void *> mapped_regions;
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
// The function supports allocating 512MB or 4GB addr spaces.
// Please read the POSIX implementation for more information. On Windows this is
// rather straightforward.
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
{
#ifdef TARGET_UWP
return MemTypeError;
return false;
#endif
unmapped_regions.reserve(32);
mapped_regions.reserve(32);
@ -81,7 +80,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
verify(ptr == *vmem_base_addr);
unmapped_regions.push_back(ptr);
return MemType512MB;
return true;
}
// Just tries to wipe as much as possible in the relevant area.