YaK:: $A000 bug in OS9Boot for coco3, NitrOS-9 Level 2 | [Changes] [Calendar] [Search] [Index] [PhotoTags] |
With your browser, view the text file PROBLEM-Nov6, linked just above.
Using Control-F, find the two places where the word "problem" occurs.
Just above it, you will see
# - ffff 02 = #1457162 C_POKE 01ffa5 06 (was 02) # w ffa5 06 # --- IOPAGE WRITE: addr ffa5 flags 2206 data 6 C_POKE 01ffa6 3e (was 03) # w ffa6 3e # --- IOPAGE WRITE: addr ffa6 flags 63e data 3e |
There is one "# r" line for each read cycle, and one "# w" for each write cycle, and "# - ffff" for an extra non-memory cycle. Numbers after "#" like "#1457167" are CPU cycle numbers, and are a unique way to find things in the file.
(For each write cycle, there is also a C_POKE line before the "# w" line, and if it is in the $FFxx page, there is a "# --- IOPAGE WRITE:" line after it, for extra verbosity. You can ignore those.)
What is important is that 0x06 and 0x3E are written to addresses $FFA5 and $FFA6. These remap the $[AB]xxx and $[CD]xxx MMU blocks for the kernel mode (task 0).
Now look between the two "problem" words and you see an LDU and a STU instruction:
# @ f2bf ee = #1457167 T0(0 3e 3e 1 4 6 3e 3f):07f2bf :: "krn.0edf349400"+02bf l@ ldu ,x++ get the source bytes # r f2c0 81 = #1457168 # r f2c1 ef = #1457169 # - ffff 02 = #1457170 # - ffff 02 = #1457171 # - ffff 02 = #1457172 # r a2f4 ff =Y #1457173 # r a2f5 00 = #1457174 # @ f2c1 ef = #1457175 T0(0 3e 3e 1 4 6 3e 3f):07f2c1 :: "krn.0edf349400"+02c1 stu ,y++ and save them in the destination # r f2c2 a1 = #1457176 # r f2c3 5a = #1457177 # - ffff 02 = #1457178 # - ffff 02 = #1457179 # - ffff 02 = #1457180 C_POKE 00c2f2 ff (was 80) # w a2f2 ff C_POKE 00c2f3 00 (was 02) # w a2f3 00 problem |
At the end of the LDU, it's reading from addresses $A2F4 and $A2F5.
At the end of the STU, it's writing to addresses $A2F2 and $A2F3.
Notice this is an a loop -- there is soon a " bn l@ branch if not done" and the LDU and STU are repeated.
That's how I noticed the problem. The source and destination buffers overlap! The source and destination addresses are only different by 2, but the buffers are longer than 2 bytes, but the buffers are 12 bytes long (see cycle #1457165). That's probably not what was intended.
What is happening is the destination is hardwired to use MMU Block with offset 5:
# @ f2ba fd = #1457159 T0(0 3e 3e 1 4 2 3 3f):07f2ba :: "krn.0edf349400"+02ba std >DAT.Regs+5 map in the blocks |
And what is the source? It's the system stack for the user process.
# @ db77 9e = #1456884 T0(0 3e 3e 1 4 2 3 3f):007b77 :: "ioman.0a2512cd6d"+05b4 ldx <D.Proc Get current process dsc ptr # r db78 50 = #1456885 # - ffff 02 = #1456886 # r 0050 a1 =Y #1456887 # r 0051 00 = #1456888 |
See that "a1" then "00" get loaded into X from D.Proc. So the Proc structure for the current process is at $A100, and is $200 bytes long. At the end of it is the system stack for the process, around $A2F4.
After the buffer copy is done, and the MMU is restored, this is executed:
# @ f2cf 35 = #1457314 T0(0 3e 3e 1 4 2 3 3f):07f2cf :: "krn.0edf349400"+02cf puls cc,x,y,u,pc restore & return # r f2d0 f1 = #1457315 # - ffff 02 = #1457316 # - ffff 02 = #1457317 # r a2eb 84 = #1457318 # r a2ec a1 = #1457319 # r a2ed 00 = #1457320 # r a2ee a6 = #1457321 # r a2ef 40 = #1457322 # r a2f0 a2 = #1457323 # r a2f1 f4 = #1457324 # r a2f2 f2 = #1457325 # r a2f3 76 = #1457326 # r a2f4 84 = #1457327 |
You see that the system stack that it is pulling from is in the $A2F2 range, there at the end of that instruction.
So the code that hardwired using MMU Block Offset 5 ($[AB]xxx) for the destination was assuming that no Proc Structure could be that high in Task0 RAM. If your kernel modules are small and few enough, that assumption is wrong.
However I'm confident that my conclusion is accurate, that this code cannot work unless proc structures are always below $A000.
(last modified 2025-01-04) [Login] |