Subversion Repositories HelenOS

Rev

Rev 2071 | Rev 2745 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 jermar 1
/*
2071 jermar 2
 * Copyright (c) 2003-2004 Jakub Jermar
1 jermar 3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
1776 jermar 29
/** @addtogroup mips32mm	
1702 cejka 30
 * @{
31
 */
32
/** @file
33
 */
34
 
1 jermar 35
#include <arch/mm/tlb.h>
727 jermar 36
#include <mm/asid.h>
1 jermar 37
#include <mm/tlb.h>
391 jermar 38
#include <mm/page.h>
703 jermar 39
#include <mm/as.h>
1 jermar 40
#include <arch/cp0.h>
41
#include <panic.h>
42
#include <arch.h>
268 palkovsky 43
#include <symtab.h>
391 jermar 44
#include <synch/spinlock.h>
45
#include <print.h>
396 jermar 46
#include <debug.h>
983 palkovsky 47
#include <align.h>
1595 palkovsky 48
#include <interrupt.h>
268 palkovsky 49
 
958 jermar 50
static void tlb_refill_fail(istate_t *istate);
51
static void tlb_invalid_fail(istate_t *istate);
52
static void tlb_modified_fail(istate_t *istate);
391 jermar 53
 
1780 jermar 54
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc);
399 jermar 55
 
1780 jermar 56
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn);
57
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr);
394 jermar 58
 
391 jermar 59
/** Initialize TLB
60
 *
61
 * Initialize TLB.
62
 * Invalidate all entries and mark wired entries.
63
 */
569 jermar 64
void tlb_arch_init(void)
389 jermar 65
{
599 jermar 66
	int i;
67
 
389 jermar 68
	cp0_pagemask_write(TLB_PAGE_MASK_16K);
599 jermar 69
	cp0_entry_hi_write(0);
70
	cp0_entry_lo0_write(0);
71
	cp0_entry_lo1_write(0);
389 jermar 72
 
599 jermar 73
	/* Clear and initialize TLB. */
74
 
75
	for (i = 0; i < TLB_ENTRY_COUNT; i++) {
76
		cp0_index_write(i);
77
		tlbwi();
78
	}
612 jermar 79
 
598 jermar 80
 
389 jermar 81
	/*
82
	 * The kernel is going to make use of some wired
391 jermar 83
	 * entries (e.g. mapping kernel stacks in kseg3).
389 jermar 84
	 */
85
	cp0_wired_write(TLB_WIRED);
86
}
87
 
391 jermar 88
/** Process TLB Refill Exception
89
 *
90
 * Process TLB Refill Exception.
91
 *
958 jermar 92
 * @param istate Interrupted register context.
391 jermar 93
 */
958 jermar 94
void tlb_refill(istate_t *istate)
1 jermar 95
{
396 jermar 96
	entry_lo_t lo;
1044 jermar 97
	entry_hi_t hi;
98
	asid_t asid;
1780 jermar 99
	uintptr_t badvaddr;
391 jermar 100
	pte_t *pte;
1288 jermar 101
	int pfrc;
397 jermar 102
 
391 jermar 103
	badvaddr = cp0_badvaddr_read();
397 jermar 104
 
1044 jermar 105
	spinlock_lock(&AS->lock);
106
	asid = AS->asid;
107
	spinlock_unlock(&AS->lock);
399 jermar 108
 
1044 jermar 109
	page_table_lock(AS, true);
110
 
1411 jermar 111
	pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
1288 jermar 112
	if (!pte) {
113
		switch (pfrc) {
114
		case AS_PF_FAULT:
115
			goto fail;
116
			break;
117
		case AS_PF_DEFER:
118
			/*
119
			 * The page fault came during copy_from_uspace()
120
			 * or copy_to_uspace().
121
			 */
122
			page_table_unlock(AS, true);
123
			return;
124
		default:
125
			panic("unexpected pfrc (%d)\n", pfrc);
126
		}
127
	}
391 jermar 128
 
129
	/*
394 jermar 130
	 * Record access to PTE.
391 jermar 131
	 */
394 jermar 132
	pte->a = 1;
391 jermar 133
 
1044 jermar 134
	prepare_entry_hi(&hi, asid, badvaddr);
831 jermar 135
	prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
394 jermar 136
 
391 jermar 137
	/*
138
	 * New entry is to be inserted into TLB
139
	 */
399 jermar 140
	cp0_entry_hi_write(hi.value);
391 jermar 141
	if ((badvaddr/PAGE_SIZE) % 2 == 0) {
396 jermar 142
		cp0_entry_lo0_write(lo.value);
391 jermar 143
		cp0_entry_lo1_write(0);
144
	}
145
	else {
146
		cp0_entry_lo0_write(0);
396 jermar 147
		cp0_entry_lo1_write(lo.value);
391 jermar 148
	}
612 jermar 149
	cp0_pagemask_write(TLB_PAGE_MASK_16K);
391 jermar 150
	tlbwr();
151
 
1044 jermar 152
	page_table_unlock(AS, true);
391 jermar 153
	return;
154
 
155
fail:
1044 jermar 156
	page_table_unlock(AS, true);
958 jermar 157
	tlb_refill_fail(istate);
391 jermar 158
}
159
 
394 jermar 160
/** Process TLB Invalid Exception
161
 *
162
 * Process TLB Invalid Exception.
163
 *
958 jermar 164
 * @param istate Interrupted register context.
394 jermar 165
 */
958 jermar 166
void tlb_invalid(istate_t *istate)
391 jermar 167
{
396 jermar 168
	tlb_index_t index;
1780 jermar 169
	uintptr_t badvaddr;
396 jermar 170
	entry_lo_t lo;
399 jermar 171
	entry_hi_t hi;
394 jermar 172
	pte_t *pte;
1288 jermar 173
	int pfrc;
394 jermar 174
 
175
	badvaddr = cp0_badvaddr_read();
176
 
177
	/*
178
	 * Locate the faulting entry in TLB.
179
	 */
399 jermar 180
	hi.value = cp0_entry_hi_read();
181
	prepare_entry_hi(&hi, hi.asid, badvaddr);
182
	cp0_entry_hi_write(hi.value);
394 jermar 183
	tlbp();
396 jermar 184
	index.value = cp0_index_read();
1044 jermar 185
 
186
	page_table_lock(AS, true);	
394 jermar 187
 
188
	/*
189
	 * Fail if the entry is not in TLB.
190
	 */
396 jermar 191
	if (index.p) {
192
		printf("TLB entry not found.\n");
394 jermar 193
		goto fail;
396 jermar 194
	}
394 jermar 195
 
1411 jermar 196
	pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
1288 jermar 197
	if (!pte) {
198
		switch (pfrc) {
199
		case AS_PF_FAULT:
200
			goto fail;
201
			break;
202
		case AS_PF_DEFER:
203
			/*
204
			 * The page fault came during copy_from_uspace()
205
			 * or copy_to_uspace().
206
			 */
207
			page_table_unlock(AS, true);			 
208
			return;
209
		default:
210
			panic("unexpected pfrc (%d)\n", pfrc);
211
		}
212
	}
394 jermar 213
 
214
	/*
215
	 * Read the faulting TLB entry.
216
	 */
217
	tlbr();
218
 
219
	/*
220
	 * Record access to PTE.
221
	 */
222
	pte->a = 1;
223
 
831 jermar 224
	prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
394 jermar 225
 
226
	/*
227
	 * The entry is to be updated in TLB.
228
	 */
229
	if ((badvaddr/PAGE_SIZE) % 2 == 0)
396 jermar 230
		cp0_entry_lo0_write(lo.value);
394 jermar 231
	else
396 jermar 232
		cp0_entry_lo1_write(lo.value);
612 jermar 233
	cp0_pagemask_write(TLB_PAGE_MASK_16K);
394 jermar 234
	tlbwi();
235
 
1044 jermar 236
	page_table_unlock(AS, true);
394 jermar 237
	return;
238
 
239
fail:
1044 jermar 240
	page_table_unlock(AS, true);
958 jermar 241
	tlb_invalid_fail(istate);
391 jermar 242
}
243
 
394 jermar 244
/** Process TLB Modified Exception
245
 *
246
 * Process TLB Modified Exception.
247
 *
958 jermar 248
 * @param istate Interrupted register context.
394 jermar 249
 */
958 jermar 250
void tlb_modified(istate_t *istate)
391 jermar 251
{
396 jermar 252
	tlb_index_t index;
1780 jermar 253
	uintptr_t badvaddr;
396 jermar 254
	entry_lo_t lo;
399 jermar 255
	entry_hi_t hi;
394 jermar 256
	pte_t *pte;
1288 jermar 257
	int pfrc;
394 jermar 258
 
259
	badvaddr = cp0_badvaddr_read();
260
 
261
	/*
262
	 * Locate the faulting entry in TLB.
263
	 */
399 jermar 264
	hi.value = cp0_entry_hi_read();
265
	prepare_entry_hi(&hi, hi.asid, badvaddr);
266
	cp0_entry_hi_write(hi.value);
394 jermar 267
	tlbp();
396 jermar 268
	index.value = cp0_index_read();
1044 jermar 269
 
270
	page_table_lock(AS, true);	
394 jermar 271
 
272
	/*
273
	 * Fail if the entry is not in TLB.
274
	 */
396 jermar 275
	if (index.p) {
276
		printf("TLB entry not found.\n");
394 jermar 277
		goto fail;
396 jermar 278
	}
394 jermar 279
 
1411 jermar 280
	pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate, &pfrc);
1288 jermar 281
	if (!pte) {
282
		switch (pfrc) {
283
		case AS_PF_FAULT:
284
			goto fail;
285
			break;
286
		case AS_PF_DEFER:
287
			/*
288
			 * The page fault came during copy_from_uspace()
289
			 * or copy_to_uspace().
290
			 */
291
			page_table_unlock(AS, true);			 
292
			return;
293
		default:
294
			panic("unexpected pfrc (%d)\n", pfrc);
295
		}
296
	}
394 jermar 297
 
298
	/*
299
	 * Fail if the page is not writable.
300
	 */
301
	if (!pte->w)
302
		goto fail;
303
 
304
	/*
305
	 * Read the faulting TLB entry.
306
	 */
307
	tlbr();
308
 
309
	/*
310
	 * Record access and write to PTE.
311
	 */
312
	pte->a = 1;
831 jermar 313
	pte->d = 1;
394 jermar 314
 
831 jermar 315
	prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn);
394 jermar 316
 
317
	/*
318
	 * The entry is to be updated in TLB.
319
	 */
320
	if ((badvaddr/PAGE_SIZE) % 2 == 0)
396 jermar 321
		cp0_entry_lo0_write(lo.value);
394 jermar 322
	else
396 jermar 323
		cp0_entry_lo1_write(lo.value);
612 jermar 324
	cp0_pagemask_write(TLB_PAGE_MASK_16K);
394 jermar 325
	tlbwi();
326
 
1044 jermar 327
	page_table_unlock(AS, true);
394 jermar 328
	return;
329
 
330
fail:
1044 jermar 331
	page_table_unlock(AS, true);
958 jermar 332
	tlb_modified_fail(istate);
391 jermar 333
}
334
 
958 jermar 335
void tlb_refill_fail(istate_t *istate)
391 jermar 336
{
324 palkovsky 337
	char *symbol = "";
338
	char *sym2 = "";
339
 
958 jermar 340
	char *s = get_symtab_entry(istate->epc);
332 palkovsky 341
	if (s)
342
		symbol = s;
958 jermar 343
	s = get_symtab_entry(istate->ra);
332 palkovsky 344
	if (s)
345
		sym2 = s;
1595 palkovsky 346
 
1735 decky 347
	fault_if_from_uspace(istate, "TLB Refill Exception on %p", cp0_badvaddr_read());
348
	panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), istate->epc, symbol, sym2);
1 jermar 349
}
350
 
391 jermar 351
 
958 jermar 352
void tlb_invalid_fail(istate_t *istate)
1 jermar 353
{
268 palkovsky 354
	char *symbol = "";
355
 
958 jermar 356
	char *s = get_symtab_entry(istate->epc);
332 palkovsky 357
	if (s)
358
		symbol = s;
1735 decky 359
	fault_if_from_uspace(istate, "TLB Invalid Exception on %p", cp0_badvaddr_read());
360
	panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
1 jermar 361
}
362
 
958 jermar 363
void tlb_modified_fail(istate_t *istate)
389 jermar 364
{
365
	char *symbol = "";
366
 
958 jermar 367
	char *s = get_symtab_entry(istate->epc);
389 jermar 368
	if (s)
369
		symbol = s;
1735 decky 370
	fault_if_from_uspace(istate, "TLB Modified Exception on %p", cp0_badvaddr_read());
371
	panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
389 jermar 372
}
373
 
394 jermar 374
/** Try to find PTE for faulting address
375
 *
376
 * Try to find PTE for faulting address.
703 jermar 377
 * The AS->lock must be held on entry to this function.
394 jermar 378
 *
379
 * @param badvaddr Faulting virtual address.
1411 jermar 380
 * @param access Access mode that caused the fault.
1288 jermar 381
 * @param istate Pointer to interrupted state.
382
 * @param pfrc Pointer to variable where as_page_fault() return code will be stored.
394 jermar 383
 *
384
 * @return PTE on success, NULL otherwise.
385
 */
1780 jermar 386
pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc)
394 jermar 387
{
396 jermar 388
	entry_hi_t hi;
394 jermar 389
	pte_t *pte;
390
 
396 jermar 391
	hi.value = cp0_entry_hi_read();
394 jermar 392
 
393
	/*
394
	 * Handler cannot succeed if the ASIDs don't match.
395
	 */
703 jermar 396
	if (hi.asid != AS->asid) {
397
		printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid);
394 jermar 398
		return NULL;
396 jermar 399
	}
703 jermar 400
 
394 jermar 401
	/*
703 jermar 402
	 * Check if the mapping exists in page tables.
403
	 */	
756 jermar 404
	pte = page_mapping_find(AS, badvaddr);
831 jermar 405
	if (pte && pte->p) {
703 jermar 406
		/*
407
		 * Mapping found in page tables.
408
		 * Immediately succeed.
409
		 */
410
		return pte;
411
	} else {
1288 jermar 412
		int rc;
413
 
703 jermar 414
		/*
415
		 * Mapping not found in page tables.
416
		 * Resort to higher-level page fault handler.
417
		 */
1044 jermar 418
		page_table_unlock(AS, true);
1411 jermar 419
		switch (rc = as_page_fault(badvaddr, access, istate)) {
1288 jermar 420
		case AS_PF_OK:
703 jermar 421
			/*
422
			 * The higher-level page fault handler succeeded,
423
			 * The mapping ought to be in place.
424
			 */
1044 jermar 425
			page_table_lock(AS, true);
756 jermar 426
			pte = page_mapping_find(AS, badvaddr);
831 jermar 427
			ASSERT(pte && pte->p);
703 jermar 428
			return pte;
1288 jermar 429
			break;
430
		case AS_PF_DEFER:
1044 jermar 431
			page_table_lock(AS, true);
1288 jermar 432
			*pfrc = AS_PF_DEFER;
433
			return NULL;
434
			break;
435
		case AS_PF_FAULT:
436
			page_table_lock(AS, true);
1044 jermar 437
			printf("Page fault.\n");
1288 jermar 438
			*pfrc = AS_PF_FAULT;
1044 jermar 439
			return NULL;
1288 jermar 440
			break;
441
		default:
442
			panic("unexpected rc (%d)\n", rc);
703 jermar 443
		}
1044 jermar 444
 
703 jermar 445
	}
394 jermar 446
}
447
 
1780 jermar 448
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn)
394 jermar 449
{
399 jermar 450
	lo->value = 0;
394 jermar 451
	lo->g = g;
452
	lo->v = v;
453
	lo->d = d;
831 jermar 454
	lo->c = cacheable ? PAGE_CACHEABLE_EXC_WRITE : PAGE_UNCACHED;
394 jermar 455
	lo->pfn = pfn;
456
}
399 jermar 457
 
1780 jermar 458
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
399 jermar 459
{
983 palkovsky 460
	hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2);
399 jermar 461
	hi->asid = asid;
462
}
569 jermar 463
 
594 jermar 464
/** Print contents of TLB. */
569 jermar 465
void tlb_print(void)
466
{
612 jermar 467
	page_mask_t mask;
594 jermar 468
	entry_lo_t lo0, lo1;
704 jermar 469
	entry_hi_t hi, hi_save;
2720 decky 470
	unsigned int i;
594 jermar 471
 
704 jermar 472
	hi_save.value = cp0_entry_hi_read();
2720 decky 473
 
474
	printf("#  ASID VPN2   MASK G V D C PFN\n");
475
	printf("-- ---- ------ ---- - - - - ------\n");
476
 
594 jermar 477
	for (i = 0; i < TLB_ENTRY_COUNT; i++) {
478
		cp0_index_write(i);
479
		tlbr();
480
 
612 jermar 481
		mask.value = cp0_pagemask_read();
594 jermar 482
		hi.value = cp0_entry_hi_read();
483
		lo0.value = cp0_entry_lo0_read();
484
		lo1.value = cp0_entry_lo1_read();
485
 
2720 decky 486
		printf("%-2u %-4u %#6x %#4x %1u %1u %1u %1u %#6x\n",
487
			i, hi.asid, hi.vpn2, mask.mask,
488
			lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
489
		printf("                    %1u %1u %1u %1u %#6x\n",
490
			lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
594 jermar 491
	}
704 jermar 492
 
493
	cp0_entry_hi_write(hi_save.value);
569 jermar 494
}
598 jermar 495
 
618 jermar 496
/** Invalidate all not wired TLB entries. */
598 jermar 497
void tlb_invalidate_all(void)
498
{
599 jermar 499
	ipl_t ipl;
500
	entry_lo_t lo0, lo1;
704 jermar 501
	entry_hi_t hi_save;
598 jermar 502
	int i;
503
 
704 jermar 504
	hi_save.value = cp0_entry_hi_read();
599 jermar 505
	ipl = interrupts_disable();
598 jermar 506
 
618 jermar 507
	for (i = TLB_WIRED; i < TLB_ENTRY_COUNT; i++) {
598 jermar 508
		cp0_index_write(i);
599 jermar 509
		tlbr();
510
 
511
		lo0.value = cp0_entry_lo0_read();
512
		lo1.value = cp0_entry_lo1_read();
513
 
514
		lo0.v = 0;
515
		lo1.v = 0;
516
 
517
		cp0_entry_lo0_write(lo0.value);
518
		cp0_entry_lo1_write(lo1.value);
519
 
598 jermar 520
		tlbwi();
521
	}
599 jermar 522
 
523
	interrupts_restore(ipl);
704 jermar 524
	cp0_entry_hi_write(hi_save.value);
598 jermar 525
}
526
 
527
/** Invalidate all TLB entries belonging to specified address space.
528
 *
529
 * @param asid Address space identifier.
530
 */
531
void tlb_invalidate_asid(asid_t asid)
532
{
599 jermar 533
	ipl_t ipl;
534
	entry_lo_t lo0, lo1;
704 jermar 535
	entry_hi_t hi, hi_save;
598 jermar 536
	int i;
537
 
599 jermar 538
	ASSERT(asid != ASID_INVALID);
539
 
704 jermar 540
	hi_save.value = cp0_entry_hi_read();
599 jermar 541
	ipl = interrupts_disable();
542
 
598 jermar 543
	for (i = 0; i < TLB_ENTRY_COUNT; i++) {
544
		cp0_index_write(i);
545
		tlbr();
546
 
599 jermar 547
		hi.value = cp0_entry_hi_read();
548
 
598 jermar 549
		if (hi.asid == asid) {
599 jermar 550
			lo0.value = cp0_entry_lo0_read();
551
			lo1.value = cp0_entry_lo1_read();
552
 
553
			lo0.v = 0;
554
			lo1.v = 0;
555
 
556
			cp0_entry_lo0_write(lo0.value);
557
			cp0_entry_lo1_write(lo1.value);
558
 
598 jermar 559
			tlbwi();
560
		}
561
	}
599 jermar 562
 
563
	interrupts_restore(ipl);
704 jermar 564
	cp0_entry_hi_write(hi_save.value);
598 jermar 565
}
566
 
727 jermar 567
/** Invalidate TLB entries for specified page range belonging to specified address space.
598 jermar 568
 *
569
 * @param asid Address space identifier.
727 jermar 570
 * @param page First page whose TLB entry is to be invalidated.
571
 * @param cnt Number of entries to invalidate.
598 jermar 572
 */
1780 jermar 573
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
598 jermar 574
{
727 jermar 575
	int i;
599 jermar 576
	ipl_t ipl;
577
	entry_lo_t lo0, lo1;
704 jermar 578
	entry_hi_t hi, hi_save;
598 jermar 579
	tlb_index_t index;
580
 
599 jermar 581
	ASSERT(asid != ASID_INVALID);
582
 
704 jermar 583
	hi_save.value = cp0_entry_hi_read();
599 jermar 584
	ipl = interrupts_disable();
585
 
983 palkovsky 586
	for (i = 0; i < cnt+1; i+=2) {
727 jermar 587
		hi.value = 0;
588
		prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
589
		cp0_entry_hi_write(hi.value);
599 jermar 590
 
727 jermar 591
		tlbp();
592
		index.value = cp0_index_read();
598 jermar 593
 
727 jermar 594
		if (!index.p) {
595
			/* Entry was found, index register contains valid index. */
596
			tlbr();
599 jermar 597
 
727 jermar 598
			lo0.value = cp0_entry_lo0_read();
599
			lo1.value = cp0_entry_lo1_read();
599 jermar 600
 
727 jermar 601
			lo0.v = 0;
602
			lo1.v = 0;
599 jermar 603
 
727 jermar 604
			cp0_entry_lo0_write(lo0.value);
605
			cp0_entry_lo1_write(lo1.value);
599 jermar 606
 
727 jermar 607
			tlbwi();
608
		}
598 jermar 609
	}
599 jermar 610
 
611
	interrupts_restore(ipl);
704 jermar 612
	cp0_entry_hi_write(hi_save.value);
598 jermar 613
}
1702 cejka 614
 
1776 jermar 615
/** @}
1702 cejka 616
 */