Skip to content

Commit

Permalink
[SPARC64]: Rewrite bootup sequence.
Browse files Browse the repository at this point in the history
Instead of all of this cpu-specific code to remap the kernel
to the correct location, use portable firmware calls to do
this instead.

What we do now is the following in position independant
assembler:

	chosen_node = prom_finddevice("/chosen");
	prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu");
	vaddr = 4MB_ALIGN(current_text_addr());
	prom_translate(vaddr, &paddr_high, &paddr_low, &mode);
	prom_boot_mapping_mode = mode;
	prom_boot_mapping_phys_high = paddr_high;
	prom_boot_mapping_phys_low = paddr_low;
	prom_map(-1, 8 * 1024 * 1024, KERNBASE, paddr_low);

and that replaces the massive amount of by-hand TLB probing and
programming we used to do here.

The new code should also handle properly the case where the kernel
is mapped at the correct address already (think: future kexec
support).

Consequently, the bulk of remap_kernel() dies as does the entirety
of arch/sparc64/prom/map.S

We try to share some strings in the PROM library with the ones used
at bootup, and while we're here mark input strings to oplib.h routines
with "const" when appropriate.

There are many more simplifications now possible.  For one thing, we
can consolidate the two copies we now have of a lot of cpu setup code
sitting in head.S and trampoline.S.

This is a significant step towards CONFIG_DEBUG_PAGEALLOC support.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 23, 2005
1 parent 40fd353 commit bff06d5
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 644 deletions.
549 changes: 159 additions & 390 deletions arch/sparc64/kernel/head.S

Large diffs are not rendered by default.

15 changes: 1 addition & 14 deletions arch/sparc64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,20 +536,7 @@ void __init setup_arch(char **cmdline_p)
}
pfn_base = phys_base >> PAGE_SHIFT;

switch (tlb_type) {
default:
case spitfire:
kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent());
kern_base &= _PAGE_PADDR_SF;
break;

case cheetah:
case cheetah_plus:
kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
kern_base &= _PAGE_PADDR;
break;
};

kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;

if (!root_flags)
Expand Down
16 changes: 8 additions & 8 deletions arch/sparc64/kernel/trampoline.S
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ startup_continue:
sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
Expand Down Expand Up @@ -156,8 +156,8 @@ startup_continue:
sethi %hi(itlb_load), %g2
or %g2, %lo(itlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
Expand Down Expand Up @@ -190,8 +190,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
Expand Down Expand Up @@ -228,8 +228,8 @@ do_dtlb:
sethi %hi(dtlb_load), %g2
or %g2, %lo(dtlb_load), %g2
stx %g2, [%sp + 2047 + 128 + 0x18]
sethi %hi(mmu_ihandle_cache), %g2
lduw [%g2 + %lo(mmu_ihandle_cache)], %g2
sethi %hi(prom_mmu_ihandle_cache), %g2
lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
stx %g2, [%sp + 2047 + 128 + 0x20]
sethi %hi(KERNBASE + 0x400000), %g2
stx %g2, [%sp + 2047 + 128 + 0x28]
Expand Down
98 changes: 5 additions & 93 deletions arch/sparc64/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,108 +505,20 @@ static int read_obp_translations(void)
return n;
}

static inline void early_spitfire_errata32(void)
{
/* Spitfire Errata #32 workaround */
/* NOTE: Using plain zero for the context value is
* correct here, we are not using the Linux trap
* tables yet so we should not use the special
* UltraSPARC-III+ page size encodings yet.
*/
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
"flush %%g6"
: /* No outputs */
: "r" (0), "r" (PRIMARY_CONTEXT),
"i" (ASI_DMMU));
}

static void lock_remap_func_page(unsigned long phys_page)
{
unsigned long tte_data = (phys_page | pgprot_val(PAGE_KERNEL));

if (tlb_type == spitfire) {
/* Lock this into i/d tlb entry 59 */
__asm__ __volatile__(
"stxa %%g0, [%2] %3\n\t"
"stxa %0, [%1] %4\n\t"
"membar #Sync\n\t"
"flush %%g6\n\t"
"stxa %%g0, [%2] %5\n\t"
"stxa %0, [%1] %6\n\t"
"membar #Sync\n\t"
"flush %%g6"
: /* no outputs */
: "r" (tte_data), "r" (59 << 3), "r" (TLB_TAG_ACCESS),
"i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
"i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
: "memory");
} else {
/* Lock this into i/d tlb-0 entry 11 */
__asm__ __volatile__(
"stxa %%g0, [%2] %3\n\t"
"stxa %0, [%1] %4\n\t"
"membar #Sync\n\t"
"flush %%g6\n\t"
"stxa %%g0, [%2] %5\n\t"
"stxa %0, [%1] %6\n\t"
"membar #Sync\n\t"
"flush %%g6"
: /* no outputs */
: "r" (tte_data), "r" ((0 << 16) | (11 << 3)),
"r" (TLB_TAG_ACCESS), "i" (ASI_DMMU),
"i" (ASI_DTLB_DATA_ACCESS), "i" (ASI_IMMU),
"i" (ASI_ITLB_DATA_ACCESS)
: "memory");
}
}

static void remap_kernel(void)
{
unsigned long phys_page, tte_vaddr, tte_data;
void (*remap_func)(unsigned long, unsigned long, int);
int tlb_ent = sparc64_highest_locked_tlbent();

early_spitfire_errata32();

if (tlb_type == spitfire)
phys_page = spitfire_get_dtlb_data(tlb_ent);
else
phys_page = cheetah_get_ldtlb_data(tlb_ent);

phys_page &= _PAGE_PADDR;
phys_page += ((unsigned long)&prom_boot_page -
(unsigned long)KERNBASE);

lock_remap_func_page(phys_page);

tte_vaddr = (unsigned long) KERNBASE;

early_spitfire_errata32();

if (tlb_type == spitfire)
tte_data = spitfire_get_dtlb_data(tlb_ent);
else
tte_data = cheetah_get_ldtlb_data(tlb_ent);
phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
tte_data = (phys_page | (_PAGE_VALID | _PAGE_SZ4MB |
_PAGE_CP | _PAGE_CV | _PAGE_P |
_PAGE_L | _PAGE_W));

kern_locked_tte_data = tte_data;

remap_func = (void *) ((unsigned long) &prom_remap -
(unsigned long) &prom_boot_page);

early_spitfire_errata32();

phys_page = tte_data & _PAGE_PADDR;
remap_func(phys_page, KERNBASE, prom_get_mmu_ihandle());
if (bigkernel)
remap_func(phys_page + 0x400000,
KERNBASE + 0x400000,
prom_get_mmu_ihandle());

/* Flush out that temporary mapping. */
spitfire_flush_dtlb_nucleus_page(0x0);
spitfire_flush_itlb_nucleus_page(0x0);

/* Now lock us back into the TLBs via OBP. */
/* Now lock us into the TLBs via OBP. */
prom_dtlb_load(tlb_ent, tte_data, tte_vaddr);
prom_itlb_load(tlb_ent, tte_data, tte_vaddr);
if (bigkernel) {
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc64/prom/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ EXTRA_AFLAGS := -ansi
EXTRA_CFLAGS := -Werror

lib-y := bootstr.o devops.o init.o memory.o misc.o \
tree.o console.o printf.o p1275.o map.o cif.o
tree.o console.o printf.o p1275.o cif.o
2 changes: 1 addition & 1 deletion arch/sparc64/prom/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ prom_putchar(char c)
}

void
prom_puts(char *s, int len)
prom_puts(const char *s, int len)
{
p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
P1275_INOUT(3,1),
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc64/prom/devops.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Returns 0 on failure.
*/
int
prom_devopen(char *dstr)
prom_devopen(const char *dstr)
{
return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
P1275_INOUT(1,1),
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc64/prom/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
if((prom_root_node == 0) || (prom_root_node == -1))
prom_halt();

prom_chosen_node = prom_finddevice("/chosen");
prom_chosen_node = prom_finddevice(prom_chosen_path);
if (!prom_chosen_node || prom_chosen_node == -1)
prom_halt();

Expand Down
72 changes: 0 additions & 72 deletions arch/sparc64/prom/map.S

This file was deleted.

34 changes: 16 additions & 18 deletions arch/sparc64/prom/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
#include <asm/system.h>

/* Reset and reboot the machine with the command 'bcommand'. */
void prom_reboot(char *bcommand)
void prom_reboot(const char *bcommand)
{
p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_INOUT(1, 0), bcommand);
}

/* Forth evaluate the expression contained in 'fstring'. */
void prom_feval(char *fstring)
void prom_feval(const char *fstring)
{
if (!fstring || fstring[0] == 0)
return;
Expand Down Expand Up @@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba)
p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
}

int mmu_ihandle_cache = 0;

int prom_get_mmu_ihandle(void)
{
int node, ret;

if (mmu_ihandle_cache != 0)
return mmu_ihandle_cache;
if (prom_mmu_ihandle_cache != 0)
return prom_mmu_ihandle_cache;

node = prom_finddevice("/chosen");
ret = prom_getint(node, "mmu");
node = prom_finddevice(prom_chosen_path);
ret = prom_getint(node, prom_mmu_name);
if (ret == -1 || ret == 0)
mmu_ihandle_cache = -1;
prom_mmu_ihandle_cache = -1;
else
mmu_ihandle_cache = ret;
prom_mmu_ihandle_cache = ret;

return ret;
}
Expand Down Expand Up @@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index,
unsigned long tte_data,
unsigned long vaddr)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
Expand All @@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index,
unsigned long tte_data,
unsigned long vaddr)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
Expand All @@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index,
int prom_map(int mode, unsigned long size,
unsigned long vaddr, unsigned long paddr)
{
int ret = p1275_cmd("call-method",
int ret = p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(3, P1275_ARG_IN_64B) |
P1275_ARG(4, P1275_ARG_IN_64B) |
P1275_ARG(6, P1275_ARG_IN_64B) |
P1275_INOUT(7, 1)),
"map",
prom_map_name,
prom_get_mmu_ihandle(),
mode,
size,
Expand All @@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size,

void prom_unmap(unsigned long size, unsigned long vaddr)
{
p1275_cmd("call-method",
p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(2, P1275_ARG_IN_64B) |
P1275_ARG(3, P1275_ARG_IN_64B) |
P1275_INOUT(4, 0)),
"unmap",
prom_unmap_name,
prom_get_mmu_ihandle(),
size,
vaddr);
Expand All @@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr)
/* Set aside physical memory which is not touched or modified
* across soft resets.
*/
unsigned long prom_retain(char *name,
unsigned long prom_retain(const char *name,
unsigned long pa_low, unsigned long pa_high,
long size, long align)
{
Expand Down Expand Up @@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code,
unsigned long phys_addr,
char *buf, int buflen)
{
return p1275_cmd("call-method",
return p1275_cmd(prom_callmethod_name,
(P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_ARG(3, P1275_ARG_OUT_BUF) |
P1275_ARG(6, P1275_ARG_IN_64B) |
Expand Down
Loading

0 comments on commit bff06d5

Please sign in to comment.