August 24, 2025

Sun 3 bootrom souce - the Sun 3/80 - black magic with the MMU

We used the following process to gain access to the IDPROM region in the NVRAM. At the time we had no real clue about what was going on, but now let's take a closer look.
^t fef04000
Virtual Addr 0xFEF04000 is mapped to Physical Addr 0x64000000.
TIA Entry = 0xFFA500, TIB Entry = 0xFFB80A.
PTE = 0x64000049
Then we do:
m a fedfa000
ffa500
.
m b fedfa000
ffb80a
.
p fedfa000
64000049
.
o fedfa7d8
The ^t command examines the setup for virtual address 0xfef04000. This is the virtual address that is currently mapped to the NVRAM.

The basic idea in the above scheme is to set up virtual address 0xfedf_a000 to also be mapped to the NVRAM, then we will be able to use it to monkey with the IDPROM address range.

We just copy the TIA and TIB register values from the 0xfef0_4000 mapping to the mapping for 0xfedfa000. It is somewhat interesting to look at the original values before we overwrite them:

m a fedfa000
TIA Map FEDFA000 [00FFA000] = 00FFA500? .
m b fedfa000
TIB Map FEDFA000 [00FFA500] = 00000000? .
p fedfa000
PageMap FEDFA000 [00000000] = 00000000? .
The original TIA value would have been fine to just leave alone.
The original TIB value was 0, so this an attempt to access this address would have yielded a bus error.

Note also the access via "p" to the page map. This is just the name Sun uses for the level 3 TIC table. The original value here was also 0, which would yield a bus error. I am sort of surprised there is a page table entry at all, given that the B table had a zero value. It is likely that the rom set up a linear page table for the whole range 0xfe000000 to 0xffffffff. Maybe, that is 32M and would involve 4096 entries, which is not unthinkable.

Why was this virtual address chosen? It is as good as many others that could have been used. The fact that it mapped to invalid pages indicates that it is a good candidate. We haven't yet learned anything about these values that get placed in the registers. Actually the TIA value (which didn't get changed) just points to the TIB register.

What about the PTE (page map entry)

We install the value 0x64000049.

The physical address is 0x64000000. The low 13 bits are the offset in the page, so we might expect those bits to be free in the PTE and used for other purposes.

We have to do some guessing here. The long format of the page descriptor is 64 bits with status in the upper 32 bits and the page address in the lower 32 bits. Let's suppose the ROM is (for the sake of the "p" command), putting the status bits in the unused low 13 bits.

0x49 = 0100  1001
 0 - unused
 1 - CI = inhibit caching
 0 - unused
 0 - M = indicates a modified page
 1 - U = indicates access
 0 - WP = write protect
 01 -  DT = valid page descriptor

Use this trick to look at the MMU tables

m a fedfa000
ffa500
.
m b fedfa000
ffb80a
.
p fedfa000
00ffa049
.
Actually we can skip the first "m a" since that value is there already.
Here is the "A" map:
v fedfa000 fedfa4ff l
FEDFA000:	7FFFFC0A 00FFA400 00000000 00000000 	..|...$.........
FEDFA010:	00000000 00000000 00000000 00000000 	................
FEDFA020:	00000000 00000000 00000000 00000000 	................
....
....
FEDFA3D0:	00000000 00000000 00000000 00000000 	................
FEDFA3E0:	00000000 00000000 00000000 00000000 	................
FEDFA3F0:	00000000 00000000 7FFFFC0A 00FFA500 	..........|...%.
Now we get to see the verbatim "A" table from 000 to 3ff. Remember the virtual addresses shown above are for the alternate setup we just made. These are really at 0x00ffa000.

The table is full of zeros except for the first and last entry. Each entry is 8 bytes. All zeros is an invalid entry.

Look at our first 8 byte entry (these are long format, as per the TC bits).

7FFFFC0A 00FFA400
This is a long format table descriptor, as follows
7FFF - 16 bit limit field
FC0A - 16 bit status field
00FFA400 - 32 bit table address
And look at those status bits:
FC0A = 1111 1100 0000 1010
 1111 = always these ones
 1100 = always "110", last bit is S
 0000 = always these zeros
 1010 = U, WP, DT(2 bits)

S = 0 would say "supervisor only"
U = 1 is an access bit
WP = 0 is write protect
DT = 10 says the next table is 4 byte descriptors.
Next we get the first of two "B" maps. This is the one for the first 32M (00000000 to 01ffffff).
FEDFA400:	00FFA60A 00FFA70A 00FFA80A 00FFA902 	..&...'...(...).
FEDFA410:	00FFAA02 00FFAB02 00FFAC02 00FFAD02 	..*...+...,...-.
FEDFA420:	00FFAE02 00FFAF02 00FFB002 00FFB102 	....../...0...1.
FEDFA430:	00FFB202 00FFB302 00FFB402 00FFB502 	..2...3...4...5.
FEDFA440:	00000000 00000000 00000000 00000000 	................
FEDFA450:	00000000 00000000 00000000 00000000 	................
FEDFA460:	00000000 00000000 00000000 00000000 	................
FEDFA470:	00000000 00000000 00000000 00000000 	................
FEDFA480:	00000000 00000000 00000000 00000000 	................
FEDFA490:	00000000 00000000 00000000 00000000 	................
FEDFA4A0:	00000000 00000000 00000000 00000000 	................
FEDFA4B0:	00000000 00000000 00000000 00000000 	................
FEDFA4C0:	00000000 00000000 00000000 00000000 	................
FEDFA4D0:	00000000 00000000 00000000 00000000 	................
FEDFA4E0:	00000000 00000000 00000000 00000000 	................
FEDFA4F0:	00000000 00000000 00000000 00000000 	................
We now have handy smaller 4 byte descriptors. They are short format table descriptors. The first is like so:
00FFA60A
It is all address, except the last 4 bits.
Here these are: U, WP, DT (2 bits)
1 = U = access
0 = WP
10 = DT = pointer to another 4 byte (short format) table.
A quick note. Our virtual address is 7:6:6:13.
The A table has 128 entries of 8 bytes each, and takes up 1024 bytes (0-3ff).
Each B table has 64 entries of 4 bytes each, and takes up 256 bytes (0-ff).
Likewise, each C table has 64 entries of 4 bytes each, and takes up 256 bytes (0-ff).

We have two valid entries in our A table.

The second A table entry

Our second A table entry is:
7FFFFC0A 00FFA500
Here is the B table it points to. This is for addresses fe00_0000 to ffff_ffff
v fedfa500 fedfa5ff l
FEDFA500:	00000000 00000000 00000000 00000000 	................
FEDFA510:	00000000 00000000 00000000 00000000 	................
FEDFA520:	00000000 00000000 00000000 00000000 	................
FEDFA530:	00000000 00000000 00000000 00000000 	................
FEDFA540:	00000000 00000000 00000000 00000000 	................
FEDFA550:	00000000 00000000 00000000 00000000 	................
FEDFA560:	00000000 00000000 00000000 00FFB80A 	..............8.
FEDFA570:	00FFB602 00FFB702 00FFB80A 00FFB90A 	..6...7...8...9.
FEDFA580:	00000000 00000000 00000000 00000000 	................
FEDFA590:	00000000 00000000 00000000 00000000 	................
FEDFA5A0:	00000000 00000000 00000000 00000000 	................
FEDFA5B0:	00000000 00000000 00000000 00000000 	................
FEDFA5C0:	00000000 00000000 00000000 00000000 	................
FEDFA5D0:	00000000 00000000 00000000 00000000 	................
FEDFA5E0:	00000000 00000000 00000000 00000000 	................
FEDFA5F0:	00000000 00000000 00FFBA0A 00FFBB02 	..........:...;.
Again, it is filled mostly with zero (invalid) entries. Note that each entry in the B table points to 64 entries in the C table.

Note: One special thing. The entry FFB80A appears twice. This means the same physical address is aliased to two virtual addresses. The first of these two looks like the entry we patched in to do this trick.

The first C table is at A600 (offset 600 in our 8K window) and the last C table is at BB00 (offset 1b00 in our 8K windows.

An 8K window can show us from offset 0 to 1fff, so we can see the whole set of MMU tables without setting up a second window!

Here is the first C table (for RAM):

v fedfa600 fedfa6ff l
FEDFA600:	00000049 00002059 00004059 00006041 	...I...Y..@Y..`A
FEDFA610:	00008041 0000A041 0000C041 0000E041 	...A...A..@A..`A
FEDFA620:	00010041 00012041 00014041 00016041 	...A...A..@A..`A
FEDFA630:	00018041 0001A041 0001C041 0001E041 	...A...A..@A..`A
FEDFA640:	00020041 00022041 00024041 00026041 	...A...A..@A..`A
FEDFA650:	00028041 0002A041 0002C041 0002E041 	...A...A..@A..`A
FEDFA660:	00030041 00032041 00034041 00036041 	...A...A..@A..`A
FEDFA670:	00038041 0003A041 0003C041 0003E041 	...A...A..@A..`A
FEDFA680:	00040041 00042041 00044041 00046041 	...A...A..@A..`A
FEDFA690:	00048041 0004A041 0004C041 0004E041 	...A...A..@A..`A
FEDFA6A0:	00050041 00052041 00054041 00056041 	...A...A..@A..`A
FEDFA6B0:	00058041 0005A041 0005C041 0005E041 	...A...A..@A..`A
FEDFA6C0:	00060041 00062041 00064041 00066041 	...A...A..@A..`A
FEDFA6D0:	00068041 0006A041 0006C041 0006E041 	...A...A..@A..`A
FEDFA6E0:	00070041 00072041 00074041 00076041 	...A...A..@A..`A
FEDFA6F0:	00078041 0007A041 0007C041 0007E041 	...A...A..@A..`A
...
...
FEDFB500:	00780041 00782041 00784041 00786041 	.x.A.x.A.x@A.x`A
FEDFB510:	00788041 0078A041 0078C041 0078E041 	.x.A.x.A.x@A.x`A
FEDFB520:	00790041 00792041 00794041 00796041 	.y.A.y.A.y@A.y`A
FEDFB530:	00798041 0079A041 0079C041 0079E041 	.y.A.y.A.y@A.y`A
FEDFB540:	007A0041 007A2041 007A4041 007A6041 	.z.A.z.A.z@A.z`A
FEDFB550:	007A8041 007AA041 007AC041 007AE041 	.z.A.z.A.z@A.z`A
FEDFB560:	007B0041 007B2041 007B4041 007B6041 	.{.A.{.A.{@A.{`A
FEDFB570:	007B8041 007BA041 007BC041 007BE041 	.{.A.{.A.{@A.{`A
FEDFB580:	007C0041 007C2041 007C4041 007C6041 	.|.A.|.A.|@A.|`A
FEDFB590:	007C8041 007CA041 007CC041 007CE041 	.|.A.|.A.|@A.|`A
FEDFB5A0:	007D0041 007D2041 007D4041 007D6041 	.}.A.}.A.}@A.}`A
FEDFB5B0:	007D8041 007DA041 007DC041 007DE041 	.}.A.}.A.}@A.}`A
FEDFB5C0:	007E0041 007E2041 007E4041 007E6041 	.~.A.~.A.~@A.~`A
FEDFB5D0:	007E8041 007EA041 007EC041 007EE041 	.~.A.~.A.~@A.~`A
FEDFB5E0:	007F0041 007F2041 007F4041 007F6041 	...A...A..@A..`A
FEDFB5F0:	007F8041 007FA041 007FC041 007FE041 	...A...A..@A..`A
Here, the low 8 bits are status, and the low 2 bits are DT. When DT is 01 (as it is here) we have a page descriptor. The status bits are 0, CI, 0, M -- U, WP, DT (2 bits).

In every entry the CI bit is set to inhibit caching. This is sort of surprising for ram, but it no doubt simplifies things like the network driver that does DMA and would require explicit cache handling. We have 8K pages, so the addresses increment by 0x2000.

Here are the rest of the page (C) tables for IO:

v fedfb600 fedfb6ff l
FEDFB600:	00000000 00000000 00000000 00000000 	................
FEDFB610:	00000000 00000000 00000000 00000000 	................
FEDFB620:	00000000 00000000 00000000 00000000 	................
FEDFB630:	00000000 00000000 00000000 00000000 	................
FEDFB640:	00000000 00000000 00000000 00000000 	................
FEDFB650:	00000000 00000000 00000000 00000000 	................
FEDFB660:	00000000 00000000 00000000 00000000 	................
FEDFB670:	00000000 00000000 00000000 00000000 	................
FEDFB680:	00000000 00000000 00000000 00000000 	................
FEDFB690:	00000000 00000000 00000000 00000000 	................
FEDFB6A0:	00000000 00000000 00000000 00000000 	................
FEDFB6B0:	00000000 00000000 00000000 00000000 	................
FEDFB6C0:	00000000 00000000 00000000 00000000 	................
FEDFB6D0:	00000000 00000000 00000000 00000000 	................
FEDFB6E0:	00000000 00000000 00000000 00000000 	................
FEDFB6F0:	00000000 00000000 00000000 00000000 	................
v fedfb700 fedfb8ff l
FEDFB700:	00000000 00000000 00000000 00000000 	................
FEDFB710:	00000000 00000000 00000000 00000000 	................
FEDFB720:	00000000 00000000 00000000 00000000 	................
FEDFB730:	00000000 00000000 00000000 00000000 	................
FEDFB740:	00000000 00000000 00000000 00000000 	................
FEDFB750:	00000000 00000000 00000000 00000000 	................
FEDFB760:	00000000 00000000 00000000 00000000 	................
FEDFB770:	00000000 00000000 00000000 00000000 	................
FEDFB780:	00000000 00000000 00000000 00000000 	................
FEDFB790:	00000000 00000000 00000000 00000000 	................
FEDFB7A0:	00000000 00000000 00000000 00000000 	................
FEDFB7B0:	00000000 00000000 00000000 00000000 	................
FEDFB7C0:	00000000 00000000 00000000 00000000 	................
FEDFB7D0:	00000000 00000000 00000000 00000000 	................
FEDFB7E0:	00000000 00000000 00000000 00000000 	................
FEDFB7F0:	00000000 00000000 00000000 00000000 	................

FEDFB800:	62000059 62002059 64000049 64000839 	b..Yb..Yd..Id..9
FEDFB810:	61001059 61001459 00000000 65002041 	a..Ya..Y....e..A
FEDFB820:	00000000 66002041 00000000 61000059 	....f..A....a..Y
FEDFB830:	61000449 61000859 61000C41 50300049 	a..Ia..Ya..AP0.I
FEDFB840:	00000000 00000000 00000000 00000000 	................
FEDFB850:	00000000 00000000 00000000 00000000 	................
FEDFB860:	00000000 00000000 00000000 00000000 	................
FEDFB870:	00000000 00000000 00000000 00000000 	................
FEDFB880:	00000000 00000000 00000000 00000000 	................
FEDFB890:	00000000 00000000 00000000 00000000 	................
FEDFB8A0:	00000000 00000000 00000000 00000000 	................
FEDFB8B0:	00000000 00000000 00000000 00000000 	................
FEDFB8C0:	00FFE059 00000000 00FFA059 60000059 	..`Y.......Y`..Y
FEDFB8D0:	00000000 00000000 00000000 00000000 	................
FEDFB8E0:	00000000 00FFC059 00FFA041 00000000 	......@Y...A....
FEDFB8F0:	00000000 00FFA049 00000000 00000000 	.......I........
v fedfb900 fedfbbff l
FEDFB900:	6F000059 65002059 66000059 66000059 	o..Ye..Yf..Yf..Y
FEDFB910:	66000059 66000059 00000000 00000000 	f..Yf..Y........
FEDFB920:	00000000 00000000 00000000 00000000 	................
FEDFB930:	00000000 00000000 00000000 00000000 	................
FEDFB940:	00000000 00000000 00000000 00000000 	................
FEDFB950:	00000000 00000000 00000000 00000000 	................
FEDFB960:	00000000 00000000 00000000 00000000 	................
FEDFB970:	00000000 00000000 00000000 00000000 	................
FEDFB980:	00000000 00000000 00000000 00000000 	................
FEDFB990:	00000000 00000000 00000000 00000000 	................
FEDFB9A0:	00000000 00000000 00000000 00000000 	................
FEDFB9B0:	00000000 00000000 00000000 00000000 	................
FEDFB9C0:	63000009 63002009 63004009 63006009 	c...c...c.@.c.`.
FEDFB9D0:	63008001 6300A009 6300C001 6300E009 	c...c...c.@.c.`.
FEDFB9E0:	63010009 63012009 63014009 63016009 	c...c...c.@.c.`.
FEDFB9F0:	63018001 6301A001 6301C001 6301E001 	c...c...c.@.c.`.

FEDFBA00:	00FF8041 00FF6059 00FF4059 00E06041 	...A..`Y..@Y.``A
FEDFBA10:	00E08041 00E0A041 00E0C041 00E0E041 	.`.A.`.A.`@A.``A
FEDFBA20:	00E10041 00E12041 00E14041 00E16041 	.a.A.a.A.a@A.a`A
FEDFBA30:	00E18041 00E1A041 00E1C041 00E1E041 	.a.A.a.A.a@A.a`A
FEDFBA40:	00E20041 00E22041 00E24041 00E26041 	.b.A.b.A.b@A.b`A
FEDFBA50:	00E28041 00E2A041 00E2C041 00E2E041 	.b.A.b.A.b@A.b`A
FEDFBA60:	00E30041 00E32041 00E34041 00E36041 	.c.A.c.A.c@A.c`A
FEDFBA70:	00E38041 00E3A041 00E3C041 00E3E041 	.c.A.c.A.c@A.c`A
FEDFBA80:	00E40041 00E42041 00E44041 00E46041 	.d.A.d.A.d@A.d`A
FEDFBA90:	00E48041 00E4A041 00E4C041 00E4E041 	.d.A.d.A.d@A.d`A
FEDFBAA0:	00E50041 00E52041 00E54041 00E56041 	.e.A.e.A.e@A.e`A
FEDFBAB0:	00E58041 00E5A041 00E5C041 00E5E041 	.e.A.e.A.e@A.e`A
FEDFBAC0:	00E60041 00E62041 00E64041 00E66041 	.f.A.f.A.f@A.f`A
FEDFBAD0:	00E68041 00E6A041 00E6C041 00E6E041 	.f.A.f.A.f@A.f`A
FEDFBAE0:	00E70041 00E72041 00E74041 00E76041 	.g.A.g.A.g@A.g`A
FEDFBAF0:	00E78041 00E7A041 00E7C041 00E7E041 	.g.A.g.A.g@A.g`A
FEDFBB00:	00E80041 00E82041 00E84041 00E86041 	.h.A.h.A.h@A.h`A
FEDFBB10:	00E88041 00E8A041 00E8C041 00E8E041 	.h.A.h.A.h@A.h`A
FEDFBB20:	00E90041 00E92041 00E94041 00E96041 	.i.A.i.A.i@A.i`A
FEDFBB30:	00E98041 00E9A041 00E9C041 00E9E041 	.i.A.i.A.i@A.i`A
FEDFBB40:	00EA0041 00EA2041 00EA4041 00EA6041 	.j.A.j.A.j@A.j`A
FEDFBB50:	00EA8041 00EAA041 00EAC041 00EAE041 	.j.A.j.A.j@A.j`A
FEDFBB60:	00EB0041 00EB2041 00EB4041 00EB6041 	.k.A.k.A.k@A.k`A
FEDFBB70:	00EB8041 00EBA041 00EBC041 00EBE041 	.k.A.k.A.k@A.k`A
FEDFBB80:	00EC0041 00EC2041 00EC4041 00EC6041 	.l.A.l.A.l@A.l`A
FEDFBB90:	00EC8041 00ECA041 00ECC041 00ECE041 	.l.A.l.A.l@A.l`A
FEDFBBA0:	00ED0041 00ED2041 00ED4041 00ED6041 	.m.A.m.A.m@A.m`A
FEDFBBB0:	00ED8041 00EDA041 00EDC041 00EDE041 	.m.A.m.A.m@A.m`A
FEDFBBC0:	00EE0041 00EE2041 00EE4041 00EE6041 	.n.A.n.A.n@A.n`A
FEDFBBD0:	00EE8041 00EEA041 00EEC041 00EEE041 	.n.A.n.A.n@A.n`A
FEDFBBE0:	00EF0041 00EF2041 00EF4041 00EF6041 	.o.A.o.A.o@A.o`A
FEDFBBF0:	00EF8041 00EFA041 00EFC041 00FFC041 	.o.A.o.A.o@A..@A
There is certainly some strange business in those IO pages!

Remember that we monkeyed with the mapping to get access to this, making changes to:

m a fedfa000 -- nothing needed to change
ffa500
.
m b fedfa000 -- change the entry at 00FFa500 to FFb800
ffb80a
.
p fedfa000
00ffa049

A summary (sort of)

For ram, we have the one A table descriptor, which could map 32M of ram. The B table it points to has 16 valid descriptors, each mapping 1/2M, so we map 8M. These each point to tables of 64 page descriptors which are located at A600 through B500. These map 0 to 0, 0x2000 to 0x2000 and so forth to give a 1:1 mapping for 8M of memory.

For IO, we have the one A table descriptor at the end of the virtual address space, mapping addresses 0xFE00_0000 to 0xFFff_ffff. The B table at A500 is sparse with only 7 valid entries out of 64. There are 5 entries that map:

TIB Map FED80000 [00FFA500] = 00FFB80A?
TIB Map FEE00000 [00FFA500] = 00FFB602?
TIB Map FEE80000 [00FFA500] = 00FFB702? 
TIB Map FEF00000 [00FFA500] = 00FFB80A?
TIB Map FEF80000 [00FFA500] = 00FFB90A?

And there are 2 at the very end that map:

TIB Map FFF00000 [00FFA500] = 00FFBA0A?
TIB Map FFF80000 [00FFA500] = 00FFBB02?

Each of these points to 64 page table entries, so there are 448 page table entries involved.

There is plenty of tricky business in those 448 entries.

We need a nice virtual to physical map for the upper addresses

So I generated one. See this page:

The way Sun uses (used) the '030 MMU

SunOS had 8K pages back when they used their own custom built MMU, so they stuck with them with the 68030. The A and B maps just direct the mapping to the C map, which Sun calls the page map or PTE array. As you have seen if you have followed the above, this is not a contiguous map -- which is advantageous as far as avoiding huge maps in memory.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org