2 * This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; version 2 of
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <console/console.h>
21 #define MIN_PAGE_SIZE (4 * KiB)
23 static int add_wired_tlb_entry(uint32_t entrylo0
, uint32_t entrylo1
,
24 uint32_t entryhi
, uint32_t pgsize
)
28 tlbindex
= read_c0_wired();
29 if (tlbindex
>= get_tlb_size() || tlbindex
>= C0_WIRED_MASK
) {
30 printk(BIOS_ERR
, "Ran out of TLB entries\n");
33 write_c0_wired(tlbindex
+ 1);
34 write_c0_index(tlbindex
);
35 write_c0_pagemask(((pgsize
/ MIN_PAGE_SIZE
) - 1) << C0_PAGEMASK_SHIFT
);
36 write_c0_entryhi(entryhi
);
37 write_c0_entrylo0(entrylo0
);
38 write_c0_entrylo1(entrylo1
);
46 static uint32_t pick_pagesize(uint32_t start
, uint32_t len
)
48 uint32_t pgsize
, max_pgsize
;
50 max_pgsize
= get_max_pagesize();
51 for (pgsize
= max_pgsize
;
52 pgsize
>= MIN_PAGE_SIZE
;
53 pgsize
= pgsize
/ 4) {
55 * Each TLB entry maps a pair of virtual pages. To avoid
56 * aliasing, pick the largest page size that is at most
57 * half the size of the region we're trying to map.
59 if (IS_ALIGNED(start
, 2 * pgsize
) && (2 * pgsize
<= len
))
67 * Identity map the memory from [start,start+len] in the TLB using the
68 * largest suitable page size so as to conserve TLB entries.
70 int identity_map(uint32_t start
, size_t len
, uint32_t coherency
)
72 uint32_t pgsize
, pfn
, entryhi
, entrylo0
, entrylo1
;
74 coherency
&= C0_ENTRYLO_COHERENCY_MASK
;
76 pgsize
= pick_pagesize(start
, len
);
79 entrylo0
= (pfn
<< C0_ENTRYLO_PFN_SHIFT
) | coherency
|
80 C0_ENTRYLO_D
| C0_ENTRYLO_V
| C0_ENTRYLO_G
;
82 len
-= MIN(len
, pgsize
);
85 entrylo1
= (pfn
<< C0_ENTRYLO_PFN_SHIFT
) |
86 coherency
| C0_ENTRYLO_D
| C0_ENTRYLO_V
|
89 len
-= MIN(len
, pgsize
);
93 if (add_wired_tlb_entry(entrylo0
, entrylo1
, entryhi
, pgsize
))