File: cache.c

package info (click to toggle)
kernel-image-2.4.18-hppa 62.3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 156,012 kB
  • ctags: 448,723
  • sloc: ansic: 2,586,445; asm: 145,047; makefile: 8,574; sh: 3,097; perl: 2,578; yacc: 1,177; tcl: 577; lex: 352; awk: 251; lisp: 218; sed: 72
file content (224 lines) | stat: -rw-r--r-- 5,654 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1999 Helge Deller (07-13-1999)
 * Copyright (C) 1999 SuSE GmbH Nuernberg
 * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
 *
 * Cache and TLB management
 *
 */
 
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/seq_file.h>

#include <asm/pdc.h>
#include <asm/cache.h>
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>

int split_tlb;
int dcache_stride;
int icache_stride;

struct pdc_cache_info cache_info;
#ifndef CONFIG_PA20
static struct pdc_btlb_info btlb_info;
#endif

#ifdef CONFIG_SMP
void
flush_data_cache(void)
{
	smp_call_function((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
	flush_data_cache_local();
}
#endif

void
flush_cache_all_local(void)
{
	flush_instruction_cache_local();
	flush_data_cache_local();
}

/* flushes EVERYTHING (tlb & cache) */

void
flush_all_caches(void)
{
	flush_cache_all();
	flush_tlb_all();
}

void
update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
{
	struct page *page = pte_page(pte);

	if (VALID_PAGE(page) && page->mapping &&
	    test_bit(PG_dcache_dirty, &page->flags)) {

		flush_kernel_dcache_page(page_address(page));
		clear_bit(PG_dcache_dirty, &page->flags);
	}
}

void
show_cache_info(struct seq_file *m)
{
	seq_printf(m, "I-cache\t\t: %ld KB\n", 
		cache_info.ic_size/1024 );
	seq_printf(m, "D-cache\t\t: %ld KB (%s)%s\n", 
		cache_info.dc_size/1024,
		(cache_info.dc_conf.cc_wt ? "WT":"WB"),
		(cache_info.dc_conf.cc_sh ? " - shared I/D":"")
	);

	seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
		cache_info.it_size,
		cache_info.dt_size,
		cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
	);
		
#ifndef CONFIG_PA20
	/* BTLB - Block TLB */
	if (btlb_info.max_size==0) {
		seq_printf(m, "BTLB\t\t: not supported\n" );
	} else {
		seq_printf(m, 
		"BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
		"BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
		"BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
		btlb_info.max_size, (int)4096,
		btlb_info.max_size>>8,
		btlb_info.fixed_range_info.num_i,
		btlb_info.fixed_range_info.num_d,
		btlb_info.fixed_range_info.num_comb, 
		btlb_info.variable_range_info.num_i,
		btlb_info.variable_range_info.num_d,
		btlb_info.variable_range_info.num_comb
		);
	}
#endif
}

void __init 
cache_init(void)
{
	if(pdc_cache_info(&cache_info)<0)
		panic("cache_init: pdc_cache_info failed");

#if 0
	printk(KERN_DEBUG "ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
	    cache_info.ic_size,
	    cache_info.dc_size,
	    cache_info.it_size,
	    sizeof (struct pdc_cache_info) / sizeof (long),
	    sizeof (struct pdc_cache_cf)
	);

	printk(KERN_DEBUG "dc base %x dc stride %x dc count %x dc loop %d\n",
	    cache_info.dc_base,
	    cache_info.dc_stride,
	    cache_info.dc_count,
	    cache_info.dc_loop);

	printk(KERN_DEBUG "dc conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
	    cache_info.dc_conf.cc_alias,
	    cache_info.dc_conf.cc_block,
	    cache_info.dc_conf.cc_line,
	    cache_info.dc_conf.cc_wt,
	    cache_info.dc_conf.cc_sh,
	    cache_info.dc_conf.cc_cst,
	    cache_info.dc_conf.cc_assoc);

	printk(KERN_DEBUG "ic conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
	    cache_info.ic_conf.cc_alias,
	    cache_info.ic_conf.cc_block,
	    cache_info.ic_conf.cc_line,
	    cache_info.ic_conf.cc_wt,
	    cache_info.ic_conf.cc_sh,
	    cache_info.ic_conf.cc_cst,
	    cache_info.ic_conf.cc_assoc);

	printk(KERN_DEBUG "dt conf: sh %d page %d cst %d aid %d pad1 %d \n",
	    cache_info.dt_conf.tc_sh,
	    cache_info.dt_conf.tc_page,
	    cache_info.dt_conf.tc_cst,
	    cache_info.dt_conf.tc_aid,
	    cache_info.dt_conf.tc_pad1);

	printk(KERN_DEBUG "it conf: sh %d page %d cst %d aid %d pad1 %d \n",
	    cache_info.it_conf.tc_sh,
	    cache_info.it_conf.tc_page,
	    cache_info.it_conf.tc_cst,
	    cache_info.it_conf.tc_aid,
	    cache_info.it_conf.tc_pad1);
#endif

	split_tlb = 0;
	if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {

	    if (cache_info.dt_conf.tc_sh == 2)
		printk(KERN_WARNING "Unexpected TLB configuration. "
			"Will flush I/D separately (could be optimized).\n");

	    split_tlb = 1;
	}

	dcache_stride = ( (1<<(cache_info.dc_conf.cc_block+3)) *
			 cache_info.dc_conf.cc_line );
	icache_stride = ( (1<<(cache_info.ic_conf.cc_block+3)) *
			 cache_info.ic_conf.cc_line );
#ifndef CONFIG_PA20
	if(pdc_btlb_info(&btlb_info)<0) {
		memset(&btlb_info, 0, sizeof btlb_info);
	}
#endif

	if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) {
		printk(KERN_WARNING "Only equivalent aliasing supported\n");
#ifndef CONFIG_SMP
		panic("SMP kernel required to avoid non-equivalent aliasing");
#endif
	}
}

void disable_sr_hashing(void)
{
    int srhash_type;

    if (boot_cpu_data.cpu_type == pcxl2)
	return; /* pcxl2 doesn't support space register hashing */

    switch (boot_cpu_data.cpu_type) {

    case pcx:
	BUG(); /* We shouldn't get here. code in setup.c should prevent it */
	return;

    case pcxs:
    case pcxt:
    case pcxt_:
	srhash_type = SRHASH_PCXST;
	break;

    case pcxl:
	srhash_type = SRHASH_PCXL;
	break;

    default: /* Currently all PA2.0 machines use the same ins. sequence */
	srhash_type = SRHASH_PA20;
	break;
    }

    disable_sr_hashing_asm(srhash_type);
}