TABLE OF CONTENTS Enforcer LawBreaker Move4K Enforcer Enforcer NAME Enforcer V37 - An advanced version of Enforcer - Requires V37 SYNOPSIS Enforcer - A tool to watch for illegal memory accesses FUNCTION Enforcer will use the MMU in the advanced 680x0 processors to set up MMU tables to watch for illegal accesses to memory such as the low-page and non-existent pages. To use, run Enforcer (plus any options you may wish) If you wish to detach, just use RUN >NIL: NIL: Enforcer QUIET should be placed into the startup-sequence right after SetPatch. TINY/S - This tells Enforcer to output a minimal hit. The output is basically the first line of the Enforcer hit. (see below) SMALL/S - This tells Enforcer to output the hit line, the USP: line, and the Name: line. (This means that no register or stack display will be output) SHOWPC/S - This tells Enforcer to also output the two lines that contain the memory area around the PC where the hit happened. Useful for disassembly. This option will not do anything if QUIET, SMALL or TINY output modes are selected. STACKLINES/K/N - This lets you pick the number of lines of stack backtrace to display. The default is 2. If set to 0, no stack backtrace will be displayed. There is no enforced limit on the number of lines. DEADLY/S - This makes Enforcer be a bit more nasty. Normally, when an illegal read happens, Enforcer returns 0 as the result of this read. With this option, Enforcer will return $ABADFEED as the read data. This option can make programs with Enforcer hits cause even more hits. FSPACE/S - This option will make the special $00F00000 address space available for writing to. This is useful for those people with $00F00000 boards. Mainly Commodore internal development work -- should only be used in that enviroment. VERBOSE/S - This option will make Enforcer display information as to the mapping of the I/O boards and other technical information. This information maybe useful in specialized debugging. PARALLEL/S - This option will make Enforcer use the parallel port hardware rather than the serial port for output. RAWIO/S - This option will make Enforcer stuff the hit report (special IO) into an internal buffer and then from the main Enforcer process output the results via the RawPutChar() EXEC debugging LVO. Since the output happens on the Enforcer task it is possible for a hit that ends in a system crash to not be able to be reported. This option is here such that tools which can redirect debugging output can redirect the Enforcer output too. FILE/K - This option will make Enforcer output the hit report (special IO) but to a file insted of sending it to the hardware directly or using the RAWIO LVO. A good example of such a file is CON:0/0/640/100/HIT/AUTO/WAIT. Another thing that can be done is to have a program sit on a named pipe and have Enforcer output to it. This program can then do whatever it feels like with the Enforcer hits. (Such as decode them, etc.) *NOTE* It is not a good idea to have Enforcer hits go to a file on a disk as if the system crashes during/after the Enforcer hit, the disk may become corrupt. STDIO/S - This option will make Enforcer output the hit report (special IO) to STDOUT. This option only works from the CLI as it requires STDOUT. It is best used with redirection or pipes. BUFFERSIZE/K/N - This lets you set Enforcer's internal output buffer for the special I/O options. This option is only valid with the RAWIO, FILE, or STDIO options. The minimum setting is 8000. The default is 8000. Having the right amount of buffer is rather important for the special I/O modes. The reason is due to the fact that no operating system calls can be made from a bus error. Thus, in the special I/O mode, Enforcer must store the output in this buffer and, via some special magic, wake up the Enforcer task to read the buffer and write it out as needed. However, if a task is in Forbid() or Disable() when the Enforcer hit happens, the Enforcer task will not be able to output the results of the hit. This buffer lets a number of hits happen even if the Enforcer task was unable to do the I/O. If the number of hits that happen before the I/O was able to run gets too large, the last few hits will either be cut off completely or contain only partial information. INTRO/K - This optional introduction string will be output at the start of every Enforcer hit. For example: INTRO="*NBad Program!" The default is no string. PRIORITY/K/N - This lets you set Enforcer's I/O task priority. The default for this priority is 99. In some special cases, you may wish to adjust this. It is, however, recommended that if you are using one of the special I/O options (RAWIO, FILE, or STDIO) that you keep the priority rather high. The value is not checked for valid priority range. ON/S - Mainly for completeness. If not specified, it is assumed you want to turn ON Enforcer. QUIT=OFF/S - Tells Enforcer to turn off. Enforcer can also be stopped by sending a CTRL-C to its process. RESULTS When running, a set of MMU tables that map addresses that are not in the system's address map as invalid such that any access to them will cause an access fault. Enforcer will then display this fact and generate a diagnostic message as to what the illegal access was. The first memory page (the one starting at location 0) is also marked as invalid as many programming errors cause invalid access to these addresses. These addresses are completely off limits to applications. When an access violation happens, a report such as the following is output. WORD-WRITE to 00000000 data=4444 PC: 07895CA4 USP: 078D692C SR: 0000 SW: 0729 (U0)(-)(-) TCB: 078A2690 Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 07848E1C 00009C40 078A30B4 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 078E9048 00011DA8 DEADBEEF PC-8: AAAA1111 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C40000 PC *: 522E0127 201433FC 400000DF F09A522E 012611C7 00CE4EAE FF7642B8 0324532E Name: "New_Shell" CLI: "lawbreaker" Hunk 0000 Offset 0000007C LONG-READ from AAAA4444 PC: 07895CA8 USP: 078D692C SR: 0015 SW: 0749 (U0)(F)(-) TCB: 078A2690 Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 07848E1C 00009C40 078A30B4 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 078E9048 00011DA8 DEADBEEF PC-8: 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C40000 522E0127 PC *: 201433FC 400000DF F09A522E 012611C7 00CE4EAE FF7642B8 0324532E 01266C08 Name: "New_Shell" CLI: "lawbreaker" Hunk 0000 Offset 00000080 Here is a breakdown of what these reports are saying: The first line of each report describes the access violation and where it happened from. In the case of a WRITE, the data that was being written will be displayed as well. If an instruction mode access caused the fault, there will be an (INST) in the line. The first line may also contain the BUS ERROR message. This will be displayed when an address that is valid in the system lists causes a physical bus fault during the access. This usually will happen with plug-in cards or when a hardware problem causes some form of system fault. Watch out, if this does show up, your system may be unstable and/or unreliable. The second line (starts USP:) displays the USER stack pointer (USP), the status register (SR:), the special status word (SW:). It then displays the supervisor/user state and the interrupt level. This will be from (U0) to (U7) or (S0) to (S7) (S=Supervisor) Next is the forbid state (F=forbid, -=not) and the disable state (D or -) of the task that was running when the access fault took place. Finally, the task control block address is displayed (TCB:) The next two lines contain the data and address register dumps from when the access fault happened. Note that A7 is not listed here. It is the stack pointer and is listed as USP: in the line above. Then come the lines of stack backtrace. These lines show the data on the stack. If the stack is in invalid memory, Enforcer will display a message to that fact. Next, optionally, comes the data around the program counter when the access fault happened. The first line (PC-8:) is the 8 long-words before the program counter. The second line starts at the program counter and goes for 8 long words. The last line displays the name of the task that was running when the access fault took place. It the task was a CLI, it will display the name of the CLI command that was running. If the access fault was found to have happened within the seglist of a loaded program, the segment number and the offset from the start of the segment will be displayed. (Note that this works for any LoadSeg()'ed process) WARNING Enforcer is for software testing. In this role it is vital. Software that causes Enforcer hits may well not be able to run on newer hardware. (Enforcer hits of high addresses on systems not running Enforcer but with a 68040 will most likely crash the system) Future systems and hardware will make this even more improtant. The system can NOT survive software that causes Enforcer hits. However, Enforcer is NOT a system protector. As a side effect, it may well keep a system from crashing when Enforcer hits happen, but it may just as well make the software crash earlier. Enforcer is mainly a development and testing tool. Enforcer causes no ill effects if no software causes an Enforcer hit. NOTES This new Enforcer is a completely new program. Bryce Nesbitt came up with the original "Enforcer" that has been instrumental to the improvement in the quality of software on the Amiga. The Amiga users and developers owe him a great deal for this. Thank you Bryce! This Enforcer came about due to a number of needs. These included the need for more output options and better performance. It also marks the removal of all kludges that were in the older versions. Also, some future plans required some of these changes... In addition, the complete redesign was needed in order to also support the 68040. The internal design of Enforcer is now set up such that CPU/MMU specific code can be cleanly accessed from the general house keeping aspect of the code. The MMU bus error handling is, however, 100% CPU specific. Since AbsExecBase is in low memory, reads of this address are slower with Enforcer running. Caching AbsExecBase locally is highly recommended since it is in CHIP memory and on systems with FAST memory, it will be faster to access the local cached value. (In addition to the performance increase when running Enforcer) Note that doing many reads of location 4 will hurt interrupt performance. When the Amiga produces an ALERT, EXEC places some magic numbers into some special locations in low memory. The exact pattern changes between versions of the operating system. Enforcer will patch the EXEC function ColdReboot() in an attempt to "get out of the way" when someone tries to reboot the system. Enforcer will clean up as much as possible the MMU tables and then call the original LVO. When Enforcer is asked to quit, it will check to make sure it can remove itself from this LVO. If it can not, it will not quit at that time. If run from the shell, it will display a message saying that it tried but could not exit. Enforcer will continue to be active and you can try later to deactivate it. 68020 NOTES The 68020 does not have a built-in MMU but has a co-processor feature that lets an external MMU be connected. Enforcer MMU code is designed for use with 68851 MMU. This is the some-what 68030 compatible MMU by Motorola. Enforcer uses the same code for both the 68030 and the 68020/68851. For this reason, 68020/68851 users should see the 68030 NOTES section. 68030 NOTES The 68030 uses cycle/instruction continuation and will supply the data on reads and ignore writes during an access fault rather than let the real bus cycle happen. This means that on a fault caused by MMU tables, no bus cycle to the fault address will be generated. (For those of you with analyzers) In some cases, the 68030 will have advanced the Program Counter past the instruction by the time the access fault happens. This is usually only on WRITE faults. For this reason, the PC may either point at the instruction that caused the fault or just after the instruction that caused the fault. (Which could mean that it is pointing to the middle of the instruction that caused the fault.) Note that there is a processor called 68EC030. This processor has a disabled or defective MMU. However, it may function well enough for Enforcer to think it has a fully functional MMU and thus Enforcer will attempt to run. However, even if it looks like the MMU is functioning, it is not fully operational and thus may cause strange system activity and even crashes. Do not assume that Enforcer is safe to use on 68EC030 systems. 68040 NOTES Enforcer, on the 68040, *requires* that the 68040.library be installed and it requires an MMU 68040 CPU. The 68EC040 does not have a MMU. The 68LC040 does have an MMU and is supported. Enforcer will work best in a system with the 68040.library 37.10 or better but it does know how to deal with systems that do not have that version. Due to the design of the 68040, Enforcer is required to do a number of things differently. For example, the MMU page size can only be either 8K or 4K. This means that to protect the low 1K of memory, Enforcer will end up having to mark the first 4K of memory as invalid and emulate the access to the 3K of that memory that is valid. For this reason Enforcer moves a number of possible structures from the first 4K of memory to higher addresses. This means that the system will continue to run at a reasonable speed. The first time Enforcer is run it may need to allocate memory for these structures that it will move. Enforcer can never return this memory to the system. In addition to the fact that the 68040 MMU table size is different, the address fault handling is also different. Namely, the 68040 can only rerun the cycle and not continue it like the 68030. This means that on a 68040, the page must be made available first and then made unavailable. Make this work, Enforcer will switch the instruction that caused the error into trace mode and let it run with a special MMU setup. When the trace exception comes in, the MMU is set up back to the way it was. Enforcer does its best to keep debuggers working. Note, however, that the interrupt level during a trace of a READ will end up being set to 7. This is to prevent interrupts from changing the order of trace/MMU table execution. The level will be restored to the original state before continuing. Since T0 mode tracing is also supported, there are also some changes in the way it operates. T0 mode tracing is defined, on the 68040, to cause a trace whenever the instruction pipeline needed to be reloaded. While on the 68020/030 processors this was normally only for the branch instructions, in the 68040 this includes a large number of other instructions. (Including NOP!) Anyway, if an Enforcer hit happens while in T0 tracing mode, the trace will happen even on instructions that normally would not cause a T0 mode trace. Since this may actually help in debugging and because it was not possible to do anything else, this method of operation is deemed acceptable. Another issue with the 68040 is that WRITE faults happen *after* the instruction has executed. (Except for MOVEM) In fact, it is common for the 68040 to execute one ot more extra instructions before the WRITE fault is executed. This design makes the 68040 much faster, but it also makes the Program Counter value that Enforcer can report for the fault much less likely to be pointing to the instruction that caused it. The worst cases are sequences such as a write fault followed by a branch instruction. In these cases, the branch is usually already executed before the write fault happens and thus the PC will be pointing to the target of the branch. There is nothing that can be done within Enforcer to help out here. You will just need to be aware of this and deal with it as best as possible. Along with the above issue, is the fact that since a write fault may be delayed, a read fault may happen before the write fault shows up. Internally, enforcer does not do special processing for these and they will not show up. Since another hit was happening anyway, it is felt that it is best to just not report the hit. Along the same lines, the hit generated from a MOVEM instruction may only show as a single hit rather than 1 for each register moved. On the Amiga, MOVE16 is not supported 100%. Causing an Enforcer hit with a MOVE16 will cause major problems and maybe cause Enforcer or your task to lock. Since MOVE16 is not supported, this is not a major issue. Just watch out if you are using this 68040 instruction. (Also, watch out for the 68040 CPU bug with MOVE16) The functions CachePreDMA(), CachePostDMA(), and CacheControl() are patched when the 68040 MMU is turned on by Enforcer. These functions are patched such the issues with DMA and the 68040 COPYBACK data caches are addressed. The 68040.library normally deals with this, however since Enforcer turns on the MMU, the method of dealing with it in the 68040.library will not work. For this reason, Enforcer will patch these and implement the required fix for when the MMU is on. When Enforcer is asked to exit, it will check if it can remove itself from these functions. If it can not, it will ignore the request to exit. If Enforcer was run from the CLI, it will print a message saying that it can not exit when the attempt is made. SEE ALSO "A master's secrets are only as good as the master's ability to explain them to others." - Michael Sinz BUGS None? LawBreaker LawBreaker NAME LawBreaker - A quicky test of Enforcer SYNOPSIS This is a quick test of Enforcer and its reporting abilities. FUNCTION This program is used to make sure that Enforcer is correctly installed and operating. LawBreaker works from either the CLI or Workbench. It will try to read and write certain memory areas that will cause an Enforcer hit or four. INPUTS Just run it... RESULTS When running Enforcer, you will see some output from Enforcer. Output on a 68030 machine would look something like this: WORD-WRITE to 00000000 data=0000 PC: 0783AC6A USP: 078CAAEC SR: 0004 SW: 0729 (U0)(-)(-) TCB: 078AADF8 Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 0784991C 00009C40 078AB81C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 00000000 006B54E0 ABADCAFE PC-8: AAAA1111 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C00000 PC *: 522E0127 201433FC 400000DF F09A522E 012611C1 01004EAE FF7621C0 0104532E Name: "Shell" CLI: "NewTest:LawBreaker" Hunk 0000 Offset 0000007A LONG-READ from AAAA4444 PC: 0783AC6E USP: 078CAAEC SR: 0015 SW: 0749 (U0)(F)(-) TCB: 078AADF8 Data: DDDD0000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 0784991C 00009C40 078AB81C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 00000000 006B54E0 ABADCAFE PC-8: 247CAAAA 2222267C AAAA3333 287CAAAA 44442A7C AAAA5555 31C00000 522E0127 PC *: 201433FC 400000DF F09A522E 012611C1 01004EAE FF7621C0 0104532E 01266C08 Name: "Shell" CLI: "NewTest:LawBreaker" Hunk 0000 Offset 0000007E BYTE-WRITE to 00000100 data=11 PC: 0783AC80 USP: 078CAAEC SR: 0010 SW: 0711 (U0)(F)(D) TCB: 078AADF8 Data: 00000000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 0784991C 00009C40 078AB81C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 00000000 006B54E0 ABADCAFE PC-8: 2A7CAAAA 555531C0 0000522E 01272014 33FC4000 00DFF09A 522E0126 11C10100 PC *: 4EAEFF76 21C00104 532E0126 6C0833FC C00000DF F09A201F 66024E75 22404EEE Name: "Shell" CLI: "NewTest:LawBreaker" Hunk 0000 Offset 00000090 LONG-WRITE to 00000104 data=00000000 PC: 0783AC88 USP: 078CAAEC SR: 0014 SW: 0709 (U0)(-)(D) TCB: 078AADF8 Data: 00000000 DDDD1111 DDDD2222 DDDD3333 DDDD4444 DDDD5555 DDDD6666 DDDD7777 Addr: AAAA0000 AAAA1111 AAAA2222 AAAA3333 AAAA4444 AAAA5555 07800804 -------- Stck: 00000000 0784991C 00009C40 078AB81C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB Stck: BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 00000000 006B54E0 ABADCAFE PC-8: 0000522E 01272014 33FC4000 00DFF09A 522E0126 11C10100 4EAEFF76 21C00104 PC *: 532E0126 6C0833FC C00000DF F09A201F 66024E75 22404EEE FE860024 5645523A Name: "Shell" CLI: "NewTest:LawBreaker" Hunk 0000 Offset 00000098 NOTES If enforcer is not running, the program should not cause the system to crash. It will, however, write to certain areas of low memory. Also, it will cause read access of some addresses that may not exist. This may cause bus faults. SEE ALSO "Quantum Physics: The Dreams that Stuff is made of." - Michael Sinz BUGS There are 4 known Enforcer hits in this code, however, they will not be fixed. ;^) Move4K Move4K NAME Move4K - Moves as much out of the lower 4K of RAM as possible SYNOPSIS On 68040 systems, as much of the lower 4K of CHIP RAM is removed from system use. FUNCTION On 68040 systems the MMU page sizes are 4K and 8K. Enforcer uses the 4K page size. Since watching for hits of low memory is a vital part of Enforcer, this means that the first 4K of RAM will be marked invalid. On current systems, only the first 1K of RAM is invalid and thus 3K of RAM in that first 4K will end up needing to be emulated in Enforcer. In order to reduce the overhead that this causes (and the major performance loss) this program will try to move as much from that first 4K as possible and make any of the free memory within the first 4K inaccessible. Enforcer itself also has this logic, but it may be useful to be able to run this program as the first program in the Startup-Sequence (*AFTER* SetPatch) to try to limit the number of things that may use the lower 4K of RAM. INPUTS Just run it... Can be run from CLI or Workbench RESULTS Any available memory in the lower 4K of CHIP RAM is removed plus a special graphics buffer is moved if it needs to be. After running this program you may have a bit less CHIP RAM than before. You can run this program as many times as you wish since it only moves things if it needs to. NOTES This program will do nothing on systems without a 68040. It does not, however, check for the MMU and thus it will move the lower 4K even if the CPU is not able to run Enforcer. V39 of the operating system already does have the lowest MMU page empty and thus this program will effectively do nothing under V39. SEE ALSO "Eloquence is vehement simplicity" BUGS None.