[BACK]Return to mm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / amd64 / stand / prekern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/arch/amd64/stand/prekern/mm.c between version 1.5 and 1.6

version 1.5, 2017/10/28 19:28:11 version 1.6, 2017/10/29 11:28:30
Line 37  static const pt_entry_t protection_codes
Line 37  static const pt_entry_t protection_codes
         /* RWX does not exist */          /* RWX does not exist */
 };  };
   
   struct bootspace bootspace;
   
 extern paddr_t kernpa_start, kernpa_end;  extern paddr_t kernpa_start, kernpa_end;
 vaddr_t iom_base;  vaddr_t iom_base;
   
Line 168  mm_map_tree(vaddr_t startva, vaddr_t end
Line 170  mm_map_tree(vaddr_t startva, vaddr_t end
         }          }
 }  }
   
 /*  static uint64_t
  * Select a random VA, and create a page tree. The size of this tree is  mm_rand_num64()
  * actually hard-coded, and matches the one created by the generic NetBSD  {
  * locore.          /* XXX: yes, this is ridiculous, will be fixed soon */
  */          return rdtsc();
   }
   
   static void
   mm_map_head()
   {
           size_t i, npages, size;
           uint64_t rnd;
           vaddr_t randva;
   
           /*
            * To get the size of the head, we give a look at the read-only
            * mapping of the kernel we created in locore. We're identity mapped,
            * so kernpa = kernva.
            */
           size = elf_get_head_size((vaddr_t)kernpa_start);
           npages = size / PAGE_SIZE;
   
           rnd = mm_rand_num64();
           randva = rounddown(HEAD_WINDOW_BASE + rnd % (HEAD_WINDOW_SIZE - size),
               PAGE_SIZE);
           mm_map_tree(randva, randva + size);
   
           /* Enter the area and build the ELF info */
           for (i = 0; i < npages; i++) {
                   mm_enter_pa(kernpa_start + i * PAGE_SIZE,
                       randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
           }
           elf_build_head(randva);
   
           /* Register the values in bootspace */
           bootspace.head.va = randva;
           bootspace.head.pa = kernpa_start;
           bootspace.head.sz = size;
   }
   
 static vaddr_t  static vaddr_t
 mm_rand_base()  mm_randva_kregion(size_t size)
 {  {
           static struct {
                   vaddr_t sva;
                   vaddr_t eva;
           } regions[4];
           static size_t idx = 0;
         vaddr_t randva;          vaddr_t randva;
         uint64_t rnd;          uint64_t rnd;
         size_t size;          size_t i;
           bool ok;
   
         size = (NKL2_KIMG_ENTRIES + 1) * NBPD_L2;          ASSERT(idx < 4);
   
         /* XXX: yes, this is ridiculous, will be fixed soon */          while (1) {
         rnd = rdtsc();                  rnd = mm_rand_num64();
         randva = rounddown(KASLR_WINDOW_BASE + rnd % (KASLR_WINDOW_SIZE - size),                  randva = rounddown(KASLR_WINDOW_BASE +
             PAGE_SIZE);                      rnd % (KASLR_WINDOW_SIZE - size), PAGE_SIZE);
   
                   /* Detect collisions */
                   ok = true;
                   for (i = 0; i < idx; i++) {
                           if ((regions[i].sva <= randva) &&
                               (randva < regions[i].eva)) {
                                   ok = false;
                                   break;
                           }
                           if ((regions[i].sva < randva + size) &&
                               (randva + size <= regions[i].eva)) {
                                   ok = false;
                                   break;
                           }
                   }
                   if (ok) {
                           break;
                   }
           }
   
           regions[idx].eva = randva;
           regions[idx].sva = randva + size;
           idx++;
   
         mm_map_tree(randva, randva + size);          mm_map_tree(randva, randva + size);
   
         return randva;          return randva;
 }  }
   
 /*  static void
  * Virtual address space of the kernel:  mm_map_segments()
  * +---------------+---------------------+------------------+-------------+  
  * | KERNEL + SYMS | [PRELOADED MODULES] | BOOTSTRAP TABLES | ISA I/O MEM |  
  * +---------------+---------------------+------------------+-------------+  
  * We basically choose a random VA, and map everything contiguously starting  
  * from there. Note that the physical pages allocated by mm_palloc are part  
  * of the BOOTSTRAP TABLES.  
  */  
 vaddr_t  
 mm_map_kernel()  
 {  {
         size_t i, npages, size;          size_t i, npages, size;
         vaddr_t baseva;          vaddr_t randva;
           paddr_t pa;
   
         size = (pa_avail - kernpa_start);          /*
         baseva = mm_rand_base();           * Kernel text segment.
            */
           elf_get_text(&pa, &size);
           randva = mm_randva_kregion(size);
         npages = size / PAGE_SIZE;          npages = size / PAGE_SIZE;
   
         /* Enter the whole area linearly */          /* Enter the area and build the ELF info */
         for (i = 0; i < npages; i++) {          for (i = 0; i < npages; i++) {
                 mm_enter_pa(kernpa_start + i * PAGE_SIZE,                  mm_enter_pa(pa + i * PAGE_SIZE,
                     baseva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);                      randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
         }          }
           elf_build_text(randva, pa, size);
   
           /* Register the values in bootspace */
           bootspace.text.va = randva;
           bootspace.text.pa = pa;
           bootspace.text.sz = size;
   
           /*
            * Kernel rodata segment.
            */
           elf_get_rodata(&pa, &size);
           randva = mm_randva_kregion(size);
           npages = size / PAGE_SIZE;
   
           /* Enter the area and build the ELF info */
           for (i = 0; i < npages; i++) {
                   mm_enter_pa(pa + i * PAGE_SIZE,
                       randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
           }
           elf_build_rodata(randva, pa, size);
   
           /* Register the values in bootspace */
           bootspace.rodata.va = randva;
           bootspace.rodata.pa = pa;
           bootspace.rodata.sz = size;
   
           /*
            * Kernel data segment.
            */
           elf_get_data(&pa, &size);
           randva = mm_randva_kregion(size);
           npages = size / PAGE_SIZE;
   
           /* Enter the area and build the ELF info */
           for (i = 0; i < npages; i++) {
                   mm_enter_pa(pa + i * PAGE_SIZE,
                       randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
           }
           elf_build_data(randva, pa, size);
   
           /* Register the values in bootspace */
           bootspace.data.va = randva;
           bootspace.data.pa = pa;
           bootspace.data.sz = size;
   }
   
   static void
   mm_map_boot()
   {
           size_t i, npages, size;
           vaddr_t randva;
           paddr_t bootpa;
   
           /*
            * The "boot" region is special: its page tree has a fixed size, but
            * the number of pages entered is lower.
            */
   
           /* Create the page tree */
           size = (NKL2_KIMG_ENTRIES + 1) * NBPD_L2;
           randva = mm_randva_kregion(size);
   
           /* Enter the area and build the ELF info */
           bootpa = bootspace.data.pa + bootspace.data.sz;
           size = (pa_avail - bootpa);
           npages = size / PAGE_SIZE;
           for (i = 0; i < npages; i++) {
                   mm_enter_pa(bootpa + i * PAGE_SIZE,
                       randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
           }
           elf_build_boot(randva, bootpa);
   
         /* Enter the ISA I/O MEM */          /* Enter the ISA I/O MEM */
         iom_base = baseva + npages * PAGE_SIZE;          iom_base = randva + npages * PAGE_SIZE;
         npages = IOM_SIZE / PAGE_SIZE;          npages = IOM_SIZE / PAGE_SIZE;
         for (i = 0; i < npages; i++) {          for (i = 0; i < npages; i++) {
                 mm_enter_pa(IOM_BEGIN + i * PAGE_SIZE,                  mm_enter_pa(IOM_BEGIN + i * PAGE_SIZE,
                     iom_base + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);                      iom_base + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
         }          }
   
         return baseva;          /* Register the values in bootspace */
           bootspace.boot.va = randva;
           bootspace.boot.pa = bootpa;
           bootspace.boot.sz = (size_t)(iom_base + IOM_SIZE) -
               (size_t)bootspace.boot.va;
   
           /* Initialize the values that are located in the "boot" region */
           extern uint64_t PDPpaddr;
           bootspace.spareva = bootspace.boot.va + NKL2_KIMG_ENTRIES * NBPD_L2;
           bootspace.pdir = bootspace.boot.va + (PDPpaddr - bootspace.boot.pa);
           bootspace.emodule = bootspace.boot.va + NKL2_KIMG_ENTRIES * NBPD_L2;
   }
   
   /*
    * There are five independent regions: head, text, rodata, data, boot. They are
    * all mapped at random VAs.
    *
    * Head contains the ELF Header and ELF Section Headers, and we use them to
    * map the rest of the regions. Head must be placed in memory *before* the
    * other regions.
    *
    * At the end of this function, the bootspace structure is fully constructed.
    */
   void
   mm_map_kernel()
   {
           memset(&bootspace, 0, sizeof(bootspace));
           mm_map_head();
           mm_map_segments();
           mm_map_boot();
 }  }
   

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.6

CVSweb <webmaster@jp.NetBSD.org>