Subversion Repositories HelenOS

Rev

Rev 2725 | Rev 3230 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Jakub 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.  
  29. /** @addtogroup mips32mm   
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <macros.h>
  36. #include <arch/mm/frame.h>
  37. #include <arch/mm/tlb.h>
  38. #include <mm/frame.h>
  39. #include <mm/asid.h>
  40. #include <config.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.  
  153.  
  154. /** Create memory zones
  155.  *
  156.  * Walk through available 1 MB chunks of physical
  157.  * memory and create zones.
  158.  *
  159.  */
  160. void frame_arch_init(void)
  161. {
  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.         }
  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.     }  
  237. }
  238.  
  239. /** @}
  240.  */
  241.