Subversion Repositories HelenOS

Rev

Rev 3966 | Rev 4108 | 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 <interrupt.h>
  39. #include <mm/frame.h>
  40. #include <mm/asid.h>
  41. #include <config.h>
  42. #include <arch/drivers/msim.h>
  43. #include <arch/drivers/serial.h>
  44. #include <print.h>
  45.  
  46. #define ZERO_PAGE_MASK      TLB_PAGE_MASK_256K
  47. #define ZERO_FRAMES         2048
  48. #define ZERO_PAGE_WIDTH     18  /* 256K */
  49. #define ZERO_PAGE_SIZE      (1 << ZERO_PAGE_WIDTH)
  50. #define ZERO_PAGE_ASID      ASID_INVALID
  51. #define ZERO_PAGE_TLBI      0
  52. #define ZERO_PAGE_ADDR      0
  53. #define ZERO_PAGE_OFFSET    (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
  54. #define ZERO_PAGE_VALUE     (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
  55.  
  56. #define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
  57.  
  58. #define MAX_REGIONS         32
  59.  
  60. typedef struct {
  61.     pfn_t start;
  62.     pfn_t count;
  63. } phys_region_t;
  64.  
  65. static count_t phys_regions_count = 0;
  66. static phys_region_t phys_regions[MAX_REGIONS];
  67.  
  68. uintptr_t end_frame = 0;
  69.  
  70.  
  71. /** Check whether frame is available
  72.  *
  73.  * Returns true if given frame is generally available for use.
  74.  * Returns false if given frame is used for physical memory
  75.  * mapped devices and cannot be used.
  76.  *
  77.  */
  78. static bool frame_available(pfn_t frame)
  79. {
  80. #ifdef MACHINE_msim
  81.     /* MSIM device (dprinter) */
  82.     if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
  83.         return false;
  84.    
  85.     /* MSIM device (dkeyboard) */
  86.     if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
  87.         return false;
  88. #endif
  89.  
  90. #ifdef MACHINE_simics
  91.     /* Simics device (serial line) */
  92.     if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
  93.         return false;
  94. #endif
  95.  
  96. #if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
  97.     /* gxemul devices */
  98.     if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
  99.         0x10000000, MB2SIZE(256)))
  100.         return false;
  101. #endif
  102.    
  103.     return true;
  104. }
  105.  
  106.  
  107. /** Check whether frame is safe to write
  108.  *
  109.  * Returns true if given frame is safe for read/write test.
  110.  * Returns false if given frame should not be touched.
  111.  *
  112.  */
  113. static bool frame_safe(pfn_t frame)
  114. {
  115.     /* Kernel structures */
  116.     if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
  117.         return false;
  118.    
  119.     /* Kernel */
  120.     if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
  121.         KA2PA(config.base), config.kernel_size))
  122.         return false;
  123.    
  124.     /* Kernel stack */
  125.     if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
  126.         KA2PA(config.stack_base), config.stack_size))
  127.         return false;
  128.    
  129.     /* Init tasks */
  130.     bool safe = true;
  131.     count_t i;
  132.     for (i = 0; i < init.cnt; i++)
  133.         if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
  134.             KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
  135.             safe = false;
  136.             break;
  137.         }
  138.    
  139.     return safe;
  140. }
  141.  
  142. static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
  143. {
  144.     if (end_frame > start_frame) {
  145.         /* Convert 1M frames to 16K frames */
  146.         pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
  147.         pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
  148.        
  149.         /* Interrupt vector frame is blacklisted */
  150.         pfn_t conf_frame;
  151.         if (first == 0)
  152.             conf_frame = 1;
  153.         else
  154.             conf_frame = first;
  155.        
  156.         zone_create(first, count, conf_frame, 0);
  157.        
  158.         if (phys_regions_count < MAX_REGIONS) {
  159.             phys_regions[phys_regions_count].start = first;
  160.             phys_regions[phys_regions_count].count = count;
  161.             phys_regions_count++;
  162.         }
  163.     }
  164. }
  165.  
  166.  
  167. /** Create memory zones
  168.  *
  169.  * Walk through available 256 KB chunks of physical
  170.  * memory and create zones.
  171.  *
  172.  * Note: It is assumed that the TLB is not yet being
  173.  * used in any way, thus there is no interference.
  174.  *
  175.  */
  176. void frame_arch_init(void)
  177. {
  178.     ipl_t ipl = interrupts_disable();
  179.    
  180.     /* Clear and initialize TLB */
  181.     cp0_pagemask_write(ZERO_PAGE_MASK);
  182.     cp0_entry_lo0_write(0);
  183.     cp0_entry_lo1_write(0);
  184.     cp0_entry_hi_write(0);
  185.  
  186.     count_t i;
  187.     for (i = 0; i < TLB_ENTRY_COUNT; i++) {
  188.         cp0_index_write(i);
  189.         tlbwi();
  190.     }
  191.        
  192.     pfn_t start_frame = 0;
  193.     pfn_t frame;
  194.     bool avail = true;
  195.    
  196.     /* Walk through all 1 MB frames */
  197.     for (frame = 0; frame < ZERO_FRAMES; frame++) {
  198.         if (!frame_available(frame))
  199.             avail = false;
  200.         else {
  201.             if (frame_safe(frame)) {
  202.                 entry_lo_t lo0;
  203.                 entry_lo_t lo1;
  204.                 entry_hi_t hi;
  205.                 tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
  206.                 tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
  207.                 tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
  208.                
  209.                 cp0_pagemask_write(ZERO_PAGE_MASK);
  210.                 cp0_entry_lo0_write(lo0.value);
  211.                 cp0_entry_lo1_write(lo1.value);
  212.                 cp0_entry_hi_write(hi.value);
  213.                 cp0_index_write(ZERO_PAGE_TLBI);
  214.                 tlbwi();
  215.                
  216.                 ZERO_PAGE_VALUE = 0;
  217.                 if (ZERO_PAGE_VALUE != 0)
  218.                     avail = false;
  219.                 else {
  220.                     ZERO_PAGE_VALUE = 0xdeadbeef;
  221.                     if (ZERO_PAGE_VALUE != 0xdeadbeef)
  222.                         avail = false;
  223. #if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
  224.                     else {
  225.                         ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
  226.                         if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
  227.                             avail = false;
  228.                     }
  229. #endif
  230.                 }
  231.             }
  232.         }
  233.        
  234.         if (!avail) {
  235.             frame_add_region(start_frame, frame);
  236.             start_frame = frame + 1;
  237.             avail = true;
  238.         }
  239.     }
  240.    
  241.     end_frame = frame;
  242.    
  243.     frame_add_region(start_frame, end_frame);
  244.    
  245.     /* Blacklist interrupt vector frame */
  246.     frame_mark_unavailable(0, 1);
  247.    
  248.     /* Cleanup */
  249.     cp0_pagemask_write(ZERO_PAGE_MASK);
  250.     cp0_entry_lo0_write(0);
  251.     cp0_entry_lo1_write(0);
  252.     cp0_entry_hi_write(0);
  253.     cp0_index_write(ZERO_PAGE_TLBI);
  254.     tlbwi();
  255.    
  256.     interrupts_restore(ipl);
  257. }
  258.  
  259.  
  260. void physmem_print(void)
  261. {
  262.     printf("Base       Size\n");
  263.     printf("---------- ----------\n");
  264.    
  265.     count_t i;
  266.     for (i = 0; i < phys_regions_count; i++) {
  267.         printf("%#010x %10u\n",
  268.             PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
  269.     }  
  270. }
  271.  
  272. /** @}
  273.  */
  274.