The sequence to move over to the Linux trap tables from
the firmware ones needs to be more air tight. It turns
out that to be %100 safe we do need to be able to translate
OBP mappings in our TLB miss handlers early.
In order not to eat up a lot of kernel image memory with
static page tables, just use the translations array in
the OBP TLB miss handlers. That solves the bulk of the
problem.
Furthermore, to make sure the OBP TLB miss path will work
even before the fixed MMU globals are loaded, explicitly
load %g1 to TLB_SFSR at the beginning of the i-TLB and
d-TLB miss handlers.
To ease the OBP TLB miss walking of the prom_trans[] array,
we sort it then delete all of the non-OBP entries in there
(for example, there are entries for the kernel image itself
which we're not interested in at all).
We also save about 32K of kernel image size with this change.
Not a bad side effect :-)
There are still some reasons why trampoline.S can't use the
setup_trap_table() yet. The most noteworthy are:
1) OBP boots secondary processors with non-bias'd stack for
some reason. This is easily fixed by using a small bootup
stack in the kernel image explicitly for this purpose.
2) Doing a firmware call via the normal C call prom_set_trap_table()
goes through the whole OBP enter/exit sequence that saves and
restores OBP and Linux kernel state in the MMUs. This path
unfortunately does a "flush %g6" while loading up the OBP locked
TLB entries for the firmware call.
If we setup the %g6 in the trampoline.S code properly, that
is in the PAGE_OFFSET linear mapping, but we're not on the
kernel trap table yet so those addresses won't translate properly.
One idea is to do a by-hand firmware call like we do in the
early bootup code and elsewhere here in trampoline.S But this
fails as well, as aparently the secondary processors are not
booted with OBP's special locked TLB entries loaded. These
are necessary for the firwmare to processes TLB misses correctly
up until the point where we take over the trap table.
This does need to be resolved at some point.
Signed-off-by: David S. Miller <davem@davemloft.net>
The trick is that we do the kernel linear mapping TLB miss starting
with an instruction sequence like this:
ba,pt %xcc, kvmap_load
xor %g2, %g4, %g5
succeeded by an instruction sequence which performs a full page table
walk starting at swapper_pg_dir.
We first take over the trap table from the firmware. Then, using this
constant PTE generation for the linear mapping area above, we build
the kernel page tables for the linear mapping.
After this is setup, we patch that branch above into a "nop", which
will cause TLB misses to fall through to the full page table walk.
With this, the page unmapping for CONFIG_DEBUG_PAGEALLOC is trivial.
Signed-off-by: David S. Miller <davem@davemloft.net>
This was kind of ugly, and actually buggy. The bug was that
we didn't handle a machine with memory starting > 4GB. If
the 'prompmd' was allocated in physical memory > 4GB we'd
croak because the obp_iaddr_patch and obp_daddr_patch things
only supported a 32-bit physical address.
So fix this by just loading the appropriate values from two
variables in the kernel image, which is locked into the TLB
and thus accesses to them can't cause a recursive TLB miss.
Signed-off-by: David S. Miller <davem@davemloft.net>