Aucune description
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

paging-multilevel-translate.py 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #! /usr/bin/env python
  2. import sys
  3. from optparse import OptionParser
  4. import random
  5. import math
  6. def convert(size):
  7. length = len(size)
  8. lastchar = size[length-1]
  9. if (lastchar == 'k') or (lastchar == 'K'):
  10. m = 1024
  11. nsize = int(size[0:length-1]) * m
  12. elif (lastchar == 'm') or (lastchar == 'M'):
  13. m = 1024*1024
  14. nsize = int(size[0:length-1]) * m
  15. elif (lastchar == 'g') or (lastchar == 'G'):
  16. m = 1024*1024*1024
  17. nsize = int(size[0:length-1]) * m
  18. else:
  19. nsize = int(size)
  20. return nsize
  21. def roundup(size):
  22. value = 1.0
  23. while value < size:
  24. value = value * 2.0
  25. return value
  26. class OS:
  27. def __init__(self):
  28. # 4k phys memory (128 pages)
  29. self.pageSize = 32
  30. self.physPages = 128
  31. self.physMem = self.pageSize * self.physPages
  32. self.vaPages = 1024
  33. self.vaSize = self.pageSize * self.vaPages
  34. self.pteSize = 1
  35. self.pageBits = 5 # log of page size
  36. # os tracks
  37. self.usedPages = []
  38. self.usedPagesCount = 0
  39. self.maxPageCount = self.physMem / self.pageSize
  40. # no pages used (yet)
  41. for i in range(0, self.maxPageCount):
  42. self.usedPages.append(0)
  43. # set contents of memory to 0, too
  44. self.memory = []
  45. for i in range(0, self.physMem):
  46. self.memory.append(0)
  47. # associative array of pdbr's (indexed by PID)
  48. self.pdbr = {}
  49. # mask is 11111 00000 00000 --> 0111 1100 0000 0000
  50. self.PDE_MASK = 0x7c00
  51. self.PDE_SHIFT = 10
  52. # 00000 11111 00000 -> 000 0011 1110 0000
  53. self.PTE_MASK = 0x03e0
  54. self.PTE_SHIFT = 5
  55. self.VPN_MASK = self.PDE_MASK | self.PTE_MASK
  56. self.VPN_SHIFT = self.PTE_SHIFT
  57. # grabs the last five bits of a virtual address
  58. self.OFFSET_MASK = 0x1f
  59. def findFree(self):
  60. assert(self.usedPagesCount < self.maxPageCount)
  61. look = int(random.random() * self.maxPageCount)
  62. while self.usedPages[look] == 1:
  63. look = int(random.random() * self.maxPageCount)
  64. self.usedPagesCount = self.usedPagesCount + 1
  65. self.usedPages[look] = 1
  66. return look
  67. def initPageDir(self, whichPage):
  68. whichByte = whichPage << self.pageBits
  69. for i in range(whichByte, whichByte + self.pageSize):
  70. self.memory[i] = 0x7f
  71. def initPageTablePage(self, whichPage):
  72. self.initPageDir(whichPage)
  73. def getPageTableEntry(self, virtualAddr, ptePage, printStuff):
  74. pteBits = (virtualAddr & self.PTE_MASK) >> self.PTE_SHIFT
  75. pteAddr = (ptePage << self.pageBits) | pteBits
  76. pte = self.memory[pteAddr]
  77. valid = (pte & 0x80) >> 7
  78. pfn = (pte & 0x7f)
  79. if printStuff == True:
  80. print ' --> pte index:0x%x [decimal %d] pte contents:0x%x (valid %d, pfn 0x%02x [decimal %d])' % \
  81. (pteBits, pteBits, pte, valid, pfn, pfn)
  82. return (valid, pfn, pteAddr)
  83. def getPageDirEntry(self, pid, virtualAddr, printStuff):
  84. pageDir = self.pdbr[pid]
  85. pdeBits = (virtualAddr & self.PDE_MASK) >> self.PDE_SHIFT
  86. pdeAddr = (pageDir << self.pageBits) | pdeBits
  87. pde = self.memory[pdeAddr]
  88. valid = (pde & 0x80) >> 7
  89. ptPtr = (pde & 0x7f)
  90. if printStuff == True:
  91. print ' --> pde index:0x%x [decimal %d] pde contents:0x%x (valid %d, pfn 0x%02x [decimal %d])' % \
  92. (pdeBits, pdeBits, pde, valid, ptPtr, ptPtr)
  93. return (valid, ptPtr, pdeAddr)
  94. def setPageTableEntry(self, pteAddr, physicalPage):
  95. self.memory[pteAddr] = 0x80 | physicalPage
  96. def setPageDirEntry(self, pdeAddr, physicalPage):
  97. self.memory[pdeAddr] = 0x80 | physicalPage
  98. def allocVirtualPage(self, pid, virtualPage, physicalPage):
  99. # make it into a virtual address, as everything uses this (and not VPN)
  100. virtualAddr = virtualPage << self.pageBits
  101. (valid, ptPtr, pdeAddr) = self.getPageDirEntry(pid, virtualAddr, False)
  102. if valid == 0:
  103. # must allocate a page of the page table now, and have the PD point to it
  104. assert(ptPtr == 127)
  105. ptePage = self.findFree()
  106. self.setPageDirEntry(pdeAddr, ptePage)
  107. self.initPageTablePage(ptePage)
  108. else:
  109. # otherwise, just extract page number of page table page
  110. ptePage = ptPtr
  111. # now, look up page table entry too, and mark it valid and fill in translation
  112. (valid, pfn, pteAddr) = self.getPageTableEntry(virtualAddr, ptePage, False)
  113. assert(valid == 0)
  114. assert(pfn == 127)
  115. self.setPageTableEntry(pteAddr, physicalPage)
  116. # -2 -> PTE fault, -1 means PDE fault
  117. def translate(self, pid, virtualAddr):
  118. (valid, ptPtr, pdeAddr) = self.getPageDirEntry(pid, virtualAddr, True)
  119. if valid == 1:
  120. ptePage = ptPtr
  121. (valid, pfn, pteAddr) = self.getPageTableEntry(virtualAddr, ptePage, True)
  122. if valid == 1:
  123. offset = (virtualAddr & self.OFFSET_MASK)
  124. paddr = (pfn << self.pageBits) | offset
  125. # print ' --> pfn: %02x offset: %x' % (pfn, offset)
  126. return paddr
  127. else:
  128. return -2
  129. return -1
  130. def fillPage(self, whichPage):
  131. for j in range(0, self.pageSize):
  132. self.memory[(whichPage * self.pageSize) + j] = int(random.random() * 31)
  133. def procAlloc(self, pid, numPages):
  134. # need a PDBR: find one somewhere in memory
  135. pageDir = self.findFree()
  136. # print '**ALLOCATE** page dir', pageDir
  137. self.pdbr[pid] = pageDir
  138. self.initPageDir(pageDir)
  139. used = {}
  140. for vp in range(0, self.vaPages):
  141. used[vp] = 0
  142. allocatedVPs = []
  143. for vp in range(0, numPages):
  144. vp = int(random.random() * self.vaPages)
  145. while used[vp] == 1:
  146. vp = int(random.random() * self.vaPages)
  147. assert(used[vp] == 0)
  148. used[vp] = 1
  149. allocatedVPs.append(vp)
  150. pp = self.findFree()
  151. # print '**ALLOCATE** page', pp
  152. # print ' trying to map vp:%08x to pp:%08x' % (vp, pp)
  153. self.allocVirtualPage(pid, vp, pp)
  154. self.fillPage(pp)
  155. return allocatedVPs
  156. def dumpPage(self, whichPage):
  157. i = whichPage
  158. for j in range(0, self.pageSize):
  159. print self.memory[(i * self.pageSize) + j],
  160. print ''
  161. def memoryDump(self):
  162. for i in range(0, self.physMem / self.pageSize):
  163. print 'page %3d:' % i,
  164. for j in range(0, self.pageSize):
  165. print '%02x' % self.memory[(i * self.pageSize) + j],
  166. print ''
  167. def getPDBR(self, pid):
  168. return self.pdbr[pid]
  169. def getValue(self, addr):
  170. return self.memory[addr]
  171. # allocate some processes in memory
  172. # allocate some multi-level page tables in memory
  173. # make a bit of a mystery:
  174. # can examine PDBR (PFN of current proc's page directory)
  175. # can examine contents of any page
  176. # fill pages with values too
  177. # ask: when given
  178. # LOAD VA, R1
  179. # what will final value will be loaded into R1?
  180. #
  181. # main program
  182. #
  183. parser = OptionParser()
  184. parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed')
  185. parser.add_option('-a', '--allocated', default=64, help='number of virtual pages allocated',
  186. action='store', type='int', dest='allocated')
  187. parser.add_option('-n', '--addresses', default=10, help='number of virtual addresses to generate',
  188. action='store', type='int', dest='num')
  189. parser.add_option('-c', '--solve', help='compute answers for me', action='store_true', default=False, dest='solve')
  190. (options, args) = parser.parse_args()
  191. print 'ARG seed', options.seed
  192. print 'ARG allocated', options.allocated
  193. print 'ARG num', options.num
  194. print ""
  195. random.seed(options.seed)
  196. # do the work now
  197. os = OS()
  198. used = os.procAlloc(1, options.allocated)
  199. os.memoryDump()
  200. print '\nPDBR:', os.getPDBR(1), ' (decimal) [This means the page directory is held in this page]\n'
  201. for i in range(0, options.num):
  202. if (random.random() * 100) > 50.0 or i >= len(used):
  203. vaddr = int(random.random() * 1024 * 32)
  204. else:
  205. vaddr = (used[i] << 5) | int(random.random() * 32)
  206. if options.solve == True:
  207. print 'Virtual Address %04x:' % vaddr
  208. r = os.translate(1, vaddr)
  209. if r > -1:
  210. print ' --> Translates to Physical Address 0x%03x --> Value: %02x' % (r, os.getValue(r))
  211. elif r == -1:
  212. print ' --> Fault (page directory entry not valid)'
  213. else:
  214. print ' --> Fault (page table entry not valid)'
  215. else:
  216. print 'Virtual Address %04x: Translates To What Physical Address (And Fetches what Value)? Or Fault?' % vaddr
  217. print ''
  218. exit(0)