On PowerPC Macs, this code will designate a page as "Quiet Read-Only". Writes to that page will be silently ignored, instead of generating an exception.
It can cause all sorts of interesting crashes and misbehavior. Most code assumes that when you make a memory write, memory actually gets written. It is thus an excellent tool for making code behave oddly.
Using this when Virtual Memory is on is probably a bad idea. Virtual Memory will have no idea that you did this, and might try to move or page out the page you have modified.
It has to be compiled as 68k, because the NanoKernel Virtual Memory API (invoked with 0xFE06 or 0xFE0A) only works from the 68k Emulator.
It can cause all sorts of interesting crashes and misbehavior. Most code assumes that when you make a memory write, memory actually gets written. It is thus an excellent tool for making code behave oddly.
Using this when Virtual Memory is on is probably a bad idea. Virtual Memory will have no idea that you did this, and might try to move or page out the page you have modified.
It has to be compiled as 68k, because the NanoKernel Virtual Memory API (invoked with 0xFE06 or 0xFE0A) only works from the 68k Emulator.
Code:
#include <ConditionalMacros.h>
#include <MacTypes.h>
#if !TARGET_OS_MAC || !TARGET_CPU_68K || TARGET_RT_MAC_CFM
#error needs to be compiled for non-cfm 68k
#endif
#define EMMUOpTrap 0xFE06 //do VM op, cause a line F instruction if it fails
#define EMMUOpCCR 0xFE0A //do VM op, set CCR.Z if it fails
#pragma parameter __D0 KernelVMDispatch(__D0, __A0, __A1, __D1)
EXTERN_API(UInt32)
KernelVMDispatch(UInt32 routine_selector, UInt32 param1, UInt32 param2, UInt32 param3) ONEWORDINLINE(EMMUOpTrap);
#pragma parameter __D0 VMGetPTEntryGivenPage(__A0)
EXTERN_API(UInt32)
VMGetPTEntryGivenPage(UInt32 page) TWOWORDINLINE(0x7000+19, EMMUOpTrap);
#pragma parameter VMSetPTEntryGivenPage(__A0, __A1)
EXTERN_API(void)
VMSetPTEntryGivenPage(UInt32 pte, UInt32 page) TWOWORDINLINE(0x7000+20, EMMUOpTrap);
#pragma parameter VMMakePageWriteThrough(__A0)
EXTERN_API(void)
VMMakePageWriteThrough(UInt32 page) TWOWORDINLINE(0x7000+24, EMMUOpTrap);
#pragma parameter VMMakePageCacheable(__A0)
EXTERN_API(void)
VMMakePageCacheable(UInt32 page) TWOWORDINLINE(0x7000+17, EMMUOpTrap);
#pragma parameter VMMakePageNonCacheable(__A0)
EXTERN_API(void)
VMMakePageNonCacheable(UInt32 page) TWOWORDINLINE(0x7000+18, EMMUOpTrap);
void MakePageQuietReadOnly(void * address)
{
UInt32 page = ((UInt32)address) >> 12;
UInt32 pte = VMGetPTEntryGivenPage(page);
pte |= 4;//set write-protect bit
VMSetPTEntryGivenPage(pte, page);
VMMakePageWriteThrough(page);
//quiet = write-protect + write-through
}
void MakePageReadWrite(void * address)
{
UInt32 page = ((UInt32)address) >> 12;
UInt32 pte = VMGetPTEntryGivenPage(page);
pte &= ~4;//clear write-protect bit
VMSetPTEntryGivenPage(pte, page);
VMMakePageCacheable(page);
}