Skip to content

Commit 34b0978

Browse files
committed
msan changes
1 parent 4104ab0 commit 34b0978

File tree

6 files changed

+143
-109
lines changed

6 files changed

+143
-109
lines changed

src/core/gpu.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ uint32_t PCSX::GPU::gpuDmaChainSize(uint32_t addr) {
473473
size += (header >> 24) + 1;
474474

475475
// next 32-bit pointer
476-
uint32_t nextAddr = header & 0xfffffc;
476+
uint32_t nextAddr = header & 0xffffff;
477477
if (usingMsan && nextAddr == PCSX::Memory::c_msanChainMarker) {
478478
addr = g_emulator->m_mem->msanGetChainPtr(addr);
479479
continue;
@@ -745,7 +745,7 @@ void PCSX::GPU::chainedDMAWrite(const uint32_t *memory, uint32_t hwAddr) {
745745
}
746746

747747
// next 32-bit pointer
748-
uint32_t nextAddr = header & 0xfffffc;
748+
uint32_t nextAddr = header & 0xffffff;
749749
if (usingMsan && nextAddr == PCSX::Memory::c_msanChainMarker) {
750750
addr = g_emulator->m_mem->msanGetChainPtr(addr);
751751
continue;

src/core/psxhw.cc

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "core/psxemulator.h"
3131
#include "core/sio.h"
3232
#include "core/sio1.h"
33+
#include "supportpsx/memory.h"
3334
#include "lua/luawrapper.h"
3435
#include "spu/interface.h"
3536

@@ -373,16 +374,22 @@ uint32_t PCSX::HW::read32(uint32_t add) {
373374
}
374375
case 0x1f802094: {
375376
uint32_t headerAddr = g_emulator->m_cpu->m_regs.GPR.n.a0;
376-
if (headerAddr == 0x1f802094) {
377-
g_system->printf(_("Recursive msanGetChainPtr\n"));
378-
g_system->pause();
379-
return 0xffffffff;
380-
}
381-
uint32_t ptr = g_emulator->m_mem->read32(headerAddr) & 0xfffffc;
382-
if (ptr == PCSX::Memory::c_msanChainMarker) {
383-
return g_emulator->m_mem->msanGetChainPtr(headerAddr);
384-
} else {
385-
return ptr;
377+
PSXAddress headerAddrInfo(headerAddr);
378+
switch (headerAddrInfo.type) {
379+
case PSXAddress::Type::RAM:
380+
case PSXAddress::Type::MSAN: {
381+
uint32_t ptr = g_emulator->m_mem->read32(headerAddr) & 0xffffff;
382+
if (ptr == PCSX::Memory::c_msanChainMarker) {
383+
return g_emulator->m_mem->msanGetChainPtr(headerAddr);
384+
} else {
385+
return ptr;
386+
}
387+
}
388+
default: {
389+
g_system->printf(_("Called msanGetChainPtr with invalid header pointer %8.8lx\n"), headerAddr);
390+
g_system->pause();
391+
return 0xffffffff;
392+
}
386393
}
387394
}
388395
default: {
@@ -820,16 +827,22 @@ void PCSX::HW::write32(uint32_t add, uint32_t value) {
820827
break;
821828
}
822829
case 0x1f802094: {
823-
if (value == 0x1f802094) {
824-
g_system->printf(_("Recursive msanSetChainPtr\n"));
825-
g_system->pause();
826-
return;
830+
PSXAddress headerAddrInfo(value);
831+
switch (headerAddrInfo.type) {
832+
case PSXAddress::Type::RAM:
833+
case PSXAddress::Type::MSAN: {
834+
uint32_t ptrToNext = g_emulator->m_cpu->m_regs.GPR.n.a0;
835+
uint32_t wordCount = g_emulator->m_cpu->m_regs.GPR.n.a1;
836+
uint32_t markerValue = g_emulator->m_mem->msanSetChainPtr(value, ptrToNext, wordCount);
837+
g_emulator->m_mem->write32(value, markerValue);
838+
return;
839+
}
840+
default: {
841+
g_system->printf(_("Called msanSetChainPtr with invalid header pointer %8.8lx\n"), value);
842+
g_system->pause();
843+
return;
844+
}
827845
}
828-
uint32_t ptrToNext = g_emulator->m_cpu->m_regs.GPR.n.a0;
829-
uint32_t wordCount = g_emulator->m_cpu->m_regs.GPR.n.a1;
830-
uint32_t markerValue = g_emulator->m_mem->msanSetChainPtr(value, ptrToNext, wordCount);
831-
g_emulator->m_mem->write32(value, markerValue);
832-
return;
833846
}
834847
default: {
835848
if ((hwadd >= 0x1f801c00) && (hwadd < 0x1f801e00)) {

src/core/psxinterpreter.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -997,11 +997,16 @@ void InterpretedCPU::psxSW(uint32_t code) {
997997
void InterpretedCPU::psxSWL(uint32_t code) {
998998
uint32_t addr = _oB_;
999999
uint32_t shift = addr & 3;
1000-
// the check avoids msan interpreting a fully aligned store as a read
1001-
// however it may still interpret misaligned stores as reads
1002-
uint32_t mem = shift != 3? PCSX::g_emulator->m_mem->read32(addr & ~3): 0;
1000+
addr ^= shift;
1001+
uint32_t mem;
1002+
// special handling to avoid msan interpreting this as a read
1003+
if (PCSX::g_emulator->m_mem->msanInitialized() && PCSX::g_emulator->m_mem->inMsanRange(addr)) {
1004+
mem = *(uint32_t *)&PCSX::g_emulator->m_mem->m_msanRAM[addr - PCSX::Memory::c_msanStart];
1005+
} else {
1006+
mem = PCSX::g_emulator->m_mem->read32(addr);
1007+
}
10031008

1004-
PCSX::g_emulator->m_mem->write32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) | (mem & SWL_MASK[shift]));
1009+
PCSX::g_emulator->m_mem->write32(addr, (_u32(_rRt_) >> SWL_SHIFT[shift]) | (mem & SWL_MASK[shift]));
10051010
/*
10061011
Mem = 1234. Reg = abcd
10071012
0 123a (reg >> 24) | (mem & 0xffffff00)
@@ -1014,11 +1019,16 @@ void InterpretedCPU::psxSWL(uint32_t code) {
10141019
void InterpretedCPU::psxSWR(uint32_t code) {
10151020
uint32_t addr = _oB_;
10161021
uint32_t shift = addr & 3;
1017-
// the check avoids msan interpreting a fully aligned store as a read
1018-
// however it may still interpret misaligned stores as reads
1019-
uint32_t mem = shift != 0? PCSX::g_emulator->m_mem->read32(addr & ~3): 0;
1022+
addr ^= shift;
1023+
uint32_t mem;
1024+
// special handling to avoid msan interpreting this as a read
1025+
if (PCSX::g_emulator->m_mem->msanInitialized() && PCSX::g_emulator->m_mem->inMsanRange(addr)) {
1026+
mem = *(uint32_t *)&PCSX::g_emulator->m_mem->m_msanRAM[addr - PCSX::Memory::c_msanStart];
1027+
} else {
1028+
mem = PCSX::g_emulator->m_mem->read32(addr);
1029+
}
10201030

1021-
PCSX::g_emulator->m_mem->write32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) | (mem & SWR_MASK[shift]));
1031+
PCSX::g_emulator->m_mem->write32(addr, (_u32(_rRt_) << SWR_SHIFT[shift]) | (mem & SWR_MASK[shift]));
10221032

10231033
/*
10241034
Mem = 1234. Reg = abcd

src/core/psxmem.cc

Lines changed: 75 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -278,22 +278,24 @@ uint8_t PCSX::Memory::read8(uint32_t address) {
278278
const auto pointer = (uint8_t *)m_readLUT[page];
279279
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
280280

281-
if (msanInitialized() && inMsanRange(address)) {
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];
291-
}
292-
g_system->pause();
293-
return 0;
294-
} else if (pointer != nullptr) {
281+
if (pointer != nullptr) {
282+
if (msanInitialized() && inMsanRange(address)) [[unlikely]] {
283+
switch (msanGetStatus(address, 1)) {
284+
case MsanStatus::UNINITIALIZED:
285+
g_system->log(LogClass::CPU, _("8-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
286+
break;
287+
case MsanStatus::UNUSABLE:
288+
g_system->log(LogClass::CPU, _("8-bit read from unusable msan memory: %8.8lx\n"), address);
289+
break;
290+
case MsanStatus::OK:
291+
return m_msanRAM[address - c_msanStart];
292+
}
293+
g_system->pause();
294+
return 0;
295+
}
296+
[[likely]];
295297
const uint32_t offset = address & 0xffff;
296-
return *(pointer + offset);
298+
return *(pointer + offset);
297299
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
298300
if ((address & 0xffff) < 0x400) {
299301
return m_hard[address & 0x3ff];
@@ -326,20 +328,22 @@ uint16_t PCSX::Memory::read16(uint32_t address) {
326328
const auto pointer = (uint8_t *)m_readLUT[page];
327329
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
328330

329-
if (msanInitialized() && inMsanRange(address)) {
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];
331+
if (pointer != nullptr) {
332+
if (msanInitialized() && inMsanRange(address)) {
333+
switch (msanGetStatus(address, 2)) {
334+
case MsanStatus::UNINITIALIZED:
335+
g_system->log(LogClass::CPU, _("16-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
336+
break;
337+
case MsanStatus::UNUSABLE:
338+
g_system->log(LogClass::CPU, _("16-bit read from unusable msan memory: %8.8lx\n"), address);
339+
break;
340+
case MsanStatus::OK:
341+
return SWAP_LEu16(*(uint16_t *)&m_msanRAM[address - c_msanStart]);
342+
}
343+
g_system->pause();
344+
return 0;
339345
}
340-
g_system->pause();
341-
return 0;
342-
} else if (pointer != nullptr) {
346+
[[likely]];
343347
const uint32_t offset = address & 0xffff;
344348
return SWAP_LEu16(*(uint16_t *)(pointer + offset));
345349
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
@@ -371,20 +375,22 @@ uint32_t PCSX::Memory::read32(uint32_t address, ReadType readType) {
371375
const auto pointer = (uint8_t *)m_readLUT[page];
372376
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
373377

374-
if (msanInitialized() && inMsanRange(address)) {
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];
378+
if (pointer != nullptr) {
379+
if (msanInitialized() && inMsanRange(address)) {
380+
switch (msanGetStatus(address, 4)) {
381+
case MsanStatus::UNINITIALIZED:
382+
g_system->log(LogClass::CPU, _("32-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
383+
break;
384+
case MsanStatus::UNUSABLE:
385+
g_system->log(LogClass::CPU, _("32-bit read from unusable msan memory: %8.8lx\n"), address);
386+
break;
387+
case MsanStatus::OK:
388+
return SWAP_LEu32(*(uint32_t *)&m_msanRAM[address - c_msanStart]);
389+
}
390+
g_system->pause();
391+
return 0;
384392
}
385-
g_system->pause();
386-
return 0;
387-
} else if (pointer != nullptr) {
393+
[[likely]];
388394
const uint32_t offset = address & 0xffff;
389395
return SWAP_LEu32(*(uint32_t *)(pointer + offset));
390396
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
@@ -492,14 +498,16 @@ void PCSX::Memory::write8(uint32_t address, uint32_t value) {
492498
const auto pointer = (uint8_t *)m_writeLUT[page];
493499
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
494500

495-
if (msanInitialized() && inMsanRange(address)) {
496-
if (msanValidateWrite(address, 1)) {
497-
m_msanRAM[address - c_msanStart] = value;
498-
} else {
499-
g_system->log(LogClass::CPU, _("8-bit write to unusable msan memory: %8.8lx\n"), address);
500-
g_system->pause();
501+
if (pointer != nullptr) {
502+
if (msanInitialized() && inMsanRange(address)) {
503+
if (msanValidateWrite(address, 1)) {
504+
m_msanRAM[address - c_msanStart] = value;
505+
} else {
506+
g_system->log(LogClass::CPU, _("8-bit write to unusable msan memory: %8.8lx\n"), address);
507+
g_system->pause();
508+
}
501509
}
502-
} else if (pointer != nullptr) {
510+
[[likely]];
503511
const uint32_t offset = address & 0xffff;
504512
*(pointer + offset) = static_cast<uint8_t>(value);
505513
g_emulator->m_cpu->Clear((address & (~3)), 1);
@@ -527,14 +535,16 @@ void PCSX::Memory::write16(uint32_t address, uint32_t value) {
527535
const auto pointer = (uint8_t *)m_writeLUT[page];
528536
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
529537

530-
if (msanInitialized() && inMsanRange(address)) {
531-
if (msanValidateWrite(address, 2)) {
532-
*(uint16_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu16(value);
533-
} else {
534-
g_system->log(LogClass::CPU, _("16-bit write to unusable msan memory: %8.8lx\n"), address);
535-
g_system->pause();
538+
if (pointer != nullptr) {
539+
if (msanInitialized() && inMsanRange(address)) {
540+
if (msanValidateWrite(address, 2)) {
541+
*(uint16_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu16(value);
542+
} else {
543+
g_system->log(LogClass::CPU, _("16-bit write to unusable msan memory: %8.8lx\n"), address);
544+
g_system->pause();
545+
}
536546
}
537-
} else if (pointer != nullptr) {
547+
[[likely]];
538548
const uint32_t offset = address & 0xffff;
539549
*(uint16_t *)(pointer + offset) = SWAP_LEu16(static_cast<uint16_t>(value));
540550
g_emulator->m_cpu->Clear((address & (~3)), 1);
@@ -563,14 +573,16 @@ void PCSX::Memory::write32(uint32_t address, uint32_t value) {
563573
const auto pointer = (uint8_t *)m_writeLUT[page];
564574
const bool pioConnected = g_emulator->settings.get<Emulator::SettingPIOConnected>().value;
565575

566-
if (msanInitialized() && inMsanRange(address)) {
567-
if (msanValidateWrite(address, 4)) {
568-
*(uint32_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu32(value);
569-
} else {
570-
g_system->log(LogClass::CPU, _("32-bit write to unusable msan memory: %8.8lx\n"), address);
571-
g_system->pause();
576+
if (pointer != nullptr) {
577+
if (msanInitialized() && inMsanRange(address)) {
578+
if (msanValidateWrite(address, 4)) {
579+
*(uint32_t *)&m_msanRAM[address - c_msanStart] = SWAP_LEu32(value);
580+
} else {
581+
g_system->log(LogClass::CPU, _("32-bit write to unusable msan memory: %8.8lx\n"), address);
582+
g_system->pause();
583+
}
572584
}
573-
} else if (pointer != nullptr) {
585+
[[likely]];
574586
const uint32_t offset = address & 0xffff;
575587
*(uint32_t *)(pointer + offset) = SWAP_LEu32(value);
576588
g_emulator->m_cpu->Clear((address & (~3)), 1);
@@ -923,19 +935,6 @@ uint32_t PCSX::Memory::msanRealloc(uint32_t ptr, uint32_t size) {
923935
return newPtr + c_msanStart;
924936
}
925937

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-
939938
bool PCSX::Memory::msanValidateWrite(uint32_t addr, uint32_t size) {
940939
uint32_t msanAddr = addr - c_msanStart;
941940
if (!(m_msanUsableBitmap[msanAddr / 8] & (1 << msanAddr % 8))) {
@@ -944,6 +943,7 @@ bool PCSX::Memory::msanValidateWrite(uint32_t addr, uint32_t size) {
944943
for (uint32_t checkAddr = msanAddr; checkAddr < msanAddr + size; checkAddr++) {
945944
m_msanWrittenBitmap[checkAddr / 8] |= 1 << checkAddr % 8;
946945
}
946+
[[likely]];
947947
return true;
948948
}
949949

src/core/psxmem.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace PCSX {
4949

5050
enum class MsanStatus {
5151
UNUSABLE, // memory that hasn't been allocated or has been freed
52-
UNINITIALIZED, // allocated memory that has never been written to; unreliable
52+
UNINITIALIZED, // allocated memory that has never been written to, has undefined contents
5353
OK // free to use
5454
};
5555

@@ -90,7 +90,18 @@ class Memory {
9090
uint32_t msanRealloc(uint32_t ptr, uint32_t size);
9191
uint32_t msanSetChainPtr(uint32_t headerAddr, uint32_t ptrToNext, uint32_t size);
9292
uint32_t msanGetChainPtr(uint32_t addr) const;
93-
MsanStatus msanGetStatus(uint32_t addr, uint32_t size) const;
93+
inline MsanStatus msanGetStatus(uint32_t addr, uint32_t size) const {
94+
uint32_t msanAddr = addr - c_msanStart;
95+
if (!(m_msanUsableBitmap[msanAddr / 8] & (1 << msanAddr % 8))) {
96+
return MsanStatus::UNUSABLE;
97+
}
98+
for (uint32_t checkAddr = msanAddr; checkAddr < msanAddr + size; checkAddr++) {
99+
if (!(m_msanWrittenBitmap[checkAddr / 8] & (1 << checkAddr % 8))) {
100+
return MsanStatus::UNINITIALIZED;
101+
}
102+
}
103+
return MsanStatus::OK;
104+
}
94105
bool msanValidateWrite(uint32_t addr, uint32_t size);
95106

96107
static inline bool inMsanRange(uint32_t addr) {
@@ -285,7 +296,7 @@ class Memory {
285296
EventBus::Listener m_listener;
286297

287298
std::unordered_map<uint32_t, uint32_t> m_msanAllocs;
288-
static constexpr uint32_t c_msanChainMarker = 0x7ffffc;
299+
static constexpr uint32_t c_msanChainMarker = 0x7ffffd;
289300
std::unordered_map<uint32_t, uint32_t> m_msanChainRegistry;
290301

291302
template <typename T = void>

0 commit comments

Comments
 (0)