Commit d82ace7d authored by David S. Miller's avatar David S. Miller
Browse files

[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: default avatarDavid S. Miller <davem@davemloft.net>
parent 1d2f1f90
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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]"
+88 −8
Original line number Diff line number Diff line
@@ -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_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,6 +543,7 @@ setup_trap_table:
	sllx	%o2, 32, %o2
	wr	%o2, 0, %tick_cmpr

	BRANCH_IF_SUN4V(o2, 1f)
	BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)

	ba,pt	%xcc, 2f
+42 −36
Original line number Diff line number Diff line
@@ -150,6 +150,9 @@ void enable_irq(unsigned int irq)

	preempt_disable();

	if (tlb_type == hypervisor) {
		/* XXX SUN4V: implement me... XXX */
	} else {
		if (tlb_type == cheetah || tlb_type == cheetah_plus) {
			unsigned long ver;

@@ -178,7 +181,8 @@ void enable_irq(unsigned int irq)
			tid = ((tid & UPA_CONFIG_MID) << 9);
			tid &= IMAP_TID_UPA;
		} else {
		tid = (starfire_translate(imap, smp_processor_id()) << 26);
			tid = (starfire_translate(imap,
						  smp_processor_id()) << 26);
			tid &= IMAP_TID_UPA;
		}

@@ -188,9 +192,11 @@ void enable_irq(unsigned int irq)
		 * 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.
		 * Things like FFB can now be handled via the new IRQ
		 * mechanism.
		 */
		upa_writel(tid | IMAP_VALID, imap);
	}

	preempt_enable();
}
+6 −3
Original line number Diff line number Diff line
@@ -504,9 +504,12 @@ static void __init per_cpu_patch(void)
	if (tlb_type == spitfire && !this_is_starfire)
		return;

	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) {
+56 −6
Original line number Diff line number Diff line
@@ -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,6 +35,7 @@ dtlb_load:
sparc64_cpu_startup:
	flushw

	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)

@@ -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

Loading