motoharu-gosuto / psvgamesd

User application and kernel plugin that allow to produce game card dumps and run them.
MIT License
104 stars 12 forks source link

Physical insertion bug after virtual mode insertion #1

Closed motoharu-gosuto closed 7 years ago

motoharu-gosuto commented 7 years ago

Steps to reproduce:

Read led just flashes forever and loading popup does not appear.

motoharu-gosuto commented 7 years ago

review get_insertion_state() and set_insertion_state() calls. looks like some insert_card() / remove card() calls that should be near, are missing. add proper delays after insertion and removal.

motoharu-gosuto commented 7 years ago

After adding ton of logging i have figured out that all initialization and deinitialization between switching modes works fine. Upon inserting physical card - initialization goes well till the moment after second CMD17/CMD13 pair of commands. This has 100% same behavior as in virtual mode when trying to emulate CMD13/CMD17 commands. It could be that it is some type of deadlock on read? Though this is very stable deadlock.

motoharu-gosuto commented 7 years ago

Looks like this bug is not related to conflict between mmc and sd modes. It also occurs when:

I suspect smth is wrong with remove emulation. Or some other module also handles insert/remove interrupt and does something. Need to check this by logging interrupt handler register function.

motoharu-gosuto commented 7 years ago

This could be a post effect of incomplete command emulation. Since behavior is completely similar in virtual mode - freezes after second CMD17. Maybe this is actually the same freeze? Since in virtual mode CMD17 is not emulated - instead read op is hooked. So when switching back to physical - somehow it manages to initialize till CMD17 and then freezes.

This is still a mystery though. Because I have added the code that fully reinitializes/clears all data sections that are related to game card in Sdif module. And still this bug is not fixed. This includes:

I suspect the real reason can be in Sdstor (maybe something is cached and not reinitialized?) Or in some invalid state of card. However card is reset with CMD0 during initialization!

motoharu-gosuto commented 7 years ago

After adding more logging I figured out that it goes to infinite initialiation after entering sdstor_read_sector_mmc function. It never exits the function and actual CMD17 that reads EXFAT MBR is never executed.

motoharu-gosuto commented 7 years ago

I figured out that deadlock happens on fast_mutex in function sd_context_data_lock_mutex_C68560 This is a function to manage locking of global mutex per device in sd_context_data Function is paired with sd_context_data_unlock_mutex_C6857C. Somehow mutex is not unlocked and then it is locked again and sdif enters deadlock.

What is interesting is that these functions check unk_25 byte flag. If I set it - mutex locks/unlocks are skipped. But this does not solve all deadlock problems.

motoharu-gosuto commented 7 years ago

I was able to fix this deadlock by hooking mutex lock and unlock functions that are imported. Check commits: 33de844c1a5228c572ac2bf0c039a6076bee42b7 8d210f7f141e12112aaa0b78b799f2546f2a8aa9

What happens is that lock and unlock operations are ignored for SceSdif1 mutex (specifically checked). I have tried to replace fast_mutex with standard recoursive mutex, however it does not work - I also get deadlocks. I am starting to suspect that in SD mode some SD specific code is called which unintentionally locks mutex multiple times (since I observed that there are multiple recoursive locks from same thread). Maybe this breaks the mutex?