Advertisement
Guest User

Untitled

a guest
Nov 5th, 2020
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.72 KB | None | 0 0
  1. #include "paging.h"
  2. #include "asm.h"
  3. #include "pfa.h"
  4. #include "bootscreen_output.h"
  5.  
  6. #define putline printInt(__LINE__); \
  7.                 putc('\n')
  8.  
  9. #ifndef SWAPFILE_NOT_REQUIRED
  10. // Include the filesystem driver
  11. #endif
  12.  
  13. #include "utils.h"
  14.  
  15. #define SET(field) field |= 0b1
  16. #define CLEAR(field) field &= 0b0
  17.  
  18.  
  19. typedef struct {
  20.     uint8_t present : 1;
  21.     uint8_t read_write : 1;
  22.     uint8_t user_supervisor : 1;
  23.     uint8_t cache_policy : 1;
  24.     uint8_t cache_disable : 1;
  25.     uint8_t accessed : 1;
  26.     uint8_t reserved : 3; // Must be 0b000
  27.     uint8_t avl_3 : 3;
  28.     uint64_t pdp_addr : 40;
  29.     uint16_t avl_11 : 11;
  30.     uint8_t no_execute : 1;
  31. } PML4entry;
  32.  
  33. typedef struct {
  34.     uint8_t present : 1;
  35.     uint8_t read_write : 1;
  36.     uint8_t user_supervisor : 1;
  37.     uint8_t cache_policy : 1;
  38.     uint8_t cache_disable : 1;
  39.     uint8_t accessed : 1;
  40.     uint8_t mbz : 3; // Must be 0 to also ensure it corresponds to 4kb paging
  41.     uint8_t avl_3 : 3;
  42.     uint64_t pd_addr : 40;
  43.     uint16_t avl_11 : 11;
  44.     uint8_t no_execute : 1;
  45. } PDPentry;
  46.  
  47. typedef struct {
  48.     uint8_t present : 1;
  49.     uint8_t read_write : 1;
  50.     uint8_t user_supervisor : 1;
  51.     uint8_t cache_policy : 1;
  52.     uint8_t cache_disable : 1;
  53.     uint8_t accessed : 1;
  54.     uint8_t mbz : 3; // Must be 0 to also ensure it corresponds to 4kb paging
  55.     uint8_t avl_3 : 3;
  56.     uint64_t pt_addr : 40;
  57.     uint16_t avl_11 : 11;
  58.     uint8_t no_execute : 1;
  59.  
  60. } PDentry;
  61.  
  62. typedef struct {
  63.     uint8_t present : 1;
  64.     uint8_t read_write : 1;
  65.     uint8_t user_supervisor : 1;
  66.     uint8_t cache_policy : 1;
  67.     uint8_t cache_disable : 1;
  68.     uint8_t accessed : 1;
  69.     uint8_t dirty : 1;
  70.     uint8_t pat : 1;
  71.     uint8_t global : 1;
  72.     uint8_t avl_3 : 3;
  73.     uint64_t page_base_addr : 40;
  74.     uint16_t avl_11 : 11;
  75.     uint8_t no_execute : 1;
  76. } PTentry;
  77.  
  78. #define GET_PGTADDR(x) x & 0b0000000000001111111111111111111111111111111111111111000000000000
  79.  
  80. /* Initialised from EFI's tables */
  81. static PML4entry* PML4tab;
  82. static PDPentry* PDPtab;
  83. static PDentry* PDtab;
  84. static PTentry* PTtab;
  85.  
  86. static void* make_canonical(void* addr) {
  87.     size_t naddr = (size_t)addr;
  88.     if (naddr & ((size_t)1 << 47))
  89.         naddr |= 0xFFFF000000000000;
  90.     return (void*)naddr;
  91. }
  92.  
  93. static void* decanonical(void* addr) {
  94.     return (void*)((size_t)addr & 0x0000FFFFFFFFFFFF);
  95. }
  96.  
  97. void paging_init() {
  98.     /* Find the page tables EFI has set up. Each entry points to the lower page table */
  99.     PML4tab = (PML4entry*)pfa_alloc();
  100.     PDPtab = (PDPentry*)pfa_alloc();
  101.     PDtab = (PDentry*)pfa_alloc();
  102.     PTtab = (PTentry*)pfa_alloc();
  103.  
  104.     void* pml4base = read_cr3();
  105.     uint64_t cr0 = read_cr0();
  106.     write_cr0(cr0 & (SIZE_MAX - (1 << 16))); // Disable WP and paging for now
  107.     void* pdpbase;
  108.     void* pdbase;
  109.     void* ptbase;
  110.  
  111.     uint8_t req_pdp = 0, req_pd = 0, req_pt = 0;
  112.  
  113.     /* You have to pfa_alloc for the page tables or initialise them, then relocate the entries. */
  114.     /* We can wipe all the bits - we have control of the page tables now. */
  115.  
  116.     for (uint16_t i = 0; i < 512; i++)
  117.     {
  118.         uint64_t pml4e = *((uint64_t*)pml4base + i);
  119.         if ((pml4e & 0x1) && !req_pdp)
  120.         {
  121.             printLn("Valid entry in the pml4 table found");
  122.             pdpbase = (void*)(GET_PGTADDR(pml4e));
  123.             req_pdp = 1;
  124.         }
  125.         PML4entry pml4_new_e;
  126.         pml4_new_e.present = pml4e & 0b1;
  127.         pml4_new_e.read_write = (pml4e >> 1) & 0b1;
  128.         pml4_new_e.user_supervisor = (pml4e >> 2) & 0b1;
  129.         pml4_new_e.cache_policy = (pml4e >> 3) & 0b1;
  130.         pml4_new_e.cache_disable = (pml4e >> 4) & 0b1;
  131.         pml4_new_e.accessed = (pml4e >> 5) & 0b1;
  132.         pml4_new_e.reserved = 0;
  133.         pml4_new_e.avl_3 = 0;
  134.         pml4_new_e.pdp_addr = (uint64_t)PDPtab >> 12;
  135.         pml4_new_e.avl_11 = 0;
  136.         pml4_new_e.no_execute = (pml4e >> 63) & 0b1;
  137.  
  138.         PML4tab[i] = pml4_new_e;
  139.         tlbflush(PML4tab);
  140.     }
  141.  
  142.     printLn("Finished writing in PML4 entries");
  143.  
  144.     for (int i = 0; i < 512; i++)
  145.     {
  146.         if (PML4tab[i].present) {
  147.             printLn("Found present section");
  148.             printInt(PML4tab[i].pdp_addr);
  149.         }
  150.     }
  151.  
  152.     for (uint16_t i = 0; i < 512; i++)
  153.     {
  154.         uint64_t pdpe = *((uint64_t*)pdpbase + i);
  155.         if ((pdpe & 0x1) && !req_pd)
  156.         {
  157.             printLn("Valid entry in the pdp table found");
  158.             pdbase = (void*)(GET_PGTADDR(pdpe));
  159.             req_pd = 1;
  160.         }
  161.         PDPentry pdp_new_e;
  162.         pdp_new_e.present = pdpe & 0b1;
  163.         pdp_new_e.read_write = (pdpe >> 1) & 0b1;
  164.         pdp_new_e.user_supervisor = (pdpe >> 2) & 0b1;
  165.         pdp_new_e.cache_policy = (pdpe >> 3) & 0b1;
  166.         pdp_new_e.cache_disable = (pdpe >> 4) & 0b1;
  167.         pdp_new_e.accessed = (pdpe >> 5) & 0b1;
  168.         pdp_new_e.mbz = 0b000;
  169.         pdp_new_e.avl_3 = 0;
  170.         pdp_new_e.pd_addr = (uint64_t)PDtab >> 12;
  171.         pdp_new_e.avl_11 = 0;
  172.         pdp_new_e.no_execute = (pdpe >> 63) & 0b1;
  173.  
  174.         PDPtab[i] = pdp_new_e;
  175.         tlbflush(PDPtab);
  176.     }
  177.  
  178.     printLn("Finished writing in PDP entries");
  179.  
  180.     for (uint16_t i = 0; i < 512; i++)
  181.     {
  182.         uint64_t pde = *((uint64_t*)pdbase + i);
  183.         if ((pde & 0x1) && !req_pt)
  184.         {
  185.             printLn("Valid entry in the pd table found");
  186.             ptbase = (void*)(GET_PGTADDR(pde));
  187.             req_pt = 1;
  188.         }
  189.         PDentry pd_new_e;
  190.         pd_new_e.present = pde & 0b1;
  191.         pd_new_e.read_write = (pde >> 1) & 0b1;
  192.         pd_new_e.user_supervisor = (pde >> 2) & 0b1;
  193.         pd_new_e.cache_policy = (pde>> 3) & 0b1;
  194.         pd_new_e.cache_disable = (pde >> 4) & 0b1;
  195.         pd_new_e.accessed = (pde >> 5) & 0b1;
  196.         pd_new_e.mbz = 0b000;
  197.         pd_new_e.avl_3 = 0;
  198.         pd_new_e.pt_addr = (uint64_t)PTtab >> 12;
  199.         pd_new_e.avl_11 = 0;
  200.         pd_new_e.no_execute = (pde >> 63) & 0b1;
  201.  
  202.         PDtab[i] = pd_new_e;
  203.         tlbflush(PDtab);
  204.     }
  205.  
  206.     printLn("Finished writing PD entries");
  207.  
  208.     for (uint16_t i = 0; i < 512; i++)
  209.     {
  210.         uint64_t pte = *((uint64_t*)ptbase + i);
  211.  
  212.         PTentry pt_new_e;
  213.         pt_new_e.present = pte & 0b1;
  214.         pt_new_e.read_write = (pte >> 1) & 0b1;
  215.         pt_new_e.user_supervisor = (pte >> 2) & 0b1;
  216.         pt_new_e.cache_policy = (pte >> 3) & 0b1;
  217.         pt_new_e.cache_disable = (pte >> 4) & 0b1;
  218.         pt_new_e.accessed = (pte >> 5) & 0b1;
  219.         pt_new_e.dirty = (pte >> 6) & 0b1;
  220.         pt_new_e.pat = (pte >> 7) & 0b1;
  221.         pt_new_e.global = (pte >> 8) & 0b1;
  222.         pt_new_e.avl_3 = 0b000;
  223.  
  224.         if (pt_new_e.present)
  225.             pt_new_e.page_base_addr = GET_PGTADDR(pte) >> 12;
  226.         else
  227.             pt_new_e.page_base_addr = 0;
  228.  
  229.         pt_new_e.avl_11 = 0;
  230.         pt_new_e.no_execute = (pte >> 63) & 0b1;
  231.  
  232.         PTtab[i] = pt_new_e;
  233.         tlbflush(PTtab);
  234.     }
  235.  
  236.     printLn("Finished writing in PT entries");
  237.  
  238.     pfa_free((paddr_t)pml4base);
  239.     pfa_free((paddr_t)pdpbase);
  240.     pfa_free((paddr_t)pdbase);
  241.     pfa_free((paddr_t)ptbase);
  242.  
  243.     printLn("Freed previous page tables");
  244.     printIntBase((uint64_t)PML4tab, 16);
  245.     write_cr3((void*)PML4tab);
  246.     write_cr0(cr0);
  247.     printLn("PML4 base address has been written. Paging is initialised");
  248. }
  249.  
  250. void paging_map(void* vaddr, size_t len, size_t attrset)
  251. {
  252.     putline;
  253.     while (len)
  254.     {
  255.         putline;
  256.         uint16_t pml4offset = ((size_t)decanonical(vaddr) >> 39) & 0x1FF;
  257.         uint16_t pdpoffset = ((size_t)decanonical(vaddr) >> 30) & 0x1FF;
  258.         uint16_t pdoffset = ((size_t)decanonical(vaddr) >> 21) & 0x1FF;
  259.         uint16_t ptoffset = ((size_t)decanonical(vaddr) >> 12) & 0x1FF;
  260.         uint16_t ppoffset = (size_t)decanonical(vaddr) & 0x1FF;
  261.  
  262.         putline;
  263.         PML4entry pml4entry = PML4tab[pml4offset];
  264.         PDPentry pdpentry = PDPtab[pdpoffset];
  265.         PDentry pdentry = PDtab[pdoffset];
  266.         PTentry ptentry = PTtab[ptoffset];
  267.  
  268.         putline;
  269.         if (!(ptentry.present & 0x1)) {
  270.             /* Page is present, now we have to swap to the pagefile. */
  271.  
  272. #ifndef SWAPFILE_NOT_REQUIRED
  273.             //Swap to the pagefile
  274. #endif
  275.         }
  276.         else {
  277.             putline;
  278.             //Page is not present, make a new page.
  279.             ptentry.page_base_addr = (pfa_alloc() >> 12);
  280.         }
  281.         putline;
  282.         pdentry.pt_addr = ((uint64_t)PTtab >> 12);
  283.         pdpentry.pd_addr = ((uint64_t)PDtab >> 12);
  284.         pml4entry.pdp_addr = ((uint64_t)PDPtab >> 12);
  285.         ptentry.present, pdentry.present, pdpentry.present, pml4entry.present = 0b1; // Set the present bit
  286.  
  287.         if (attrset >> 1) //Read/write => read/write set
  288.         {
  289.             SET(ptentry.read_write);
  290.             SET(pdentry.read_write);
  291.             SET(pdpentry.read_write);
  292.             SET(pml4entry.read_write);
  293.         }
  294.         else // read only set
  295.         {
  296.             CLEAR(ptentry.read_write);
  297.             CLEAR(pdentry.read_write);
  298.             CLEAR(pdpentry.read_write);
  299.             CLEAR(pml4entry.read_write);
  300.         }
  301.         if (attrset >> 2) // User/Supervisor => user and supervisor set
  302.         {
  303.             SET(ptentry.user_supervisor);
  304.             SET(pdentry.user_supervisor);
  305.             SET(pdpentry.user_supervisor);
  306.             SET(pml4entry.user_supervisor);
  307.         }
  308.         else // User only set
  309.         {
  310.             CLEAR(ptentry.user_supervisor);
  311.             CLEAR(pdentry.user_supervisor);
  312.             CLEAR(pdpentry.user_supervisor);
  313.             CLEAR(pml4entry.user_supervisor);
  314.         }
  315.         if (attrset >> 3) // Writethrough/writeback => writethrough set
  316.         {
  317.             SET(ptentry.cache_policy);
  318.             SET(pdentry.cache_policy);
  319.             SET(pdpentry.cache_policy);
  320.             SET(pml4entry.cache_policy);
  321.         }
  322.         else // writeback set
  323.         {
  324.             CLEAR(ptentry.cache_policy);
  325.             CLEAR(pdentry.cache_policy);
  326.             CLEAR(pdpentry.cache_policy);
  327.             CLEAR(pml4entry.cache_policy);
  328.         }
  329.         if (attrset >> 4) // Cache/No cache => no cache set
  330.         {
  331.             SET(ptentry.cache_disable);
  332.             SET(pdentry.cache_disable);
  333.             SET(pdpentry.cache_disable);
  334.             SET(pml4entry.cache_disable);
  335.         }
  336.         else // cache set
  337.         {
  338.             CLEAR(ptentry.cache_disable);
  339.             CLEAR(pdentry.cache_disable);
  340.             CLEAR(pdpentry.cache_disable);
  341.             CLEAR(pml4entry.cache_disable);
  342.         }
  343.         if (attrset >> 5) // No execute => no execute set
  344.         {
  345.             SET(ptentry.no_execute);
  346.             SET(pdentry.no_execute);
  347.             SET(pdpentry.no_execute);
  348.             SET(pml4entry.no_execute);
  349.         }
  350.         else // execute set
  351.         {
  352.             CLEAR(ptentry.no_execute);
  353.             CLEAR(pdentry.no_execute);
  354.             CLEAR(pdpentry.no_execute);
  355.             CLEAR(pml4entry.no_execute);
  356.         }
  357.         putline;
  358.  
  359.         PML4tab[pml4offset] = pml4entry;
  360.         PDPtab[pdpoffset] = pdpentry;
  361.         PDtab[pdoffset] = pdentry;
  362.         PTtab[ptoffset] = ptentry;
  363.  
  364.         putline;
  365.         tlbflush(PML4tab);
  366.         tlbflush(PDPtab);
  367.         tlbflush(PDtab);
  368.         tlbflush(PTtab);
  369.         putline;
  370.         memory_barrier();
  371.  
  372.         putline;
  373.         len -= EFI_PAGE_SIZE;
  374.         size_t v_t_addr = (size_t)vaddr;
  375.         v_t_addr += EFI_PAGE_SIZE;
  376.         vaddr = (void*)v_t_addr;
  377.         putline;
  378.     }
  379. }
  380.  
  381. void set_paging_attributes(void* vaddr, size_t len, size_t attrset)
  382. {
  383.     while (len)
  384.     {
  385.         uint16_t pml4offset = ((size_t)decanonical(vaddr) >> 39) & 0x1FF;
  386.         uint16_t pdpoffset = ((size_t)decanonical(vaddr) >> 30) & 0x1FF;
  387.         uint16_t pdoffset = ((size_t)decanonical(vaddr) >> 21) & 0x1FF;
  388.         uint16_t ptoffset = ((size_t)decanonical(vaddr) >> 12) & 0x1FF;
  389.         uint16_t ppoffset = (size_t)decanonical(vaddr) & 0x1FF;
  390.  
  391.         PML4entry pml4entry = PML4tab[pml4offset];
  392.         PDPentry pdpentry = PDPtab[pdpoffset];
  393.         PDentry pdentry = PDtab[pdoffset];
  394.         PTentry ptentry = PTtab[ptoffset];
  395.  
  396.         pdentry.pt_addr = ((uint64_t)PTtab >> 12);
  397.         pdpentry.pd_addr = ((uint64_t)PDtab >> 12);
  398.         pml4entry.pdp_addr = ((uint64_t)PDPtab >> 12);
  399.         ptentry.present, pdentry.present, pdpentry.present, pml4entry.present = 0b1; // Set the present bit
  400.  
  401.         if (attrset >> 1) //Read/write => read/write set
  402.         {
  403.             SET(ptentry.read_write);
  404.             SET(pdentry.read_write);
  405.             SET(pdpentry.read_write);
  406.             SET(pml4entry.read_write);
  407.         }
  408.         else // read only set
  409.         {
  410.             CLEAR(ptentry.read_write);
  411.             CLEAR(pdentry.read_write);
  412.             CLEAR(pdpentry.read_write);
  413.             CLEAR(pml4entry.read_write);
  414.         }
  415.         if (attrset >> 2) // User/Supervisor => user and supervisor set
  416.         {
  417.             SET(ptentry.user_supervisor);
  418.             SET(pdentry.user_supervisor);
  419.             SET(pdpentry.user_supervisor);
  420.             SET(pml4entry.user_supervisor);
  421.         }
  422.         else // User only set
  423.         {
  424.             CLEAR(ptentry.user_supervisor);
  425.             CLEAR(pdentry.user_supervisor);
  426.             CLEAR(pdpentry.user_supervisor);
  427.             CLEAR(pml4entry.user_supervisor);
  428.         }
  429.         if (attrset >> 3) // Writethrough/writeback => writethrough set
  430.         {
  431.             SET(ptentry.cache_policy);
  432.             SET(pdentry.cache_policy);
  433.             SET(pdpentry.cache_policy);
  434.             SET(pml4entry.cache_policy);
  435.         }
  436.         else // writeback set
  437.         {
  438.             CLEAR(ptentry.cache_policy);
  439.             CLEAR(pdentry.cache_policy);
  440.             CLEAR(pdpentry.cache_policy);
  441.             CLEAR(pml4entry.cache_policy);
  442.         }
  443.         if (attrset >> 4) // Cache/No cache => no cache set
  444.         {
  445.             SET(ptentry.cache_disable);
  446.             SET(pdentry.cache_disable);
  447.             SET(pdpentry.cache_disable);
  448.             SET(pml4entry.cache_disable);
  449.         }
  450.         else // cache set
  451.         {
  452.             CLEAR(ptentry.cache_disable);
  453.             CLEAR(pdentry.cache_disable);
  454.             CLEAR(pdpentry.cache_disable);
  455.             CLEAR(pml4entry.cache_disable);
  456.         }
  457.         if (attrset >> 5) // No execute => no execute set
  458.         {
  459.             SET(ptentry.no_execute);
  460.             SET(pdentry.no_execute);
  461.             SET(pdpentry.no_execute);
  462.             SET(pml4entry.no_execute);
  463.         }
  464.         else // execute set
  465.         {
  466.             CLEAR(ptentry.no_execute);
  467.             CLEAR(pdentry.no_execute);
  468.             CLEAR(pdpentry.no_execute);
  469.             CLEAR(pml4entry.no_execute);
  470.         }
  471.  
  472.         PML4tab[pml4offset] = pml4entry;
  473.         PDPtab[pdpoffset] = pdpentry;
  474.         PDtab[pdoffset] = pdentry;
  475.         PTtab[ptoffset] = ptentry;
  476.  
  477.         tlbflush(PML4tab);
  478.         tlbflush(PDPtab);
  479.         tlbflush(PDtab);
  480.         tlbflush(PTtab);
  481.         memory_barrier();
  482.  
  483.         len -= EFI_PAGE_SIZE;
  484.         size_t v_t_addr = (size_t)vaddr;
  485.         v_t_addr += EFI_PAGE_SIZE;
  486.         vaddr = (void*)v_t_addr;
  487.     }
  488. }
  489.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement