[blog] Virtual Memory
#1
The Playstation 2 uses co-processor 0 to implement virtual paging. Even without COP0, the Playstation 2 memory map is pretty complex and the mapping can change depending on which processor you use to read the memory from. A simple version of how the default mapping looks from the Emotion Engine side is:

The 32Mb of main memory occupying 0000_0000 - 01ff_ffff
Hardware registers occupying 1000_0000 - 1000_ffff
VU/BIOS/SPU2 addresses in 1100_0000-1fff_ffff
Special kernel modes etc in 8000_0000-bfff_ffff
A scratch pad in some other address
...And of course can't forget the hidden addresses (thanks SONY)

To make matters worse, these mappings can change depending on the setting of COP0. (Note that at the time of writing, Pcsx2 doesn't emulate even half of COP0 correctly.) The simplest and most straightforward way to emulate this is to have another memory layer through a software Translation-Lookaside-Buffer (TLB). You pass it the PS2 address, and out comes the real physical address or some special code signifying a hardware register, etc. The problem is that every read/write has to be preceded by a TLB lookup. Considering that reads/writes are as common as addition, that's a lot of wasted cycles.

Well, the OS also uses virtual memory. In fact, every process has its own special virtual memory driven by a real hardware TLB. If we could get away by mapping the 4Gb PS2 memory map onto the process's virtual memory, we could eliminate the need for the software translation (Figure 1). Looking at the virtual manipulation functions Windows XP offers, there are two major problems with this:

[Image: attachment.php?aid=%2021692]

1 WindowsXP reserves more than half the address space for OS specific stuff. A good amount is also reserved for all of Pcsx2's working memory, executable code, and plugins (especially ZeroGS). It looks like we are left with less than 1.5 Gb of address range to implement the 4Gb PS2 memory map. Note that this problem doesn't exist on 64bit operating systems where the address range is practically... infinite (don't quote me on this 20 years down the road).

2 Playstation 2 allows more than one virtual page to point to the same physical page, Windows XP doesn't (I don't know about Linux). Assume that PS2 address 0x1000 points to the same physical page as address 0x0000, each page is 4Kb. Now a write occurs at 0x1000. The game can retrieve that same value just by reading from 0x0000. In Windows XP, this has to be two different pages; so unless some clever solution/technology is discovered, we could kiss our VM dreams goodbye.

The first problem was solved somehow by introducing special address transformations before a read/write occurs.

And thankfully a clever technology presented itself for the second problem: Address Windowing Extensions. This lets Pcsx2 handle the actual physical page instead of a virtual page. We still can't map two virtual pages to the same physical page; however, what we can do instead is switch the mapping of the physical page as many times as needed! To achieve this, Pcsx2 hacks into the root exception handler and intercepts every exception the program generates. Whenever an illegal virtual page is accessed (ie, no physical page mapped to it), Pcsx2 gets a EXCEPTION_ACCESS_VIOLATION then it remaps the correct physical page to that empty virtual page and returns. Although I haven't calculated precisely, I'm pretty sure that switching physical pages around is pretty expensive, computationally speaking. So all this works fine under the assumption that game developers won't be crazy and access two virtual pages mapping to the same physical page back-and-forth frequently... [pause].

Alas, we were wrong... again (see floating-point article). It turns out that there are uncached and cached address ranges; so it is optimal to do such a bi-mapping trick: write in one virtual range and read from another. Pcsx2 tries to detect such cases and work around, but there's no clean solution.

And I'm going to stop here before this becomes a book.

So the ultimate question is: why doesn't VM work on some computers with 1Gb of RAM and the newest updates, while works on others? Turns out that real-time monitoring applications like to take up some of the 1.5 Gb of left over addresses on certain processes. (this might be OS specific programs too). I have also observed that performance/debugging monitors like NvPerfHud do similar tricks. There probably might be other reasons for VM builds of Pcsx2 not working because virtual memory is a pretty complicated issue.

Moral of the blog Read an OS book. I recommend Operating System Concepts (the dinosaur book) by Abraham Silberschatz, Peter Baer Galvin, Greg Gagne.
Reply

Sponsored links

#2
Hi, all. I am new here. I am a video game player and a software engineer---You can see why i'm quite interested in the work of yours.

I have been reading codes from pcsx2 0.9.6 for a while, mainly focused on the recompiling part. One question concening instruction fetching would not get off my mind. And since I cannot post new topic in this block, I have to reply the related blog here.

In the function "recRecompile" of "i5900-32.cpp", which I believe is the core of the recompiling engine, instructions are fethced by using the macro "PSM(<pc>)". The macro and its content seem suggesting that it maps a HW address within RAM space into the host storage of the RAM.

While "PC" should be a Virtual space address, but it doesn't go through "Virtual to HW space" translation. It may mean that either I misunderstood some codes, or that all or most ps2 binary codes resides in mem sections that are directly mapped.

Can anyone solve my confusion? Thanks a lot.
Reply
#3
(06-24-2010, 06:15 AM)zlw Wrote: In the function "recRecompile" of "i5900-32.cpp", which I believe is the core of the recompiling engine, instructions are fethced by using the macro "PSM()". The macro and its content seem suggesting that it maps a HW address within RAM space into the host storage of the RAM.

While "PC" should be a Virtual space address, but it doesn't go through "Virtual to HW space" translation. It may mean that either I misunderstood some codes, or that all or most ps2 binary codes resides in mem sections that are directly mapped.

Few, if any, PS2 games remap the PS2's system memory at all, and PCSX2's support for remappable memory is basically nil at this point. So yeah, as far as PCSX2 and playing games is concerned, there's no functional difference between using physical RAM addresses or going through the VTLB translator.

It's on the todo list to improve TLB support in PCSX2, but without any game even touching the TLB, there's little motivation to do so. The only thing that would be affected, as far as I know, is running PS2 Linux under PCSX2. Joy! Tongue
Jake Stine (Air) - Programmer - PCSX2 Dev Team
Reply
#4
(06-24-2010, 07:13 AM)Air Wrote: Few, if any, PS2 games remap the PS2's system memory at all, and PCSX2's support for remappable memory is basically nil at this point.

do we have any console printouts or a way to let us know if a game is trying to remap memory?
Check out my blog: Trashcan of Code
Reply
#5
I think I saw some "mDevCon::WriteLn" calls in the "COP0.cpp:MapTLB", which is invoked by EE instructions like "TLBWI". The "WriteLn" thing looks like some sort of trace info. Maybe that's how people found out that most commercial games are not using the virtual/phy address mapping.

Thanks, Air, your comments helped a lot. But I have some further questions if you don't mind:

First, some of the memory accessing logics seem using virtual/physical mem mapping anyway---like recLW---though the mapping lookup table may produce the exactly same phy address, the translation logic is there. Besides, the mapping table is manipulated when instruction like "TLBWI" comes. So we can say the virtual/phy mapping is (partly) implemented. Only the game codes don't use it, plus the instruction fetching is not using it. Am I right?

The "windows VM helped memory mapping" is by default disabled in 0.9.6, and the flag "PCSX2_VIRTUAL_MEM" is used to control that feature, right?

In a real ps2, I know now that most games employ a direct virtual/phy mapping policy, but how is that implemented in the real ps2? Is it done by programming some TLB entries to do the direct mapping for the whole accessable memory space? If yes, what component does the trick? Bios, or some system level codes in the games? or can it even be physically wired?

Thanks again.
Reply
#6
(06-24-2010, 04:15 PM)zlw Wrote: First, some of the memory accessing logics seem using virtual/physical mem mapping anyway---like recLW---though the mapping lookup table may produce the exactly same phy address, the translation logic is there. Besides, the mapping table is manipulated when instruction like "TLBWI" comes. So we can say the virtual/phy mapping is (partly) implemented. Only the game codes don't use it, plus the instruction fetching is not using it. Am I right?

The other part that isn't implemented is the TLB Refill exception system (a MIPS-specific design). Without it, any game remapping the TLB will typically fail. There's also lacking support int he recompilers -- if a game were to remap the TLB, the recompiled code may still assume the old mapping and fail. (its an optimization)

Quote:The "windows VM helped memory mapping" is by default disabled in 0.9.6, and the flag "PCSX2_VIRTUAL_MEM" is used to control that feature, right?

Not anymore. the Windows-based virtual memory implementation was generally not very good. It didn't work on a lot of Windows installs because it needed to allocate specific memory ranges and around 1.5gb worth at that. If any other drivers or windows kernel stuff reserved some of those areas first, it would get a VM error and quit.

We've since removed all but a few tidbits of that old system. The remaining tidbits are for reference only and will probably be removed soon.

Edit: the old VM implementation also had limited TLB support. It ignored the COP0 entirely and assumed the default memory map for the EE, and it would have been impossible to implement efficient TLB support into the old VM system due to the way it worked.
Jake Stine (Air) - Programmer - PCSX2 Dev Team
Reply
#7
Thank you. Those comments will make my reading much easier.
Reply




Users browsing this thread: 1 Guest(s)