cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cache.c (16973B)


      1/*
      2 * Cache control for MicroBlaze cache memories
      3 *
      4 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
      5 * Copyright (C) 2007-2009 PetaLogix
      6 * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com>
      7 *
      8 * This file is subject to the terms and conditions of the GNU General
      9 * Public License. See the file COPYING in the main directory of this
     10 * archive for more details.
     11 */
     12
     13#include <asm/cacheflush.h>
     14#include <linux/cache.h>
     15#include <asm/cpuinfo.h>
     16#include <asm/pvr.h>
     17
     18static inline void __enable_icache_msr(void)
     19{
     20	__asm__ __volatile__ ("	 msrset	r0, %0;"	\
     21				"nop;"			\
     22			: : "i" (MSR_ICE) : "memory");
     23}
     24
     25static inline void __disable_icache_msr(void)
     26{
     27	__asm__ __volatile__ ("	 msrclr	r0, %0;"	\
     28				"nop;"			\
     29			: : "i" (MSR_ICE) : "memory");
     30}
     31
     32static inline void __enable_dcache_msr(void)
     33{
     34	__asm__ __volatile__ ("	 msrset	r0, %0;"	\
     35				"nop;"			\
     36			: : "i" (MSR_DCE) : "memory");
     37}
     38
     39static inline void __disable_dcache_msr(void)
     40{
     41	__asm__ __volatile__ ("	 msrclr	r0, %0;"	\
     42				"nop; "			\
     43			: : "i" (MSR_DCE) : "memory");
     44}
     45
     46static inline void __enable_icache_nomsr(void)
     47{
     48	__asm__ __volatile__ ("	 mfs	r12, rmsr;"	\
     49				"nop;"			\
     50				"ori	r12, r12, %0;"	\
     51				"mts	rmsr, r12;"	\
     52				"nop;"			\
     53			: : "i" (MSR_ICE) : "memory", "r12");
     54}
     55
     56static inline void __disable_icache_nomsr(void)
     57{
     58	__asm__ __volatile__ ("	 mfs	r12, rmsr;"	\
     59				"nop;"			\
     60				"andi	r12, r12, ~%0;"	\
     61				"mts	rmsr, r12;"	\
     62				"nop;"			\
     63			: : "i" (MSR_ICE) : "memory", "r12");
     64}
     65
     66static inline void __enable_dcache_nomsr(void)
     67{
     68	__asm__ __volatile__ ("	 mfs	r12, rmsr;"	\
     69				"nop;"			\
     70				"ori	r12, r12, %0;"	\
     71				"mts	rmsr, r12;"	\
     72				"nop;"			\
     73			: : "i" (MSR_DCE) : "memory", "r12");
     74}
     75
     76static inline void __disable_dcache_nomsr(void)
     77{
     78	__asm__ __volatile__ ("	 mfs	r12, rmsr;"	\
     79				"nop;"			\
     80				"andi	r12, r12, ~%0;"	\
     81				"mts	rmsr, r12;"	\
     82				"nop;"			\
     83			: : "i" (MSR_DCE) : "memory", "r12");
     84}
     85
     86
     87/* Helper macro for computing the limits of cache range loops
     88 *
     89 * End address can be unaligned which is OK for C implementation.
     90 * ASM implementation align it in ASM macros
     91 */
     92#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size)	\
     93do {									\
     94	int align = ~(cache_line_length - 1);				\
     95	if (start <  UINT_MAX - cache_size)				\
     96		end = min(start + cache_size, end);			\
     97	start &= align;							\
     98} while (0)
     99
    100/*
    101 * Helper macro to loop over the specified cache_size/line_length and
    102 * execute 'op' on that cacheline
    103 */
    104#define CACHE_ALL_LOOP(cache_size, line_length, op)			\
    105do {									\
    106	unsigned int len = cache_size - line_length;			\
    107	int step = -line_length;					\
    108	WARN_ON(step >= 0);						\
    109									\
    110	__asm__ __volatile__ (" 1:      " #op " %0, r0;"		\
    111					"bgtid   %0, 1b;"		\
    112					"addk    %0, %0, %1;"		\
    113					: : "r" (len), "r" (step)	\
    114					: "memory");			\
    115} while (0)
    116
    117/* Used for wdc.flush/clear which can use rB for offset which is not possible
    118 * to use for simple wdc or wic.
    119 *
    120 * start address is cache aligned
    121 * end address is not aligned, if end is aligned then I have to subtract
    122 * cacheline length because I can't flush/invalidate the next cacheline.
    123 * If is not, I align it because I will flush/invalidate whole line.
    124 */
    125#define CACHE_RANGE_LOOP_2(start, end, line_length, op)			\
    126do {									\
    127	int step = -line_length;					\
    128	int align = ~(line_length - 1);					\
    129	int count;							\
    130	end = ((end & align) == end) ? end - line_length : end & align;	\
    131	count = end - start;						\
    132	WARN_ON(count < 0);						\
    133									\
    134	__asm__ __volatile__ (" 1:	" #op "	%0, %1;"		\
    135					"bgtid	%1, 1b;"		\
    136					"addk	%1, %1, %2;"		\
    137					: : "r" (start), "r" (count),	\
    138					"r" (step) : "memory");		\
    139} while (0)
    140
    141/* It is used only first parameter for OP - for wic, wdc */
    142#define CACHE_RANGE_LOOP_1(start, end, line_length, op)			\
    143do {									\
    144	unsigned int volatile temp = 0;						\
    145	unsigned int align = ~(line_length - 1);					\
    146	end = ((end & align) == end) ? end - line_length : end & align;	\
    147	WARN_ON(end < start);					\
    148									\
    149	__asm__ __volatile__ (" 1:	" #op "	%1, r0;"		\
    150					"cmpu	%0, %1, %2;"		\
    151					"bgtid	%0, 1b;"		\
    152					"addk	%1, %1, %3;"		\
    153				: : "r" (temp), "r" (start), "r" (end),	\
    154					"r" (line_length) : "memory");	\
    155} while (0)
    156
    157#define ASM_LOOP
    158
    159static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
    160{
    161	unsigned long flags;
    162#ifndef ASM_LOOP
    163	int i;
    164#endif
    165	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    166				(unsigned int)start, (unsigned int) end);
    167
    168	CACHE_LOOP_LIMITS(start, end,
    169			cpuinfo.icache_line_length, cpuinfo.icache_size);
    170
    171	local_irq_save(flags);
    172	__disable_icache_msr();
    173
    174#ifdef ASM_LOOP
    175	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
    176#else
    177	for (i = start; i < end; i += cpuinfo.icache_line_length)
    178		__asm__ __volatile__ ("wic	%0, r0;"	\
    179				: : "r" (i));
    180#endif
    181	__enable_icache_msr();
    182	local_irq_restore(flags);
    183}
    184
    185static void __flush_icache_range_nomsr_irq(unsigned long start,
    186				unsigned long end)
    187{
    188	unsigned long flags;
    189#ifndef ASM_LOOP
    190	int i;
    191#endif
    192	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    193				(unsigned int)start, (unsigned int) end);
    194
    195	CACHE_LOOP_LIMITS(start, end,
    196			cpuinfo.icache_line_length, cpuinfo.icache_size);
    197
    198	local_irq_save(flags);
    199	__disable_icache_nomsr();
    200
    201#ifdef ASM_LOOP
    202	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
    203#else
    204	for (i = start; i < end; i += cpuinfo.icache_line_length)
    205		__asm__ __volatile__ ("wic	%0, r0;"	\
    206				: : "r" (i));
    207#endif
    208
    209	__enable_icache_nomsr();
    210	local_irq_restore(flags);
    211}
    212
    213static void __flush_icache_range_noirq(unsigned long start,
    214				unsigned long end)
    215{
    216#ifndef ASM_LOOP
    217	int i;
    218#endif
    219	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    220				(unsigned int)start, (unsigned int) end);
    221
    222	CACHE_LOOP_LIMITS(start, end,
    223			cpuinfo.icache_line_length, cpuinfo.icache_size);
    224#ifdef ASM_LOOP
    225	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
    226#else
    227	for (i = start; i < end; i += cpuinfo.icache_line_length)
    228		__asm__ __volatile__ ("wic	%0, r0;"	\
    229				: : "r" (i));
    230#endif
    231}
    232
    233static void __flush_icache_all_msr_irq(void)
    234{
    235	unsigned long flags;
    236#ifndef ASM_LOOP
    237	int i;
    238#endif
    239	pr_debug("%s\n", __func__);
    240
    241	local_irq_save(flags);
    242	__disable_icache_msr();
    243#ifdef ASM_LOOP
    244	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
    245#else
    246	for (i = 0; i < cpuinfo.icache_size;
    247		 i += cpuinfo.icache_line_length)
    248			__asm__ __volatile__ ("wic	%0, r0;" \
    249					: : "r" (i));
    250#endif
    251	__enable_icache_msr();
    252	local_irq_restore(flags);
    253}
    254
    255static void __flush_icache_all_nomsr_irq(void)
    256{
    257	unsigned long flags;
    258#ifndef ASM_LOOP
    259	int i;
    260#endif
    261	pr_debug("%s\n", __func__);
    262
    263	local_irq_save(flags);
    264	__disable_icache_nomsr();
    265#ifdef ASM_LOOP
    266	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
    267#else
    268	for (i = 0; i < cpuinfo.icache_size;
    269		 i += cpuinfo.icache_line_length)
    270			__asm__ __volatile__ ("wic	%0, r0;" \
    271					: : "r" (i));
    272#endif
    273	__enable_icache_nomsr();
    274	local_irq_restore(flags);
    275}
    276
    277static void __flush_icache_all_noirq(void)
    278{
    279#ifndef ASM_LOOP
    280	int i;
    281#endif
    282	pr_debug("%s\n", __func__);
    283#ifdef ASM_LOOP
    284	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
    285#else
    286	for (i = 0; i < cpuinfo.icache_size;
    287		 i += cpuinfo.icache_line_length)
    288			__asm__ __volatile__ ("wic	%0, r0;" \
    289					: : "r" (i));
    290#endif
    291}
    292
    293static void __invalidate_dcache_all_msr_irq(void)
    294{
    295	unsigned long flags;
    296#ifndef ASM_LOOP
    297	int i;
    298#endif
    299	pr_debug("%s\n", __func__);
    300
    301	local_irq_save(flags);
    302	__disable_dcache_msr();
    303#ifdef ASM_LOOP
    304	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
    305#else
    306	for (i = 0; i < cpuinfo.dcache_size;
    307		 i += cpuinfo.dcache_line_length)
    308			__asm__ __volatile__ ("wdc	%0, r0;" \
    309					: : "r" (i));
    310#endif
    311	__enable_dcache_msr();
    312	local_irq_restore(flags);
    313}
    314
    315static void __invalidate_dcache_all_nomsr_irq(void)
    316{
    317	unsigned long flags;
    318#ifndef ASM_LOOP
    319	int i;
    320#endif
    321	pr_debug("%s\n", __func__);
    322
    323	local_irq_save(flags);
    324	__disable_dcache_nomsr();
    325#ifdef ASM_LOOP
    326	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
    327#else
    328	for (i = 0; i < cpuinfo.dcache_size;
    329		 i += cpuinfo.dcache_line_length)
    330			__asm__ __volatile__ ("wdc	%0, r0;" \
    331					: : "r" (i));
    332#endif
    333	__enable_dcache_nomsr();
    334	local_irq_restore(flags);
    335}
    336
    337static void __invalidate_dcache_all_noirq_wt(void)
    338{
    339#ifndef ASM_LOOP
    340	int i;
    341#endif
    342	pr_debug("%s\n", __func__);
    343#ifdef ASM_LOOP
    344	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
    345#else
    346	for (i = 0; i < cpuinfo.dcache_size;
    347		 i += cpuinfo.dcache_line_length)
    348			__asm__ __volatile__ ("wdc	%0, r0;" \
    349					: : "r" (i));
    350#endif
    351}
    352
    353/*
    354 * FIXME It is blindly invalidation as is expected
    355 * but can't be called on noMMU in microblaze_cache_init below
    356 *
    357 * MS: noMMU kernel won't boot if simple wdc is used
    358 * The reason should be that there are discared data which kernel needs
    359 */
    360static void __invalidate_dcache_all_wb(void)
    361{
    362#ifndef ASM_LOOP
    363	int i;
    364#endif
    365	pr_debug("%s\n", __func__);
    366#ifdef ASM_LOOP
    367	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
    368					wdc);
    369#else
    370	for (i = 0; i < cpuinfo.dcache_size;
    371		 i += cpuinfo.dcache_line_length)
    372			__asm__ __volatile__ ("wdc	%0, r0;" \
    373					: : "r" (i));
    374#endif
    375}
    376
    377static void __invalidate_dcache_range_wb(unsigned long start,
    378						unsigned long end)
    379{
    380#ifndef ASM_LOOP
    381	int i;
    382#endif
    383	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    384				(unsigned int)start, (unsigned int) end);
    385
    386	CACHE_LOOP_LIMITS(start, end,
    387			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
    388#ifdef ASM_LOOP
    389	CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
    390#else
    391	for (i = start; i < end; i += cpuinfo.dcache_line_length)
    392		__asm__ __volatile__ ("wdc.clear	%0, r0;"	\
    393				: : "r" (i));
    394#endif
    395}
    396
    397static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
    398							unsigned long end)
    399{
    400#ifndef ASM_LOOP
    401	int i;
    402#endif
    403	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    404				(unsigned int)start, (unsigned int) end);
    405	CACHE_LOOP_LIMITS(start, end,
    406			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
    407
    408#ifdef ASM_LOOP
    409	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
    410#else
    411	for (i = start; i < end; i += cpuinfo.dcache_line_length)
    412		__asm__ __volatile__ ("wdc	%0, r0;"	\
    413				: : "r" (i));
    414#endif
    415}
    416
    417static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
    418							unsigned long end)
    419{
    420	unsigned long flags;
    421#ifndef ASM_LOOP
    422	int i;
    423#endif
    424	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    425				(unsigned int)start, (unsigned int) end);
    426	CACHE_LOOP_LIMITS(start, end,
    427			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
    428
    429	local_irq_save(flags);
    430	__disable_dcache_msr();
    431
    432#ifdef ASM_LOOP
    433	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
    434#else
    435	for (i = start; i < end; i += cpuinfo.dcache_line_length)
    436		__asm__ __volatile__ ("wdc	%0, r0;"	\
    437				: : "r" (i));
    438#endif
    439
    440	__enable_dcache_msr();
    441	local_irq_restore(flags);
    442}
    443
    444static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
    445							unsigned long end)
    446{
    447	unsigned long flags;
    448#ifndef ASM_LOOP
    449	int i;
    450#endif
    451	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    452				(unsigned int)start, (unsigned int) end);
    453
    454	CACHE_LOOP_LIMITS(start, end,
    455			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
    456
    457	local_irq_save(flags);
    458	__disable_dcache_nomsr();
    459
    460#ifdef ASM_LOOP
    461	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
    462#else
    463	for (i = start; i < end; i += cpuinfo.dcache_line_length)
    464		__asm__ __volatile__ ("wdc	%0, r0;"	\
    465				: : "r" (i));
    466#endif
    467
    468	__enable_dcache_nomsr();
    469	local_irq_restore(flags);
    470}
    471
    472static void __flush_dcache_all_wb(void)
    473{
    474#ifndef ASM_LOOP
    475	int i;
    476#endif
    477	pr_debug("%s\n", __func__);
    478#ifdef ASM_LOOP
    479	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
    480				wdc.flush);
    481#else
    482	for (i = 0; i < cpuinfo.dcache_size;
    483		 i += cpuinfo.dcache_line_length)
    484			__asm__ __volatile__ ("wdc.flush	%0, r0;" \
    485					: : "r" (i));
    486#endif
    487}
    488
    489static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
    490{
    491#ifndef ASM_LOOP
    492	int i;
    493#endif
    494	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
    495				(unsigned int)start, (unsigned int) end);
    496
    497	CACHE_LOOP_LIMITS(start, end,
    498			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
    499#ifdef ASM_LOOP
    500	CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
    501#else
    502	for (i = start; i < end; i += cpuinfo.dcache_line_length)
    503		__asm__ __volatile__ ("wdc.flush	%0, r0;"	\
    504				: : "r" (i));
    505#endif
    506}
    507
    508/* struct for wb caches and for wt caches */
    509struct scache *mbc;
    510
    511/* new wb cache model */
    512static const struct scache wb_msr = {
    513	.ie = __enable_icache_msr,
    514	.id = __disable_icache_msr,
    515	.ifl = __flush_icache_all_noirq,
    516	.iflr = __flush_icache_range_noirq,
    517	.iin = __flush_icache_all_noirq,
    518	.iinr = __flush_icache_range_noirq,
    519	.de = __enable_dcache_msr,
    520	.dd = __disable_dcache_msr,
    521	.dfl = __flush_dcache_all_wb,
    522	.dflr = __flush_dcache_range_wb,
    523	.din = __invalidate_dcache_all_wb,
    524	.dinr = __invalidate_dcache_range_wb,
    525};
    526
    527/* There is only difference in ie, id, de, dd functions */
    528static const struct scache wb_nomsr = {
    529	.ie = __enable_icache_nomsr,
    530	.id = __disable_icache_nomsr,
    531	.ifl = __flush_icache_all_noirq,
    532	.iflr = __flush_icache_range_noirq,
    533	.iin = __flush_icache_all_noirq,
    534	.iinr = __flush_icache_range_noirq,
    535	.de = __enable_dcache_nomsr,
    536	.dd = __disable_dcache_nomsr,
    537	.dfl = __flush_dcache_all_wb,
    538	.dflr = __flush_dcache_range_wb,
    539	.din = __invalidate_dcache_all_wb,
    540	.dinr = __invalidate_dcache_range_wb,
    541};
    542
    543/* Old wt cache model with disabling irq and turn off cache */
    544static const struct scache wt_msr = {
    545	.ie = __enable_icache_msr,
    546	.id = __disable_icache_msr,
    547	.ifl = __flush_icache_all_msr_irq,
    548	.iflr = __flush_icache_range_msr_irq,
    549	.iin = __flush_icache_all_msr_irq,
    550	.iinr = __flush_icache_range_msr_irq,
    551	.de = __enable_dcache_msr,
    552	.dd = __disable_dcache_msr,
    553	.dfl = __invalidate_dcache_all_msr_irq,
    554	.dflr = __invalidate_dcache_range_msr_irq_wt,
    555	.din = __invalidate_dcache_all_msr_irq,
    556	.dinr = __invalidate_dcache_range_msr_irq_wt,
    557};
    558
    559static const struct scache wt_nomsr = {
    560	.ie = __enable_icache_nomsr,
    561	.id = __disable_icache_nomsr,
    562	.ifl = __flush_icache_all_nomsr_irq,
    563	.iflr = __flush_icache_range_nomsr_irq,
    564	.iin = __flush_icache_all_nomsr_irq,
    565	.iinr = __flush_icache_range_nomsr_irq,
    566	.de = __enable_dcache_nomsr,
    567	.dd = __disable_dcache_nomsr,
    568	.dfl = __invalidate_dcache_all_nomsr_irq,
    569	.dflr = __invalidate_dcache_range_nomsr_irq,
    570	.din = __invalidate_dcache_all_nomsr_irq,
    571	.dinr = __invalidate_dcache_range_nomsr_irq,
    572};
    573
    574/* New wt cache model for newer Microblaze versions */
    575static const struct scache wt_msr_noirq = {
    576	.ie = __enable_icache_msr,
    577	.id = __disable_icache_msr,
    578	.ifl = __flush_icache_all_noirq,
    579	.iflr = __flush_icache_range_noirq,
    580	.iin = __flush_icache_all_noirq,
    581	.iinr = __flush_icache_range_noirq,
    582	.de = __enable_dcache_msr,
    583	.dd = __disable_dcache_msr,
    584	.dfl = __invalidate_dcache_all_noirq_wt,
    585	.dflr = __invalidate_dcache_range_nomsr_wt,
    586	.din = __invalidate_dcache_all_noirq_wt,
    587	.dinr = __invalidate_dcache_range_nomsr_wt,
    588};
    589
    590static const struct scache wt_nomsr_noirq = {
    591	.ie = __enable_icache_nomsr,
    592	.id = __disable_icache_nomsr,
    593	.ifl = __flush_icache_all_noirq,
    594	.iflr = __flush_icache_range_noirq,
    595	.iin = __flush_icache_all_noirq,
    596	.iinr = __flush_icache_range_noirq,
    597	.de = __enable_dcache_nomsr,
    598	.dd = __disable_dcache_nomsr,
    599	.dfl = __invalidate_dcache_all_noirq_wt,
    600	.dflr = __invalidate_dcache_range_nomsr_wt,
    601	.din = __invalidate_dcache_all_noirq_wt,
    602	.dinr = __invalidate_dcache_range_nomsr_wt,
    603};
    604
    605/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
    606#define CPUVER_7_20_A	0x0c
    607#define CPUVER_7_20_D	0x0f
    608
    609void microblaze_cache_init(void)
    610{
    611	if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
    612		if (cpuinfo.dcache_wb) {
    613			pr_info("wb_msr\n");
    614			mbc = (struct scache *)&wb_msr;
    615			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
    616				/* MS: problem with signal handling - hw bug */
    617				pr_info("WB won't work properly\n");
    618			}
    619		} else {
    620			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
    621				pr_info("wt_msr_noirq\n");
    622				mbc = (struct scache *)&wt_msr_noirq;
    623			} else {
    624				pr_info("wt_msr\n");
    625				mbc = (struct scache *)&wt_msr;
    626			}
    627		}
    628	} else {
    629		if (cpuinfo.dcache_wb) {
    630			pr_info("wb_nomsr\n");
    631			mbc = (struct scache *)&wb_nomsr;
    632			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
    633				/* MS: problem with signal handling - hw bug */
    634				pr_info("WB won't work properly\n");
    635			}
    636		} else {
    637			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
    638				pr_info("wt_nomsr_noirq\n");
    639				mbc = (struct scache *)&wt_nomsr_noirq;
    640			} else {
    641				pr_info("wt_nomsr\n");
    642				mbc = (struct scache *)&wt_nomsr;
    643			}
    644		}
    645	}
    646	/*
    647	 * FIXME Invalidation is done in U-BOOT
    648	 * WT cache: Data is already written to main memory
    649	 * WB cache: Discard data on noMMU which caused that kernel doesn't boot
    650	 */
    651	/* invalidate_dcache(); */
    652	enable_dcache();
    653
    654	invalidate_icache();
    655	enable_icache();
    656}