Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[SPARC64]: Probe D/I/E-cache config and use.



At boot time, determine the D-cache, I-cache and E-cache size and
line-size.  Use them in cache flushes when appropriate.

This change was motivated by discovering that the D-cache on
UltraSparc-IIIi and later are 64K not 32K, and the flushes done by the
Cheetah error handlers were assuming a 32K size.

There are still some pieces of code that are hard coding things and
will need to be fixed up at some point.

While we're here, fix the D-cache and I-cache parity error handlers
to run with interrupts disabled, and when the trap occurs at trap
level > 1 log the event via a counter displayed in /proc/cpuinfo.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 56425306
Loading
Loading
Loading
Loading
+22 −0
Original line number Original line Diff line number Diff line
@@ -135,6 +135,28 @@ void __init device_scan(void)
		cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
		cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
							    "clock-frequency",
							    "clock-frequency",
							    0);
							    0);
		cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
							     "dcache-size",
							     16 * 1024);
		cpu_data(0).dcache_line_size =
			prom_getintdefault(cpu_node, "dcache-line-size", 32);
		cpu_data(0).icache_size = prom_getintdefault(cpu_node,
							     "icache-size",
							     16 * 1024);
		cpu_data(0).icache_line_size =
			prom_getintdefault(cpu_node, "icache-line-size", 32);
		cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
							     "ecache-size",
							     4 * 1024 * 1024);
		cpu_data(0).ecache_line_size =
			prom_getintdefault(cpu_node, "ecache-line-size", 64);
		printk("CPU[0]: Caches "
		       "D[sz(%d):line_sz(%d)] "
		       "I[sz(%d):line_sz(%d)] "
		       "E[sz(%d):line_sz(%d)]\n",
		       cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
		       cpu_data(0).icache_size, cpu_data(0).icache_line_size,
		       cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
	}
	}
#endif
#endif


+18 −9
Original line number Original line Diff line number Diff line
@@ -372,14 +372,13 @@ cheetah_plus_patch_fpdis:
	 *
	 *
	 * DATA 0: [low 32-bits]  Address of function to call, jmp to this
	 * DATA 0: [low 32-bits]  Address of function to call, jmp to this
	 *         [high 32-bits] MMU Context Argument 0, place in %g5
	 *         [high 32-bits] MMU Context Argument 0, place in %g5
	 * DATA 1: Address Argument 1, place in %g6
	 * DATA 1: Address Argument 1, place in %g1
	 * DATA 2: Address Argument 2, place in %g7
	 * DATA 2: Address Argument 2, place in %g7
	 *
	 *
	 * With this method we can do most of the cross-call tlb/cache
	 * With this method we can do most of the cross-call tlb/cache
	 * flushing very quickly.
	 * flushing very quickly.
	 *
	 *
	 * Current CPU's IRQ worklist table is locked into %g1,
	 * Current CPU's IRQ worklist table is locked into %g6, don't touch.
	 * don't touch.
	 */
	 */
	.text
	.text
	.align		32
	.align		32
@@ -853,13 +852,14 @@ cheetah_plus_dcpe_trap_vector:
	nop
	nop


do_cheetah_plus_data_parity:
do_cheetah_plus_data_parity:
	ba,pt		%xcc, etrap
	rdpr		%pil, %g2
	wrpr		%g0, 15, %pil
	ba,pt		%xcc, etrap_irq
	 rd		%pc, %g7
	 rd		%pc, %g7
	mov		0x0, %o0
	mov		0x0, %o0
	call		cheetah_plus_parity_error
	call		cheetah_plus_parity_error
	 add		%sp, PTREGS_OFF, %o1
	 add		%sp, PTREGS_OFF, %o1
	ba,pt		%xcc, rtrap
	ba,a,pt		%xcc, rtrap_irq
	 clr		%l6


cheetah_plus_dcpe_trap_vector_tl1:
cheetah_plus_dcpe_trap_vector_tl1:
	membar		#Sync
	membar		#Sync
@@ -883,13 +883,14 @@ cheetah_plus_icpe_trap_vector:
	nop
	nop


do_cheetah_plus_insn_parity:
do_cheetah_plus_insn_parity:
	ba,pt		%xcc, etrap
	rdpr		%pil, %g2
	wrpr		%g0, 15, %pil
	ba,pt		%xcc, etrap_irq
	 rd		%pc, %g7
	 rd		%pc, %g7
	mov		0x1, %o0
	mov		0x1, %o0
	call		cheetah_plus_parity_error
	call		cheetah_plus_parity_error
	 add		%sp, PTREGS_OFF, %o1
	 add		%sp, PTREGS_OFF, %o1
	ba,pt		%xcc, rtrap
	ba,a,pt		%xcc, rtrap_irq
	 clr		%l6


cheetah_plus_icpe_trap_vector_tl1:
cheetah_plus_icpe_trap_vector_tl1:
	membar		#Sync
	membar		#Sync
@@ -922,6 +923,10 @@ do_dcpe_tl1:
	 nop
	 nop
	wrpr		%g1, %tl		! Restore original trap level
	wrpr		%g1, %tl		! Restore original trap level
do_dcpe_tl1_nonfatal:	/* Ok we may use interrupt globals safely. */
do_dcpe_tl1_nonfatal:	/* Ok we may use interrupt globals safely. */
	sethi		%hi(dcache_parity_tl1_occurred), %g2
	lduw		[%g2 + %lo(dcache_parity_tl1_occurred)], %g1
	add		%g1, 1, %g1
	stw		%g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
	/* Reset D-cache parity */
	/* Reset D-cache parity */
	sethi		%hi(1 << 16), %g1	! D-cache size
	sethi		%hi(1 << 16), %g1	! D-cache size
	mov		(1 << 5), %g2		! D-cache line size
	mov		(1 << 5), %g2		! D-cache line size
@@ -968,6 +973,10 @@ do_icpe_tl1:
	 nop
	 nop
	wrpr		%g1, %tl		! Restore original trap level
	wrpr		%g1, %tl		! Restore original trap level
do_icpe_tl1_nonfatal:	/* Ok we may use interrupt globals safely. */
do_icpe_tl1_nonfatal:	/* Ok we may use interrupt globals safely. */
	sethi		%hi(icache_parity_tl1_occurred), %g2
	lduw		[%g2 + %lo(icache_parity_tl1_occurred)], %g1
	add		%g1, 1, %g1
	stw		%g1, [%g2 + %lo(icache_parity_tl1_occurred)]
	/* Flush I-cache */
	/* Flush I-cache */
	sethi		%hi(1 << 15), %g1	! I-cache size
	sethi		%hi(1 << 15), %g1	! I-cache size
	mov		(1 << 5), %g2		! I-cache line size
	mov		(1 << 5), %g2		! I-cache line size
+8 −1
Original line number Original line Diff line number Diff line
@@ -605,6 +605,9 @@ extern void smp_info(struct seq_file *);
extern void smp_bogo(struct seq_file *);
extern void smp_bogo(struct seq_file *);
extern void mmu_info(struct seq_file *);
extern void mmu_info(struct seq_file *);


unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;

static int show_cpuinfo(struct seq_file *m, void *__unused)
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
{
	seq_printf(m, 
	seq_printf(m, 
@@ -615,6 +618,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
		   "type\t\t: sun4u\n"
		   "type\t\t: sun4u\n"
		   "ncpus probed\t: %ld\n"
		   "ncpus probed\t: %ld\n"
		   "ncpus active\t: %ld\n"
		   "ncpus active\t: %ld\n"
		   "D$ parity tl1\t: %u\n"
		   "I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP
#ifndef CONFIG_SMP
		   "Cpu0Bogo\t: %lu.%02lu\n"
		   "Cpu0Bogo\t: %lu.%02lu\n"
		   "Cpu0ClkTck\t: %016lx\n"
		   "Cpu0ClkTck\t: %016lx\n"
@@ -627,7 +632,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
		   (prom_prev >> 8) & 0xff,
		   (prom_prev >> 8) & 0xff,
		   prom_prev & 0xff,
		   prom_prev & 0xff,
		   (long)num_possible_cpus(),
		   (long)num_possible_cpus(),
		   (long)num_online_cpus()
		   (long)num_online_cpus(),
		   dcache_parity_tl1_occurred,
		   icache_parity_tl1_occurred
#ifndef CONFIG_SMP
#ifndef CONFIG_SMP
		   , cpu_data(0).udelay_val/(500000/HZ),
		   , cpu_data(0).udelay_val/(500000/HZ),
		   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
		   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
+21 −0
Original line number Original line Diff line number Diff line
@@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id)
	cpu_data(id).pte_cache[1]		= NULL;
	cpu_data(id).pte_cache[1]		= NULL;
	cpu_data(id).pgd_cache			= NULL;
	cpu_data(id).pgd_cache			= NULL;
	cpu_data(id).idle_volume		= 1;
	cpu_data(id).idle_volume		= 1;

	cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
						      16 * 1024);
	cpu_data(id).dcache_line_size =
		prom_getintdefault(cpu_node, "dcache-line-size", 32);
	cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
						      16 * 1024);
	cpu_data(id).icache_line_size =
		prom_getintdefault(cpu_node, "icache-line-size", 32);
	cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
						      4 * 1024 * 1024);
	cpu_data(id).ecache_line_size =
		prom_getintdefault(cpu_node, "ecache-line-size", 64);
	printk("CPU[%d]: Caches "
	       "D[sz(%d):line_sz(%d)] "
	       "I[sz(%d):line_sz(%d)] "
	       "E[sz(%d):line_sz(%d)]\n",
	       id,
	       cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
	       cpu_data(id).icache_size, cpu_data(id).icache_line_size,
	       cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
}
}


static void smp_setup_percpu_timer(void);
static void smp_setup_percpu_timer(void);
+27 −13
Original line number Original line Diff line number Diff line
@@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr)
 */
 */
static void __cheetah_flush_icache(void)
static void __cheetah_flush_icache(void)
{
{
	unsigned long i;
	unsigned int icache_size, icache_line_size;
	unsigned long addr;

	icache_size = local_cpu_data().icache_size;
	icache_line_size = local_cpu_data().icache_line_size;


	/* Clear the valid bits in all the tags. */
	/* Clear the valid bits in all the tags. */
	for (i = 0; i < (1 << 15); i += (1 << 5)) {
	for (addr = 0; addr < icache_size; addr += icache_line_size) {
		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
				     "membar #Sync"
				     "membar #Sync"
				     : /* no outputs */
				     : /* no outputs */
				     : "r" (i | (2 << 3)), "i" (ASI_IC_TAG));
				     : "r" (addr | (2 << 3)),
				       "i" (ASI_IC_TAG));
	}
	}
}
}


@@ -904,13 +909,17 @@ static void cheetah_flush_icache(void)


static void cheetah_flush_dcache(void)
static void cheetah_flush_dcache(void)
{
{
	unsigned long i;
	unsigned int dcache_size, dcache_line_size;
	unsigned long addr;

	dcache_size = local_cpu_data().dcache_size;
	dcache_line_size = local_cpu_data().dcache_line_size;


	for (i = 0; i < (1 << 16); i += (1 << 5)) {
	for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
				     "membar #Sync"
				     "membar #Sync"
				     : /* no outputs */
				     : /* no outputs */
				     : "r" (i), "i" (ASI_DCACHE_TAG));
				     : "r" (addr), "i" (ASI_DCACHE_TAG));
	}
	}
}
}


@@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void)
 */
 */
static void cheetah_plus_zap_dcache_parity(void)
static void cheetah_plus_zap_dcache_parity(void)
{
{
	unsigned long i;
	unsigned int dcache_size, dcache_line_size;
	unsigned long addr;

	dcache_size = local_cpu_data().dcache_size;
	dcache_line_size = local_cpu_data().dcache_line_size;


	for (i = 0; i < (1 << 16); i += (1 << 5)) {
	for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
		unsigned long tag = (i >> 14);
		unsigned long tag = (addr >> 14);
		unsigned long j;
		unsigned long line;


		__asm__ __volatile__("membar	#Sync\n\t"
		__asm__ __volatile__("membar	#Sync\n\t"
				     "stxa	%0, [%1] %2\n\t"
				     "stxa	%0, [%1] %2\n\t"
				     "membar	#Sync"
				     "membar	#Sync"
				     : /* no outputs */
				     : /* no outputs */
				     : "r" (tag), "r" (i),
				     : "r" (tag), "r" (addr),
				       "i" (ASI_DCACHE_UTAG));
				       "i" (ASI_DCACHE_UTAG));
		for (j = i; j < i + (1 << 5); j += (1 << 3))
		for (line = addr; line < addr + dcache_line_size; line += 8)
			__asm__ __volatile__("membar	#Sync\n\t"
			__asm__ __volatile__("membar	#Sync\n\t"
					     "stxa	%%g0, [%0] %1\n\t"
					     "stxa	%%g0, [%0] %1\n\t"
					     "membar	#Sync"
					     "membar	#Sync"
					     : /* no outputs */
					     : /* no outputs */
					     : "r" (j), "i" (ASI_DCACHE_DATA));
					     : "r" (line),
					       "i" (ASI_DCACHE_DATA));
	}
	}
}
}


Loading