Changeset edebc15c in mainline for kernel/arch/mips32/src/mm/frame.c
- Timestamp:
- 2008-07-27T03:50:53Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4541ae4
- Parents:
- 5e8ddf5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/mm/frame.c
r5e8ddf5 redebc15c 33 33 */ 34 34 35 #include <macros.h> 35 36 #include <arch/mm/frame.h> 37 #include <arch/mm/tlb.h> 36 38 #include <mm/frame.h> 39 #include <mm/asid.h> 37 40 #include <config.h> 38 #include <arch/drivers/arc.h> 41 #include <arch/drivers/msim.h> 42 #include <arch/drivers/serial.h> 43 #include <print.h> 44 #include <debug.h> 45 46 #define TLB_PAGE_MASK_1M (0xff << 13) 47 48 #define ZERO_FRAMES 4096 49 #define ZERO_PAGE_WIDTH 20 /* 1M */ 50 #define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH) 51 #define ZERO_PAGE_ASID ASID_INVALID 52 #define ZERO_PAGE_TLBI 0 53 #define ZERO_PAGE_ADDR 0 54 #define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1) 55 #define ZERO_PAGE_VALUE (*((volatile uint32_t *) ZERO_PAGE_ADDR + ZERO_PAGE_OFFSET)) 56 57 #define MAX_REGIONS 32 58 59 typedef struct { 60 pfn_t start; 61 pfn_t count; 62 } phys_region_t; 63 64 static count_t phys_regions_count = 0; 65 static phys_region_t phys_regions[MAX_REGIONS]; 66 67 68 /** Check whether frame is available 69 * 70 * Returns true if given frame is generally available for use. 71 * Returns false if given frame is used for physical memory 72 * mapped devices and cannot be used. 73 * 74 */ 75 static bool frame_available(pfn_t frame) 76 { 77 /* MSIM device (dprinter) */ 78 if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH)) 79 return false; 80 81 /* MSIM device (dkeyboard) */ 82 if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH)) 83 return false; 84 85 /* Simics device (serial line) */ 86 if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH)) 87 return false; 88 89 return true; 90 } 91 92 93 /** Check whether frame is safe to write 94 * 95 * Returns true if given frame is safe for read/write test. 96 * Returns false if given frame should not be touched. 97 * 98 */ 99 static bool frame_safe(pfn_t frame) __attribute__((unused)); 100 static bool frame_safe(pfn_t frame) 101 { 102 /* Kernel structures */ 103 if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base)) 104 return false; 105 106 /* Kernel */ 107 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, 108 KA2PA(config.base), config.kernel_size)) 109 return false; 110 111 /* Kernel stack */ 112 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, 113 KA2PA(config.stack_base), config.stack_size)) 114 return false; 115 116 /* Init tasks */ 117 bool safe = true; 118 count_t i; 119 for (i = 0; i < init.cnt; i++) 120 if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE, 121 KA2PA(init.tasks[i].addr), init.tasks[i].size)) { 122 safe = false; 123 break; 124 } 125 126 return safe; 127 } 128 129 static void frame_add_region(pfn_t start_frame, pfn_t end_frame) 130 { 131 if (end_frame > start_frame) { 132 /* Convert 1M frames to 16K frames */ 133 pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH); 134 pfn_t count = ADDR2PFN((end_frame - start_frame - 1) << ZERO_PAGE_WIDTH); 135 136 /* Interrupt vector frame is blacklisted */ 137 pfn_t conf_frame; 138 if (start_frame == 0) 139 conf_frame = 1; 140 else 141 conf_frame = first; 142 143 zone_create(first, count, conf_frame, 0); 144 145 if (phys_regions_count < MAX_REGIONS) { 146 phys_regions[phys_regions_count].start = first; 147 phys_regions[phys_regions_count].count = count; 148 phys_regions_count++; 149 } 150 } 151 } 152 39 153 40 154 /** Create memory zones 41 155 * 42 * If ARC is known, read information from ARC, otherwise43 * assume some defaults.44 * - blacklist first FRAME because there is an exception vector156 * Walk through available 1 MB chunks of physical 157 * memory and create zones. 158 * 45 159 */ 46 160 void frame_arch_init(void) 47 161 { 48 if (!arc_frame_init()) { 49 zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0); 50 /* 51 * Blacklist interrupt vector 52 */ 53 frame_mark_unavailable(0, 1); 162 cp0_index_write(ZERO_PAGE_TLBI); 163 tlbr(); 164 165 uint32_t orig_pagemask = cp0_pagemask_read(); 166 uint32_t orig_lo0 = cp0_entry_lo0_read(); 167 uint32_t orig_lo1 = cp0_entry_lo1_read(); 168 uint32_t orig_hi = cp0_entry_hi_read(); 169 170 pfn_t start_frame = 0; 171 pfn_t frame; 172 bool avail = true; 173 174 /* Walk through all 1 MB frames */ 175 for (frame = 0; frame < ZERO_FRAMES; frame++) { 176 if (!frame_available(frame)) 177 avail = false; 178 else { 179 if (frame_safe(frame)) { 180 entry_lo_t lo0; 181 entry_lo_t lo1; 182 entry_hi_t hi; 183 tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12)); 184 tlb_prepare_entry_lo(&lo1, false, false, false, false, 0); 185 tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR); 186 187 cp0_index_write(ZERO_PAGE_TLBI); 188 cp0_pagemask_write(TLB_PAGE_MASK_1M); 189 cp0_entry_lo0_write(lo0.value); 190 cp0_entry_lo1_write(lo1.value); 191 cp0_entry_hi_write(hi.value); 192 tlbwi(); 193 194 ZERO_PAGE_VALUE = 0; 195 if (ZERO_PAGE_VALUE != 0) 196 avail = false; 197 else { 198 ZERO_PAGE_VALUE = 0xdeadbeef; 199 if (ZERO_PAGE_VALUE != 0xdeadbeef) 200 avail = false; 201 } 202 } 203 } 204 205 if (!avail) { 206 frame_add_region(start_frame, frame); 207 start_frame = frame + 1; 208 avail = true; 209 } 54 210 } 211 212 frame_add_region(start_frame, frame); 213 214 /* Cleanup TLB */ 215 cp0_index_write(ZERO_PAGE_TLBI); 216 cp0_pagemask_write(orig_pagemask); 217 cp0_entry_lo0_write(orig_lo0); 218 cp0_entry_lo1_write(orig_lo1); 219 cp0_entry_hi_write(orig_hi); 220 tlbwi(); 221 222 /* Blacklist interrupt vector frame */ 223 frame_mark_unavailable(0, 1); 224 } 225 226 227 void physmem_print(void) 228 { 229 printf("Base Size\n"); 230 printf("---------- ----------\n"); 231 232 count_t i; 233 for (i = 0; i < phys_regions_count; i++) { 234 printf("%#10x %10u\n", 235 PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count)); 236 } 55 237 } 56 238
Note:
See TracChangeset
for help on using the changeset viewer.