<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="generator" content="TempleOS V5.03">
<link rel="stylesheet" href="/style/templeos.css">
<script src="/script/templeos.js"></script>
<style type="text/css">
.cF0{color:#000000;background-color:#ffffff;}
.cF1{color:#0000aa;background-color:#ffffff;}
.cF2{color:#00aa00;background-color:#ffffff;}
.cF3{color:#00aaaa;background-color:#ffffff;}
.cF4{color:#aa0000;background-color:#ffffff;}
.cF5{color:#aa00aa;background-color:#ffffff;}
.cF6{color:#aa5500;background-color:#ffffff;}
.cF7{color:#aaaaaa;background-color:#ffffff;}
.cF8{color:#555555;background-color:#ffffff;}
.cF9{color:#5555ff;background-color:#ffffff;}
.cFA{color:#55ff55;background-color:#ffffff;}
.cFB{color:#55ffff;background-color:#ffffff;}
.cFC{color:#ff5555;background-color:#ffffff;}
.cFD{color:#ff55ff;background-color:#ffffff;}
.cFE{color:#ffff55;background-color:#ffffff;}
.cFF{color:#ffffff;background-color:#ffffff;}
</style>
</head>
<body>
<pre style="font-family: courier, monospace; font-size: 10pt;">
<a name="l1"></a><span class=cF5>                                Memory Overview</span><span class=cF0>
<a name="l2"></a>
<a name="l3"></a>Paging is practically not used.  64-bit mode requires paging, however, so it is 
<a name="l4"></a>identity-mapped -- virtual identical to physical.  All tasks on all cores use 
<a name="l5"></a>the same page table map, just as though all addresses are physical addresses.  
<a name="l6"></a>2Meg or 1Gig page table entries are used.  Nothing swaps to disk.
<a name="l7"></a>
<a name="l8"></a>In TempleOS, the lowest 2Gig of memory is called the </span><span class=cF2>code heap</span><span class=cF0>.  TempleOS's 
<a name="l9"></a>compiler always uses 32-bit signed relative JMP &amp; CALL insts because 64-bit 
<a name="l10"></a>CALLs take two insts.  With signed +/- 32-bit values, code can only call a 
<a name="l11"></a>function within 2Gig distance.  Therefore, TempleOS keeps all code in the lowest 
<a name="l12"></a>2Gig memory addresses including what would normally be called &quot;the kernel&quot;.  Two 
<a name="l13"></a>Gig is plenty for code, don't worry.
<a name="l14"></a>
<a name="l15"></a>You can create new, independent heaps using </span><a href="/Wb/Kernel/Mem/HeapCtrl.HC#l1"><span class=cF4>HeapCtrlInit</span></a><span class=cF0>().  Then, use the </span><span class=cF4>
<a name="l16"></a></span><a href="/Wb/Kernel/KernelA.HH#l2863"><span class=cF4>CHeapCtrl</span></a><span class=cF0> as the 2nd arg to </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l387"><span class=cF4>MAlloc</span></a><span class=cF0>().  See </span><a href="/Wb/Adam/Opt/Utils/HeapLog.HC#l73"><span class=cF4>HeapLog</span></a><span class=cF0>() for an example.
<a name="l17"></a>
<a name="l18"></a>Memory alloced by a task will be freed when the task is killed.  The </span><a href="/Wb/Doc/Glossary.DD.HTML#l171"><span class=cF4>Adam Task</span></a><span class=cF0> 
<a name="l19"></a>is a task that never dies.  His memory is like kernel memory in other operating 
<a name="l20"></a>systems.  See </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l402"><span class=cF4>ACAlloc</span></a><span class=cF0>(), </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l390"><span class=cF4>AMAlloc</span></a><span class=cF0>(), </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l418"><span class=cF4>AMAllocIdent</span></a><span class=cF0>() and </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l461"><span class=cF4>AStrNew</span></a><span class=cF0>().
<a name="l21"></a>
<a name="l22"></a>All of the regular page tables are marked, &quot;cached&quot;.  When accessing hardware, 
<a name="l23"></a>however, you need uncached page table.  The lowest 4Gig addresses have an alias 
<a name="l24"></a>to access hardware located toward the top of mapped space, </span><span class=cF2>0x10000000000</span><span class=cF0>.  See </span><span class=cF4>
<a name="l25"></a></span><a href="/Wb/Kernel/KMain.HC#l69"><span class=cF4>dev.uncached_alias</span></a><span class=cF0>.
<a name="l26"></a>
<a name="l27"></a>During an extended powered-on session of TempleOS, in theory, memory will become 
<a name="l28"></a>fragmented, requiring a reboot.  It has never happens to me.
<a name="l29"></a>
<a name="l30"></a>See </span><a href="/Wb/Adam/Opt/Utils/MemRep.HC#l193"><span class=cF4>MemRep</span></a><span class=cF0>() and </span><a href="/Wb/Demo/MemDemo.HC#l1"><span class=cF4>::/Demo/MemDemo.HC</span></a><span class=cF0>.
<a name="l31"></a>
<a name="l32"></a>
<a name="l33"></a></span><span class=cF5>                           Single System-wide Mem Map
<a name="l34"></a>
<a name="l35"></a></span><span class=cF2> 0x0000007C00- 0x000003616F</span><span class=cF0>
<a name="l36"></a>  Kernel module, placed here by the boot-loader, </span><a href="/Wb/Kernel/KernelA.HH#l3835"><span class=cF4>BOOT_RAM_BASE</span></a><span class=cF0>.
<a name="l37"></a>
<a name="l38"></a></span><span class=cF2> 0x0000096600- 0x0000096FFF</span><span class=cF0>
<a name="l39"></a>  Boot block relocated here before loading the Kernel module, </span><a href="/Wb/Adam/Opt/Boot/BootDVD.HC#l1"><span class=cF4>BootDVD</span></a><span class=cF0> &amp; </span><a href="/Wb/Adam/Opt/Boot/BootHD.HC#l1"><span class=cF4>BootHD</span></a><span class=cF0>.
<a name="l40"></a>
<a name="l41"></a></span><span class=cF2> 0x0000097000- 0x0000097030</span><span class=cF0> Multicore start-up vect code, </span><a href="/Wb/Kernel/KernelA.HH#l525"><span class=cF4>MPN_VECT</span></a><span class=cF0>.
<a name="l42"></a></span><span class=cF2>~0x000009F000- 0x000009FFFF</span><span class=cF0> Extended BIOS data area.
<a name="l43"></a></span><span class=cF2> 0x00000A0000- 0x00000BFFFF</span><span class=cF0> VGA graphics mem with alias at </span><a href="/Wb/Kernel/KGlbls.HC#l30"><span class=cF4>text</span></a><span class=cF0>.vga_alias.
<a name="l44"></a></span><span class=cF2> 0x0000100000- 0x0000101FFF</span><span class=cF0> </span><a href="/Wb/Kernel/KernelA.HH#l3415"><span class=cF4>CSysFixedArea</span></a><span class=cF0> for misc.
<a name="l45"></a></span><span class=cF2> 0x000050A000- 0x001FFDFFFF</span><span class=cF0> Code Heap mem.
<a name="l46"></a>
<a name="l47"></a></span><span class=cF2> 0x00E0000000- 0x00FFFFFFFF</span><span class=cF0>
<a name="l48"></a>  32-bit devices could alloc memory at 0xF0000000 going up, but this is wrong, 
<a name="l49"></a>  since some PCs already have devices at 0xF0000000.  No PCI devices are 
<a name="l50"></a>  supported, so </span><a href="/Wb/Kernel/Mem/MemPhysical.HC#l58"><span class=cF4>Mem32DevAlloc</span></a><span class=cF0>() flaws are not an issue.
<a name="l51"></a>
<a name="l52"></a></span><span class=cF2> 0x0080000000-~0x00DFFFFFFF</span><span class=cF0>
<a name="l53"></a></span><span class=cF2> 0x0100000000-~0xFFFFFFFFFF</span><span class=cF0>
<a name="l54"></a>  Data Heap mem.  (The physical memory that exists in this range is data heap.)
<a name="l55"></a>
<a name="l56"></a></span><span class=cF2> 0x10000000000- 0x100FFFFFFFF</span><span class=cF0>
<a name="l57"></a>  Uncached alias of first 4Gig.  (For 32-bit device access.)
<a name="l58"></a>
<a name="l59"></a></span><span class=cF2>             - 0x100FFFFFFFF</span><span class=cF0>
<a name="l60"></a>  64-bit devices are alloced with </span><a href="/Wb/Kernel/Mem/MemPhysical.HC#l108"><span class=cF4>Mem64DevAlloc</span></a><span class=cF0>() counting bwd, but no PCI 
<a name="l61"></a>  devices are actually supported.
<a name="l62"></a>
<a name="l63"></a>
<a name="l64"></a>
<a name="l65"></a>* Note: There is a break in the data-heap block pool.  This has no effect except 
<a name="l66"></a>the obvious effect that fragmentation has on contiguous requests.  I can </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l387"><span class=cF4>MAlloc</span></a><span class=cF0>(
<a name="l67"></a>) an 8Gig chunk on my 12Gig machine.  I can </span><a href="/Wb/Kernel/Mem/MAllocFree.HC#l387"><span class=cF4>MAlloc</span></a><span class=cF0>() an 32Gig chunk on my 64Gig 
<a name="l68"></a>machine.  
<a name="l69"></a>
<a name="l70"></a>* Note: For systems with less than 2Gig RAM, the code and data heap block pools 
<a name="l71"></a>are the same.  For systems with 2-4Gig of RAM, the code heap is 1/4 of the 
<a name="l72"></a>total.  See </span><a href="/Wb/Kernel/Mem/BlkPool.HC#l29"><span class=cF4>BlkPoolsInit</span></a><span class=cF0>().
<a name="l73"></a>
<a name="l74"></a>
<a name="l75"></a></span><span class=cF5>                                    History</span><span class=cF0>
<a name="l76"></a>
<a name="l77"></a>In 2003, I wanted to make a no-paging ring-0-only 64-bit operating system for 
<a name="l78"></a>super speed with simplicity and full access.  With paging, every memory request 
<a name="l79"></a>requires 5 accesses -- it must access the address itself, 4K, 2Meg, 1Gig, and 
<a name="l80"></a>512Gig page tables, but the CPU's translation look-aside buffer mostly removes 
<a name="l81"></a>the penalty for using paging.  So, I did not want to use paging, but long mode 
<a name="l82"></a>requires it.  I did the next best thing -- I identity-mapped everything and 
<a name="l83"></a>achieved the simplicity I was after with subtle performance boosts, not wasting 
<a name="l84"></a>time changing address maps.  And, I look forward to the day I command Intel to 
<a name="l85"></a>make an optimized no-paging long mode.
<a name="l86"></a>
<a name="l87"></a>I needed VGA A0000-BFFFF memory to be write-through and 0xE0000000-0xFFFFFFFF to 
<a name="l88"></a>be uncached for various devices.  All 64-bit computers allow stopping address 
<a name="l89"></a>translation at 2Meg page size, not using 4K.  I wanted to use 2Meg for 
<a name="l90"></a>everything because it's faster, with one less level of page tables.  I had to 
<a name="l91"></a>make A0000-BFFFF write-through, though, so I could not use 2Meg size on the 
<a name="l92"></a>lowest page.  I did the lowest 2Meg area as 4K pages.  I also unmapped the first 
<a name="l93"></a>4K to cause a fault when dereferencing NULL.
<a name="l94"></a>
<a name="l95"></a>In 2016, I came-up with an alternate idea.  I double mapped the lowest memory 
<a name="l96"></a>with an alias that was uncached.  Accessing the lowest 2Meg area directly was 
<a name="l97"></a>cached but the alias I created up at the top of address space was uncached.  See </span><span class=cF4>
<a name="l98"></a></span><a href="/Wb/Kernel/Mem/MemPhysical.HC#l138"><span class=cF4>UncachedAliasAlloc</span></a><span class=cF0>().  Unfortunately, I could no longer boast of the simplicity 
<a name="l99"></a>of identity mapping everything.  Since many of my users are familiar with 
<a name="l100"></a>A0000-BFFFF, it is actually pretty seriously unfortunate that they cannot use 
<a name="l101"></a>the easy-to-understand numbers of A0000-BFFFF, but must access the relocated 
<a name="l102"></a>alias location.  See </span><a href="/Wb/Kernel/KMain.HC#l69"><span class=cF4>text.vga_alias</span></a><span class=cF0>.  I also no longer cause a fault when 
<a name="l103"></a>dereferencing NULL.
<a name="l104"></a>
<a name="l105"></a>Then, I switched to 1Gig page sizes.  For the lowest 4Gig, I set-up an alias up 
<a name="l106"></a>at the top of address space.  See </span><a href="/Wb/Kernel/Mem/MemPhysical.HC#l138"><span class=cF4>UncachedAliasAlloc</span></a><span class=cF0>().  Not all computers 
<a name="l107"></a>support 1Gig page tables, however, so I also support 2Meg.
<a name="l108"></a>
<a name="l109"></a>My original plan was to allow changing the page tables as needed, so I had code 
<a name="l110"></a>for taking control of 2Meg pages and marking them uncached or whatever.  When I 
<a name="l111"></a>did a HDAudio driver, I requested some 32-bit address space as uncached.  Today, 
<a name="l112"></a>all of the first 4Gig can be accessed without caching at the </span><a href="/Wb/Kernel/KMain.HC#l69"><span class=cF4>dev.uncached_alias</span></a><span class=cF0>.
</span></pre></body>
</html>