aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-09 02:52:44 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 01:12:03 -0800
commitd82ace7dc4073b090a55b9740700e32b9a9ae302 (patch)
treed5aa8e10664b05bbfe31eacf95e2066c03cab102 /arch/sparc64/kernel
parent1d2f1f90a1e004b0c1b8a73ed4394a93f09104b3 (diff)
[SPARC64]: Detect sun4v early in boot process.
We look for "SUNW,sun4v" in the 'compatible' property of the root OBP device tree node. Protect every %ver register access, to make sure it is not touched on sun4v, as %ver is hyperprivileged there. Lock kernel TLB entries using hypervisor calls instead of calls into OBP. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/cpu.c6
-rw-r--r--arch/sparc64/kernel/head.S96
-rw-r--r--arch/sparc64/kernel/irq.c78
-rw-r--r--arch/sparc64/kernel/setup.c9
-rw-r--r--arch/sparc64/kernel/trampoline.S62
-rw-r--r--arch/sparc64/kernel/us2e_cpufreq.c3
-rw-r--r--arch/sparc64/kernel/us3_cpufreq.c3
7 files changed, 204 insertions, 53 deletions
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
index 00eed88ef2e..c7a4fb39702 100644
--- a/arch/sparc64/kernel/cpu.c
+++ b/arch/sparc64/kernel/cpu.c
@@ -71,6 +71,12 @@ void __init cpu_probe(void)
unsigned long ver, fpu_vers, manuf, impl, fprs;
int i;
+ if (tlb_type == hypervisor) {
+ sparc_cpu_type = "UltraSparc T1 (Niagara)";
+ sparc_fpu_type = "UltraSparc T1 integrated FPU";
+ return;
+ }
+
fprs = fprs_read();
fprs_write(FPRS_FEF);
__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]"
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 01980014aea..d048f0dfd42 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -95,12 +95,17 @@ sparc64_boot:
wrpr %g1, 0x0, %pstate
ba,a,pt %xcc, 1f
- .globl prom_finddev_name, prom_chosen_path
- .globl prom_getprop_name, prom_mmu_name
- .globl prom_callmethod_name, prom_translate_name
+ .globl prom_finddev_name, prom_chosen_path, prom_root_node
+ .globl prom_getprop_name, prom_mmu_name, prom_peer_name
+ .globl prom_callmethod_name, prom_translate_name, prom_root_compatible
.globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
.globl prom_boot_mapped_pc, prom_boot_mapping_mode
.globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
+ .globl is_sun4v
+prom_peer_name:
+ .asciz "peer"
+prom_compatible_name:
+ .asciz "compatible"
prom_finddev_name:
.asciz "finddevice"
prom_chosen_path:
@@ -117,7 +122,13 @@ prom_map_name:
.asciz "map"
prom_unmap_name:
.asciz "unmap"
+prom_sun4v_name:
+ .asciz "SUNW,sun4v"
.align 4
+prom_root_compatible:
+ .skip 64
+prom_root_node:
+ .word 0
prom_mmu_ihandle_cache:
.word 0
prom_boot_mapped_pc:
@@ -129,8 +140,54 @@ prom_boot_mapping_phys_high:
.xword 0
prom_boot_mapping_phys_low:
.xword 0
+is_sun4v:
+ .word 0
1:
rd %pc, %l0
+
+ mov (1b - prom_peer_name), %l1
+ sub %l0, %l1, %l1
+ mov 0, %l2
+
+ /* prom_root_node = prom_peer(0) */
+ stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "peer"
+ mov 1, %l3
+ stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
+ stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
+ stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, 0
+ stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
+ call %l7
+ add %sp, (2047 + 128), %o0 ! argument array
+
+ ldx [%sp + 2047 + 128 + 0x20], %l4 ! prom root node
+ mov (1b - prom_root_node), %l1
+ sub %l0, %l1, %l1
+ stw %l4, [%l1]
+
+ mov (1b - prom_getprop_name), %l1
+ mov (1b - prom_compatible_name), %l2
+ mov (1b - prom_root_compatible), %l5
+ sub %l0, %l1, %l1
+ sub %l0, %l2, %l2
+ sub %l0, %l5, %l5
+
+ /* prom_getproperty(prom_root_node, "compatible",
+ * &prom_root_compatible, 64)
+ */
+ stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
+ mov 4, %l3
+ stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
+ mov 1, %l3
+ stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
+ stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, prom_root_node
+ stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible"
+ stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_root_compatible
+ mov 64, %l3
+ stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size
+ stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
+ call %l7
+ add %sp, (2047 + 128), %o0 ! argument array
+
mov (1b - prom_finddev_name), %l1
mov (1b - prom_chosen_path), %l2
mov (1b - prom_boot_mapped_pc), %l3
@@ -239,6 +296,27 @@ prom_boot_mapping_phys_low:
add %sp, (192 + 128), %sp
sparc64_boot_after_remap:
+ sethi %hi(prom_root_compatible), %g1
+ or %g1, %lo(prom_root_compatible), %g1
+ sethi %hi(prom_sun4v_name), %g7
+ or %g7, %lo(prom_sun4v_name), %g7
+ mov 10, %g3
+1: ldub [%g7], %g2
+ ldub [%g1], %g4
+ cmp %g2, %g4
+ bne,pn %icc, 2f
+ add %g7, 1, %g7
+ subcc %g3, 1, %g3
+ bne,pt %xcc, 1b
+ add %g1, 1, %g1
+
+ sethi %hi(is_sun4v), %g1
+ or %g1, %lo(is_sun4v), %g1
+ mov 1, %g7
+ stw %g7, [%g1]
+
+2:
+ BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
ba,pt %xcc, spitfire_boot
@@ -323,14 +401,12 @@ sun4u_init:
membar #Sync
- BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
+ BRANCH_IF_SUN4V(g1, niagara_tlb_fixup)
+ BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
ba,pt %xcc, spitfire_tlb_fixup
nop
- /* XXX Nothing branches to here yet, when %ver register indicates
- * XXX Niagara we should do this.
- */
niagara_tlb_fixup:
mov 3, %g2 /* Set TLB type to hypervisor. */
sethi %hi(tlb_type), %g1
@@ -346,6 +422,9 @@ niagara_tlb_fixup:
call hypervisor_patch_cachetlbops
nop
+ ba,pt %xcc, tlb_fixup_done
+ nop
+
cheetah_tlb_fixup:
mov 2, %g2 /* Set TLB type to cheetah+. */
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
@@ -464,7 +543,8 @@ setup_trap_table:
sllx %o2, 32, %o2
wr %o2, 0, %tick_cmpr
- BRANCH_IF_ANY_CHEETAH(o2,o3,1f)
+ BRANCH_IF_SUN4V(o2, 1f)
+ BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
ba,pt %xcc, 2f
nop
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index c80d2531ec4..1f6455503f2 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -150,47 +150,53 @@ void enable_irq(unsigned int irq)
preempt_disable();
- if (tlb_type == cheetah || tlb_type == cheetah_plus) {
- unsigned long ver;
-
- __asm__ ("rdpr %%ver, %0" : "=r" (ver));
- if ((ver >> 32) == __JALAPENO_ID ||
- (ver >> 32) == __SERRANO_ID) {
- /* We set it to our JBUS ID. */
+ if (tlb_type == hypervisor) {
+ /* XXX SUN4V: implement me... XXX */
+ } else {
+ if (tlb_type == cheetah || tlb_type == cheetah_plus) {
+ unsigned long ver;
+
+ __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+ if ((ver >> 32) == __JALAPENO_ID ||
+ (ver >> 32) == __SERRANO_ID) {
+ /* We set it to our JBUS ID. */
+ __asm__ __volatile__("ldxa [%%g0] %1, %0"
+ : "=r" (tid)
+ : "i" (ASI_JBUS_CONFIG));
+ tid = ((tid & (0x1fUL<<17)) << 9);
+ tid &= IMAP_TID_JBUS;
+ } else {
+ /* We set it to our Safari AID. */
+ __asm__ __volatile__("ldxa [%%g0] %1, %0"
+ : "=r" (tid)
+ : "i"(ASI_SAFARI_CONFIG));
+ tid = ((tid & (0x3ffUL<<17)) << 9);
+ tid &= IMAP_AID_SAFARI;
+ }
+ } else if (this_is_starfire == 0) {
+ /* We set it to our UPA MID. */
__asm__ __volatile__("ldxa [%%g0] %1, %0"
: "=r" (tid)
- : "i" (ASI_JBUS_CONFIG));
- tid = ((tid & (0x1fUL<<17)) << 9);
- tid &= IMAP_TID_JBUS;
+ : "i" (ASI_UPA_CONFIG));
+ tid = ((tid & UPA_CONFIG_MID) << 9);
+ tid &= IMAP_TID_UPA;
} else {
- /* We set it to our Safari AID. */
- __asm__ __volatile__("ldxa [%%g0] %1, %0"
- : "=r" (tid)
- : "i" (ASI_SAFARI_CONFIG));
- tid = ((tid & (0x3ffUL<<17)) << 9);
- tid &= IMAP_AID_SAFARI;
+ tid = (starfire_translate(imap,
+ smp_processor_id()) << 26);
+ tid &= IMAP_TID_UPA;
}
- } else if (this_is_starfire == 0) {
- /* We set it to our UPA MID. */
- __asm__ __volatile__("ldxa [%%g0] %1, %0"
- : "=r" (tid)
- : "i" (ASI_UPA_CONFIG));
- tid = ((tid & UPA_CONFIG_MID) << 9);
- tid &= IMAP_TID_UPA;
- } else {
- tid = (starfire_translate(imap, smp_processor_id()) << 26);
- tid &= IMAP_TID_UPA;
- }
- /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
- * of this SYSIO's preconfigured IGN in the SYSIO Control
- * Register, the hardware just mirrors that value here.
- * However for Graphics and UPA Slave devices the full
- * IMAP_INR field can be set by the programmer here.
- *
- * Things like FFB can now be handled via the new IRQ mechanism.
- */
- upa_writel(tid | IMAP_VALID, imap);
+ /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
+ * of this SYSIO's preconfigured IGN in the SYSIO Control
+ * Register, the hardware just mirrors that value here.
+ * However for Graphics and UPA Slave devices the full
+ * IMAP_INR field can be set by the programmer here.
+ *
+ * Things like FFB can now be handled via the new IRQ
+ * mechanism.
+ */
+ upa_writel(tid | IMAP_VALID, imap);
+ }
preempt_enable();
}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 2d64320d3a4..7f02c8f71df 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -504,9 +504,12 @@ static void __init per_cpu_patch(void)
if (tlb_type == spitfire && !this_is_starfire)
return;
- __asm__ ("rdpr %%ver, %0" : "=r" (ver));
- is_jbus = ((ver >> 32) == __JALAPENO_ID ||
- (ver >> 32) == __SERRANO_ID);
+ is_jbus = 0;
+ if (tlb_type != hypervisor) {
+ __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+ is_jbus = ((ver >> 32) == __JALAPENO_ID ||
+ (ver >> 32) == __SERRANO_ID);
+ }
p = &__cpuid_patch;
while (p < &__cpuid_patch_end) {
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index fbf844f84a4..ffa8b79632c 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -16,6 +16,7 @@
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/mmu.h>
+#include <asm/hypervisor.h>
.data
.align 8
@@ -34,8 +35,9 @@ dtlb_load:
sparc64_cpu_startup:
flushw
- BRANCH_IF_CHEETAH_BASE(g1,g5,cheetah_startup)
- BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g5,cheetah_plus_startup)
+ BRANCH_IF_SUN4V(g1, niagara_startup)
+ BRANCH_IF_CHEETAH_BASE(g1, g5, cheetah_startup)
+ BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1, g5, cheetah_plus_startup)
ba,pt %xcc, spitfire_startup
nop
@@ -70,7 +72,9 @@ cheetah_generic_startup:
stxa %g0, [%g3] ASI_DMMU
stxa %g0, [%g3] ASI_IMMU
membar #Sync
+ /* fallthru */
+niagara_startup:
/* Disable STICK_INT interrupts. */
sethi %hi(0x80000000), %g5
sllx %g5, 32, %g5
@@ -91,6 +95,8 @@ startup_continue:
sllx %g2, 32, %g2
wr %g2, 0, %tick_cmpr
+ BRANCH_IF_SUN4V(g1, niagara_lock_tlb)
+
/* Call OBP by hand to lock KERNBASE into i/d tlbs.
* We lock 2 consequetive entries if we are 'bigkernel'.
*/
@@ -142,8 +148,7 @@ startup_continue:
sethi %hi(bigkernel), %g2
lduw [%g2 + %lo(bigkernel)], %g2
- cmp %g2, 0
- be,pt %icc, do_dtlb
+ brz,pt %g2, do_dtlb
nop
sethi %hi(call_method), %g2
@@ -214,8 +219,7 @@ do_dtlb:
sethi %hi(bigkernel), %g2
lduw [%g2 + %lo(bigkernel)], %g2
- cmp %g2, 0
- be,pt %icc, do_unlock
+ brz,pt %g2, do_unlock
nop
sethi %hi(call_method), %g2
@@ -257,6 +261,52 @@ do_unlock:
stb %g0, [%g2 + %lo(prom_entry_lock)]
membar #StoreStore | #StoreLoad
+ ba,pt %xcc, after_lock_tlb
+ nop
+
+niagara_lock_tlb:
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o0
+ sethi %hi(KERNBASE), %o1
+ clr %o2
+ sethi %hi(kern_locked_tte_data), %o3
+ ldx [%o3 + %lo(kern_locked_tte_data)], %o3
+ mov HV_MMU_IMMU, %o4
+ ta HV_FAST_TRAP
+
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o0
+ sethi %hi(KERNBASE), %o1
+ clr %o2
+ sethi %hi(kern_locked_tte_data), %o3
+ ldx [%o3 + %lo(kern_locked_tte_data)], %o3
+ mov HV_MMU_DMMU, %o4
+ ta HV_FAST_TRAP
+
+ sethi %hi(bigkernel), %g2
+ lduw [%g2 + %lo(bigkernel)], %g2
+ brz,pt %g2, after_lock_tlb
+ nop
+
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o0
+ sethi %hi(KERNBASE + 0x400000), %o1
+ clr %o2
+ sethi %hi(kern_locked_tte_data), %o3
+ ldx [%o3 + %lo(kern_locked_tte_data)], %o3
+ sethi %hi(0x400000), %o4
+ add %o3, %o4, %o3
+ mov HV_MMU_IMMU, %o4
+ ta HV_FAST_TRAP
+
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o0
+ sethi %hi(KERNBASE + 0x400000), %o1
+ clr %o2
+ sethi %hi(kern_locked_tte_data), %o3
+ ldx [%o3 + %lo(kern_locked_tte_data)], %o3
+ sethi %hi(0x400000), %o4
+ add %o3, %o4, %o3
+ mov HV_MMU_DMMU, %o4
+ ta HV_FAST_TRAP
+
+after_lock_tlb:
mov %l1, %sp
flushw
diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c
index b35dc8dc995..669fb83dd4f 100644
--- a/arch/sparc64/kernel/us2e_cpufreq.c
+++ b/arch/sparc64/kernel/us2e_cpufreq.c
@@ -346,6 +346,9 @@ static int __init us2e_freq_init(void)
unsigned long manuf, impl, ver;
int ret;
+ if (tlb_type != spitfire)
+ return -ENODEV;
+
__asm__("rdpr %%ver, %0" : "=r" (ver));
manuf = ((ver >> 48) & 0xffff);
impl = ((ver >> 32) & 0xffff);
diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
index 6d1f9a3c464..a912c45bdc0 100644
--- a/arch/sparc64/kernel/us3_cpufreq.c
+++ b/arch/sparc64/kernel/us3_cpufreq.c
@@ -203,6 +203,9 @@ static int __init us3_freq_init(void)
unsigned long manuf, impl, ver;
int ret;
+ if (tlb_type != cheetah && tlb_type != cheetah_plus)
+ return -ENODEV;
+
__asm__("rdpr %%ver, %0" : "=r" (ver));
manuf = ((ver >> 48) & 0xffff);
impl = ((ver >> 32) & 0xffff);