Changeset edebc15c in mainline for kernel/arch/mips32/src/mm/frame.c


Ignore:
Timestamp:
2008-07-27T03:50:53Z (17 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4541ae4
Parents:
5e8ddf5
Message:

physical memory detection in MSIM (discontinous regions supported)
remove Sgi Indy (ARC) support — it was unmaintaned, untested for years and without uspace support

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/mips32/src/mm/frame.c

    r5e8ddf5 redebc15c  
    3333 */
    3434
     35#include <macros.h>
    3536#include <arch/mm/frame.h>
     37#include <arch/mm/tlb.h>
    3638#include <mm/frame.h>
     39#include <mm/asid.h>
    3740#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
     59typedef struct {
     60        pfn_t start;
     61        pfn_t count;
     62} phys_region_t;
     63
     64static count_t phys_regions_count = 0;
     65static 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 */
     75static 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 */
     99static bool frame_safe(pfn_t frame) __attribute__((unused));
     100static 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
     129static 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
    39153
    40154/** Create memory zones
    41155 *
    42  * If ARC is known, read information from ARC, otherwise
    43  * assume some defaults.
    44  * - blacklist first FRAME because there is an exception vector
     156 * Walk through available 1 MB chunks of physical
     157 * memory and create zones.
     158 *
    45159 */
    46160void frame_arch_init(void)
    47161{
    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                }
    54210        }
     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
     227void 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        }       
    55237}
    56238
Note: See TracChangeset for help on using the changeset viewer.