Skip to content

Commit 49cbcc5

Browse files
committed
cleanup msan checks to do them on DMA too
1 parent f836e23 commit 49cbcc5

File tree

4 files changed

+119
-70
lines changed

4 files changed

+119
-70
lines changed

src/core/gpu.cc

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,19 @@ uint32_t PCSX::GPU::gpuDmaChainSize(uint32_t addr) {
448448
uint32_t header;
449449
if (usingMsan && PCSX::Memory::inMsanRange(addr)) {
450450
addr &= 0xfffffffc;
451-
header = *(uint32_t *) (g_emulator->m_mem->m_msanRAM + (addr - PCSX::Memory::c_msanStart));
451+
switch (g_emulator->m_mem->msanGetStatus(addr, 4)) {
452+
case PCSX::MsanStatus::UNINITIALIZED:
453+
g_system->log(LogClass::GPU, _("GPU DMA went into usable but uninitialized msan memory: %8.8lx\n"), addr);
454+
g_system->pause();
455+
return size;
456+
case PCSX::MsanStatus::UNUSABLE:
457+
g_system->log(LogClass::GPU, _("GPU DMA went into unusable msan memory: %8.8lx\n"), addr);
458+
g_system->pause();
459+
return size;
460+
case PCSX::MsanStatus::OK:
461+
header = *(uint32_t *) (g_emulator->m_mem->m_msanRAM + (addr - PCSX::Memory::c_msanStart));
462+
break;
463+
}
452464
} else {
453465
addr &= g_emulator->getRamMask<4>();
454466
header = SWAP_LEu32(*g_emulator->m_mem->getPointer<uint32_t>(addr));
@@ -702,6 +714,18 @@ void PCSX::GPU::chainedDMAWrite(const uint32_t *memory, uint32_t hwAddr) {
702714
if (usingMsan && PCSX::Memory::inMsanRange(addr)) {
703715
addr &= 0xfffffffc;
704716
const uint32_t *headerPtr = (uint32_t *) (g_emulator->m_mem->m_msanRAM + (addr - PCSX::Memory::c_msanStart));
717+
switch (g_emulator->m_mem->msanGetStatus(addr, 4)) {
718+
case PCSX::MsanStatus::UNINITIALIZED:
719+
g_system->log(LogClass::GPU, _("GPU DMA went into usable but uninitialized msan memory: %8.8lx\n"), addr);
720+
g_system->pause();
721+
return;
722+
case PCSX::MsanStatus::UNUSABLE:
723+
g_system->log(LogClass::GPU, _("GPU DMA went into unusable msan memory: %8.8lx\n"), addr);
724+
g_system->pause();
725+
return;
726+
case PCSX::MsanStatus::OK:
727+
break;
728+
}
705729
header = *headerPtr;
706730
feed = headerPtr + 1;
707731
} else {

src/core/psxhw.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ class HW {
7777
do {
7878
if (usingMsan && PCSX::Memory::inMsanRange(madr)) {
7979
madr &= 0xfffffffc;
80+
switch (g_emulator->m_mem->msanGetStatus(madr, 4)) {
81+
case PCSX::MsanStatus::UNINITIALIZED:
82+
g_system->log(LogClass::GPU, _("GPU DMA went into usable but uninitialized msan memory: %8.8lx\n"), madr);
83+
g_system->pause();
84+
return;
85+
case PCSX::MsanStatus::UNUSABLE:
86+
g_system->log(LogClass::GPU, _("GPU DMA went into unusable msan memory: %8.8lx\n"), madr);
87+
g_system->pause();
88+
return;
89+
case PCSX::MsanStatus::OK:
90+
break;
91+
}
8092
} else {
8193
madr &= 0x7ffffc;
8294
}

src/core/psxmem.cc

Lines changed: 73 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ static const std::map<uint32_t, std::string_view> s_knownBioses = {
8888
PCSX::Memory::Memory() : m_listener(g_system->m_eventBus) {
8989
m_listener.listen<Events::ExecutionFlow::Reset>([this](auto &) {
9090
free(m_msanRAM);
91-
free(m_msanBitmap);
91+
free(m_msanUsableBitmap);
9292
free(m_msanWrittenBitmap);
9393
m_msanRAM = nullptr;
94-
m_msanBitmap = nullptr;
94+
m_msanUsableBitmap = nullptr;
9595
m_msanWrittenBitmap = nullptr;
9696
m_msanAllocs.clear();
9797
});
@@ -264,10 +264,10 @@ void PCSX::Memory::shutdown() {
264264
free(m_writeLUT);
265265

266266
free(m_msanRAM);
267-
free(m_msanBitmap);
267+
free(m_msanUsableBitmap);
268268
free(m_msanWrittenBitmap);
269269
m_msanRAM = nullptr;
270-
m_msanBitmap = nullptr;
270+
m_msanUsableBitmap = nullptr;
271271
m_msanWrittenBitmap = nullptr;
272272
m_msanAllocs.clear();
273273
}
@@ -279,19 +279,18 @@ uint8_t PCSX::Memory::read8(uint32_t address) {
279279
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
280280

281281
if (msanInitialized() && inMsanRange(address)) {
282-
uint32_t msanAddress = address - c_msanStart;
283-
if ((m_msanWrittenBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) == 0) {
284-
g_system->log(LogClass::CPU, _("8-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
285-
g_system->pause();
286-
return 0;
287-
}
288-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
289-
return m_msanRAM[msanAddress];
290-
} else {
291-
g_system->log(LogClass::CPU, _("8-bit read from unusable msan memory: %8.8lx\n"), address);
292-
g_system->pause();
293-
return 0;
282+
switch (msanGetStatus(address, 1)) {
283+
case MsanStatus::UNINITIALIZED:
284+
g_system->log(LogClass::CPU, _("8-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
285+
break;
286+
case MsanStatus::UNUSABLE:
287+
g_system->log(LogClass::CPU, _("8-bit read from unusable msan memory: %8.8lx\n"), address);
288+
break;
289+
case MsanStatus::OK:
290+
return m_msanRAM[address - c_msanStart];
294291
}
292+
g_system->pause();
293+
return 0;
295294
} else if (pointer != nullptr) {
296295
const uint32_t offset = address & 0xffff;
297296
return *(pointer + offset);
@@ -328,22 +327,18 @@ uint16_t PCSX::Memory::read16(uint32_t address) {
328327
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
329328

330329
if (msanInitialized() && inMsanRange(address)) {
331-
uint32_t msanAddress = address - c_msanStart;
332-
for (unsigned offset = 0; offset < 2; offset++) {
333-
if ((m_msanWrittenBitmap[(msanAddress + offset) / 8] & (1 << ((msanAddress + offset) % 8))) == 0) {
334-
g_system->log(LogClass::CPU, _("16-bit read from usable but uninitialized msan memory: %8.8lx\n"),
335-
address);
336-
g_system->pause();
337-
return 0;
338-
}
339-
}
340-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
341-
return *(uint16_t *)&m_msanRAM[msanAddress];
342-
} else {
343-
g_system->log(LogClass::CPU, _("16-bit read from unusable msan memory: %8.8lx\n"), address);
344-
g_system->pause();
345-
return 0;
330+
switch (msanGetStatus(address, 2)) {
331+
case MsanStatus::UNINITIALIZED:
332+
g_system->log(LogClass::CPU, _("16-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
333+
break;
334+
case MsanStatus::UNUSABLE:
335+
g_system->log(LogClass::CPU, _("16-bit read from unusable msan memory: %8.8lx\n"), address);
336+
break;
337+
case MsanStatus::OK:
338+
return *(uint16_t *)&m_msanRAM[address - c_msanStart];
346339
}
340+
g_system->pause();
341+
return 0;
347342
} else if (pointer != nullptr) {
348343
const uint32_t offset = address & 0xffff;
349344
return SWAP_LEu16(*(uint16_t *)(pointer + offset));
@@ -377,22 +372,18 @@ uint32_t PCSX::Memory::read32(uint32_t address, ReadType readType) {
377372
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
378373

379374
if (msanInitialized() && inMsanRange(address)) {
380-
uint32_t msanAddress = address - c_msanStart;
381-
for (unsigned offset = 0; offset < 4; offset++) {
382-
if ((m_msanWrittenBitmap[(msanAddress + offset) / 8] & (1 << ((msanAddress + offset) % 8))) == 0) {
383-
g_system->log(LogClass::CPU, _("32-bit read from usable but uninitialized msan memory: %8.8lx\n"),
384-
address);
385-
g_system->pause();
386-
return 0;
387-
}
388-
}
389-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
390-
return *(uint32_t *)&m_msanRAM[msanAddress];
391-
} else {
392-
g_system->log(LogClass::CPU, _("32-bit read from unusable msan memory: %8.8lx\n"), address);
393-
g_system->pause();
394-
return 0;
375+
switch (msanGetStatus(address, 4)) {
376+
case MsanStatus::UNINITIALIZED:
377+
g_system->log(LogClass::CPU, _("32-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
378+
break;
379+
case MsanStatus::UNUSABLE:
380+
g_system->log(LogClass::CPU, _("32-bit read from unusable msan memory: %8.8lx\n"), address);
381+
break;
382+
case MsanStatus::OK:
383+
return *(uint32_t *)&m_msanRAM[address - c_msanStart];
395384
}
385+
g_system->pause();
386+
return 0;
396387
} else if (pointer != nullptr) {
397388
const uint32_t offset = address & 0xffff;
398389
return SWAP_LEu32(*(uint32_t *)(pointer + offset));
@@ -502,10 +493,8 @@ void PCSX::Memory::write8(uint32_t address, uint32_t value) {
502493
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
503494

504495
if (msanInitialized() && inMsanRange(address)) {
505-
uint32_t msanAddress = address - c_msanStart;
506-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
507-
m_msanWrittenBitmap[msanAddress / 8] |= (1 << (msanAddress % 8));
508-
m_msanRAM[msanAddress] = value;
496+
if (msanValidateWrite(address, 1)) {
497+
m_msanRAM[address - c_msanStart] = value;
509498
} else {
510499
g_system->log(LogClass::CPU, _("8-bit write to unusable msan memory: %8.8lx\n"), address);
511500
g_system->pause();
@@ -539,12 +528,8 @@ void PCSX::Memory::write16(uint32_t address, uint32_t value) {
539528
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
540529

541530
if (msanInitialized() && inMsanRange(address)) {
542-
uint32_t msanAddress = address - c_msanStart;
543-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
544-
for (unsigned offset = 0; offset < 2; offset++) {
545-
m_msanWrittenBitmap[(msanAddress + offset) / 8] |= (1 << ((msanAddress + offset) % 8));
546-
}
547-
*(uint16_t *)&m_msanRAM[msanAddress] = value;
531+
if (msanValidateWrite(address, 2)) {
532+
*(uint16_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu16(value);
548533
} else {
549534
g_system->log(LogClass::CPU, _("16-bit write to unusable msan memory: %8.8lx\n"), address);
550535
g_system->pause();
@@ -579,12 +564,8 @@ void PCSX::Memory::write32(uint32_t address, uint32_t value) {
579564
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
580565

581566
if (msanInitialized() && inMsanRange(address)) {
582-
uint32_t msanAddress = address - c_msanStart;
583-
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
584-
for (unsigned offset = 0; offset < 4; offset++) {
585-
m_msanWrittenBitmap[(msanAddress + offset) / 8] |= (1 << ((msanAddress + offset) % 8));
586-
}
587-
*(uint32_t *)&m_msanRAM[msanAddress] = value;
567+
if (msanValidateWrite(address, 4)) {
568+
*(uint32_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu32(value);
588569
} else {
589570
g_system->log(LogClass::CPU, _("32-bit write to unusable msan memory: %8.8lx\n"), address);
590571
g_system->pause();
@@ -820,10 +801,10 @@ void PCSX::Memory::MemoryAsFile::writeBlock(const void *src, size_t size, size_t
820801
void PCSX::Memory::initMsan(bool reset) {
821802
if (reset) {
822803
free(m_msanRAM);
823-
free(m_msanBitmap);
804+
free(m_msanUsableBitmap);
824805
free(m_msanWrittenBitmap);
825806
m_msanRAM = nullptr;
826-
m_msanBitmap = nullptr;
807+
m_msanUsableBitmap = nullptr;
827808
m_msanWrittenBitmap = nullptr;
828809
m_msanAllocs.clear();
829810
m_msanChainRegistry.clear();
@@ -836,7 +817,7 @@ void PCSX::Memory::initMsan(bool reset) {
836817

837818
// 1.5GB of RAM, with 384MB worth of bitmap, between 0x20000000 and 0x80000000
838819
m_msanRAM = (uint8_t *)calloc(c_msanSize, 1);
839-
m_msanBitmap = (uint8_t *)calloc(c_msanSize / 8, 1);
820+
m_msanUsableBitmap = (uint8_t *)calloc(c_msanSize / 8, 1);
840821
m_msanWrittenBitmap = (uint8_t *)calloc(c_msanSize / 8, 1);
841822
m_msanPtr = 1024;
842823
for (uint32_t segment = c_msanStart; segment < c_msanEnd; segment += 0x10000) {
@@ -864,7 +845,7 @@ uint32_t PCSX::Memory::msanAlloc(uint32_t size) {
864845
m_msanPtr += actualSize;
865846
// Mark the allocation as usable.
866847
for (uint32_t i = 0; i < size; i++) {
867-
m_msanBitmap[(ptr + i) / 8] |= 1 << ((ptr + i) % 8);
848+
m_msanUsableBitmap[(ptr + i) / 8] |= 1 << ((ptr + i) % 8);
868849
}
869850

870851
// Insert the allocation into the list of allocations.
@@ -891,7 +872,7 @@ void PCSX::Memory::msanFree(uint32_t ptr) {
891872
}
892873
// Mark the allocation as unusable.
893874
for (uint32_t i = 0; i < m_msanAllocs[ptr]; i++) {
894-
m_msanBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
875+
m_msanUsableBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
895876
}
896877
// Remove the allocation from the list of allocations.
897878
m_msanAllocs.erase(ptr);
@@ -930,7 +911,7 @@ uint32_t PCSX::Memory::msanRealloc(uint32_t ptr, uint32_t size) {
930911

931912
// Mark the old allocation as unusable
932913
for (uint32_t i = 0; i < oldSize; i++) {
933-
m_msanBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
914+
m_msanUsableBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
934915
}
935916
// Mark the new allocation as written to
936917
auto toCopy = std::min(size, oldSize);
@@ -942,6 +923,30 @@ uint32_t PCSX::Memory::msanRealloc(uint32_t ptr, uint32_t size) {
942923
return newPtr + c_msanStart;
943924
}
944925

926+
PCSX::MsanStatus PCSX::Memory::msanGetStatus(uint32_t addr, uint32_t size) const {
927+
uint32_t msanAddr = addr - c_msanStart;
928+
if (!(m_msanUsableBitmap[msanAddr / 8] & (1 << msanAddr % 8))) {
929+
return PCSX::MsanStatus::UNUSABLE;
930+
}
931+
for (uint32_t checkAddr = msanAddr; checkAddr < msanAddr + size; checkAddr++) {
932+
if (!(m_msanWrittenBitmap[checkAddr / 8] & (1 << checkAddr % 8))) {
933+
return PCSX::MsanStatus::UNINITIALIZED;
934+
}
935+
}
936+
return PCSX::MsanStatus::OK;
937+
}
938+
939+
bool PCSX::Memory::msanValidateWrite(uint32_t addr, uint32_t size) {
940+
uint32_t msanAddr = addr - c_msanStart;
941+
if (!(m_msanUsableBitmap[msanAddr / 8] & (1 << msanAddr % 8))) {
942+
return false;
943+
}
944+
for (uint32_t checkAddr = msanAddr; checkAddr < msanAddr + size; checkAddr++) {
945+
m_msanWrittenBitmap[checkAddr / 8] |= 1 << checkAddr % 8;
946+
}
947+
return true;
948+
}
949+
945950
uint32_t PCSX::Memory::msanSetChainPtr(uint32_t headerAddr, uint32_t nextPtr, uint32_t wordCount) {
946951
if (!inMsanRange(headerAddr)) {
947952
headerAddr &= 0xffffff;

src/core/psxmem.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
namespace PCSX {
4949

50+
enum class MsanStatus {
51+
UNUSABLE, // memory that hasn't been allocated or has been freed
52+
UNINITIALIZED, // allocated memory that has never been written to; unreliable
53+
OK // free to use
54+
};
55+
5056
class Memory {
5157
public:
5258
Memory();
@@ -84,6 +90,8 @@ class Memory {
8490
uint32_t msanRealloc(uint32_t ptr, uint32_t size);
8591
uint32_t msanSetChainPtr(uint32_t headerAddr, uint32_t ptrToNext, uint32_t size);
8692
uint32_t msanGetChainPtr(uint32_t addr) const;
93+
MsanStatus msanGetStatus(uint32_t addr, uint32_t size) const;
94+
bool msanValidateWrite(uint32_t addr, uint32_t size);
8795

8896
static inline bool inMsanRange(uint32_t addr) {
8997
return addr >= c_msanStart && addr < c_msanEnd;
@@ -271,7 +279,7 @@ class Memory {
271279
static constexpr uint32_t c_msanStart = 0x20000000;
272280
static constexpr uint32_t c_msanEnd = c_msanStart + c_msanSize;
273281
uint8_t *m_msanRAM = nullptr;
274-
uint8_t *m_msanBitmap = nullptr;
282+
uint8_t *m_msanUsableBitmap = nullptr;
275283
uint8_t *m_msanWrittenBitmap = nullptr;
276284
uint32_t m_msanPtr = 1024;
277285
EventBus::Listener m_listener;

0 commit comments

Comments
 (0)