aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorZoltan Menyhart <Zoltan.Menyhart@bull.net>2005-06-03 08:36:00 -0400
committerTony Luck <tony.luck@intel.com>2005-07-12 18:33:18 -0400
commit08357f82d4decc48bbfd39ae30d5fe0754f7f576 (patch)
treec8516a8f208e1cb253bd33f41857b0699104b130 /arch
parent60a762b6a6dec17cc4339b60154902fd04c2f9f2 (diff)
[IA64] improve flush_icache_range()
Check with PAL to see what the i-cache line size is for each level of the cache, and so use the correct stride when flushing the cache. Acked-by: David Mosberger Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kernel/setup.c37
-rw-r--r--arch/ia64/lib/flush.S46
2 files changed, 69 insertions, 14 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 2693e1522d7c..7fc891aca446 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -20,6 +20,7 @@
20 * 02/01/00 R.Seth fixed get_cpuinfo for SMP 20 * 02/01/00 R.Seth fixed get_cpuinfo for SMP
21 * 01/07/99 S.Eranian added the support for command line argument 21 * 01/07/99 S.Eranian added the support for command line argument
22 * 06/24/99 W.Drummond added boot_cpu_data. 22 * 06/24/99 W.Drummond added boot_cpu_data.
23 * 05/28/05 Z. Menyhart Dynamic stride size for "flush_icache_range()"
23 */ 24 */
24#include <linux/config.h> 25#include <linux/config.h>
25#include <linux/module.h> 26#include <linux/module.h>
@@ -83,6 +84,13 @@ EXPORT_SYMBOL(io_space);
83unsigned int num_io_spaces; 84unsigned int num_io_spaces;
84 85
85/* 86/*
87 * "flush_icache_range()" needs to know what processor dependent stride size to use
88 * when it makes i-cache(s) coherent with d-caches.
89 */
90#define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */
91unsigned long ia64_i_cache_stride_shift = ~0;
92
93/*
86 * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This 94 * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This
87 * mask specifies a mask of address bits that must be 0 in order for two buffers to be 95 * mask specifies a mask of address bits that must be 0 in order for two buffers to be
88 * mergeable by the I/O MMU (i.e., the end address of the first buffer and the start 96 * mergeable by the I/O MMU (i.e., the end address of the first buffer and the start
@@ -626,6 +634,12 @@ setup_per_cpu_areas (void)
626 /* start_kernel() requires this... */ 634 /* start_kernel() requires this... */
627} 635}
628 636
637/*
638 * Calculate the max. cache line size.
639 *
640 * In addition, the minimum of the i-cache stride sizes is calculated for
641 * "flush_icache_range()".
642 */
629static void 643static void
630get_max_cacheline_size (void) 644get_max_cacheline_size (void)
631{ 645{
@@ -639,6 +653,8 @@ get_max_cacheline_size (void)
639 printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", 653 printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
640 __FUNCTION__, status); 654 __FUNCTION__, status);
641 max = SMP_CACHE_BYTES; 655 max = SMP_CACHE_BYTES;
656 /* Safest setup for "flush_icache_range()" */
657 ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT;
642 goto out; 658 goto out;
643 } 659 }
644 660
@@ -647,14 +663,31 @@ get_max_cacheline_size (void)
647 &cci); 663 &cci);
648 if (status != 0) { 664 if (status != 0) {
649 printk(KERN_ERR 665 printk(KERN_ERR
650 "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", 666 "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n",
651 __FUNCTION__, l, status); 667 __FUNCTION__, l, status);
652 max = SMP_CACHE_BYTES; 668 max = SMP_CACHE_BYTES;
669 /* The safest setup for "flush_icache_range()" */
670 cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
671 cci.pcci_unified = 1;
653 } 672 }
654 line_size = 1 << cci.pcci_line_size; 673 line_size = 1 << cci.pcci_line_size;
655 if (line_size > max) 674 if (line_size > max)
656 max = line_size; 675 max = line_size;
657 } 676 if (!cci.pcci_unified) {
677 status = ia64_pal_cache_config_info(l,
678 /* cache_type (instruction)= */ 1,
679 &cci);
680 if (status != 0) {
681 printk(KERN_ERR
682 "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n",
683 __FUNCTION__, l, status);
684 /* The safest setup for "flush_icache_range()" */
685 cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
686 }
687 }
688 if (cci.pcci_stride < ia64_i_cache_stride_shift)
689 ia64_i_cache_stride_shift = cci.pcci_stride;
690 }
658 out: 691 out:
659 if (max > ia64_max_cacheline_size) 692 if (max > ia64_max_cacheline_size)
660 ia64_max_cacheline_size = max; 693 ia64_max_cacheline_size = max;
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index a1af9146cfdb..3e2cfa2c6d39 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -3,37 +3,59 @@
3 * 3 *
4 * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co 4 * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 *
7 * 05/28/05 Zoltan Menyhart Dynamic stride size
6 */ 8 */
9
7#include <asm/asmmacro.h> 10#include <asm/asmmacro.h>
8#include <asm/page.h> 11
9 12
10 /* 13 /*
11 * flush_icache_range(start,end) 14 * flush_icache_range(start,end)
12 * Must flush range from start to end-1 but nothing else (need to 15 *
16 * Make i-cache(s) coherent with d-caches.
17 *
18 * Must deal with range from start to end-1 but nothing else (need to
13 * be careful not to touch addresses that may be unmapped). 19 * be careful not to touch addresses that may be unmapped).
20 *
21 * Note: "in0" and "in1" are preserved for debugging purposes.
14 */ 22 */
15GLOBAL_ENTRY(flush_icache_range) 23GLOBAL_ENTRY(flush_icache_range)
24
16 .prologue 25 .prologue
17 alloc r2=ar.pfs,2,0,0,0 26 alloc r2=ar.pfs,2,0,0,0
18 sub r8=in1,in0,1 27 movl r3=ia64_i_cache_stride_shift
28 mov r21=1
29 ;;
30 ld8 r20=[r3] // r20: stride shift
31 sub r22=in1,r0,1 // last byte address
19 ;; 32 ;;
20 shr.u r8=r8,5 // we flush 32 bytes per iteration 33 shr.u r23=in0,r20 // start / (stride size)
21 .save ar.lc, r3 34 shr.u r22=r22,r20 // (last byte address) / (stride size)
22 mov r3=ar.lc // save ar.lc 35 shl r21=r21,r20 // r21: stride size of the i-cache(s)
36 ;;
37 sub r8=r22,r23 // number of strides - 1
38 shl r24=r23,r20 // r24: addresses for "fc.i" =
39 // "start" rounded down to stride boundary
40 .save ar.lc,r3
41 mov r3=ar.lc // save ar.lc
23 ;; 42 ;;
24 43
25 .body 44 .body
26 45 mov ar.lc=r8
27 mov ar.lc=r8
28 ;; 46 ;;
29.Loop: fc.i in0 // issuable on M2 only 47 /*
30 add in0=32,in0 48 * 32 byte aligned loop, even number of (actually 2) bundles
49 */
50.Loop: fc.i r24 // issuable on M0 only
51 add r24=r21,r24 // we flush "stride size" bytes per iteration
52 nop.i 0
31 br.cloop.sptk.few .Loop 53 br.cloop.sptk.few .Loop
32 ;; 54 ;;
33 sync.i 55 sync.i
34 ;; 56 ;;
35 srlz.i 57 srlz.i
36 ;; 58 ;;
37 mov ar.lc=r3 // restore ar.lc 59 mov ar.lc=r3 // restore ar.lc
38 br.ret.sptk.many rp 60 br.ret.sptk.many rp
39END(flush_icache_range) 61END(flush_icache_range)