#ifndef _MM_VIRT_H_
#define _MM_VIRT_H_
-#define KERNEL_BASE 0x80000000 // 2GiB
-
#define MM_USER_MIN 0x00001000
#define USER_LIB_MAX 0x7F800000
-#define MM_PPD_VFS 0x7F800000
+#define MM_PPD_HANDLES 0x7F800000
+#define MM_TABLE0USER 0x7F900000 // 2 GiB - 16 KiB
+#define MM_TABLE1USER 0x7FC00000 // 2 GiB - 4 MiB
// Page Blocks are 12-bits wide (12 address bits used)
// Hence, the table is 16KiB large (and must be so aligned)
// and each block addresses 1MiB of data
+// First level table is aligned to 16KiB (restriction of TTBR reg)
+// - VMSAv6 uses two TTBR regs, determined by bit 31
+
+#define KERNEL_BASE 0x80000000 // 2GiB
+
#define MM_KHEAP_BASE 0x80800000 // 8MiB of kernel code
-#define MM_KHEAP_MAX 0xC0000000 // 1GiB of kernel heap
+#define MM_KHEAP_MAX 0xC0000000 // ~1GiB of kernel heap
-#define MM_MODULE_MIN 0xC0000000
+#define MM_MODULE_MIN 0xC0000000 // - 0xD0000000
#define MM_MODULE_MAX 0xD0000000
-#define MM_KERNEL_VFS 0xFF800000 //
-#define MM_FRACTAL 0xFFE00000 // 2nd last block
+#define MM_KHEAP_MIN 0xE0000000
+#define MM_KHEAP_MAX 0xF0000000
+
+#define MM_KERNEL_VFS 0xFF000000 //
+#define MM_TABLE1KERN 0xFF800000 // - 0x???????? 4MiB
+#define MM_TABLE0KERN 0xFFC00000 // - 0xFFE04000 16KiB
#endif
--- /dev/null
+/*
+ * Acess2
+ *
+ * ARM7 Virtual Memory Manager
+ * - arch/arm7/mm_virt.c
+ */
+#include <mm_virt.h>
+
+// === TYPES ===
+typedef struct
+{
+ tPAddr PhysAddr;
+ Uint8 Size;
+ Uint8 Domain;
+} tMM_PageInfo;
+
+// === GLOBALS ===
+Uint32 *gMM_KernelTable0 = (void*)MM_TABLE0KERN;
+Uint32 *gMM_KernelTable1 = (void*)MM_TABLE1KERN;
+
+// === CODE ===
+int MM_InitialiseVirtual(void)
+{
+}
+
+int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
+{
+ Uint32 *table0, table1;
+ Uint32 desc;
+
+ if(VAddr & 0x80000000 ) {
+ table0 = MM_TABLE0KERN;
+ table1 = MM_TABLE1KERN;
+ }
+ else {
+ table0 = MM_TABLE0USER;
+ table1 = MM_TABLE1USER;
+ }
+ VAddr & 0x7FFFFFFF;
+
+ desc = table0[ VAddr >> 20 ];
+
+ switch( (desc & 3) )
+ {
+ // 0: Unmapped
+ case 0:
+ pi->PhysAddr = 0;
+ pi->Size = 20;
+ pi->Domain = 0;
+ return 1;
+
+ // 1: Coarse page table
+ case 1:
+ // Domain from top level table
+ pi->Domain = (desc >> 5) & 7;
+ // Get next level
+ desc = table1[ VAddr >> 12 ];
+ switch( desc & 3 )
+ {
+ // 0: Unmapped
+ case 0:
+ pi->Size = 12;
+ return 1;
+ // 1: Large Page (64KiB)
+ case 1:
+ pi->Size = 16;
+ pi->PhysAddr = desc & 0xFFFF0000;
+ return 0;
+ // 2/3: Small page
+ case 2:
+ case 3:
+ pi->Size = 12;
+ pi->PhysAddr = desc & 0xFFFFF000;
+ pi->bExecutable = desc & 1;
+ pi->bGlobal = !(desc >> 11);
+ pi->bSharec = (desc >> 10) & 1;
+ return 1;
+ }
+ return 1;
+
+ // 2: Section (or Supersection)
+ case 2:
+ if( desc & (1 << 18) ) {
+ // Supersection
+ pi->PhysAddr = desc & 0xFF000000;
+ pi->PhysAddr |= ((desc >> 20) & 0xF) << 32;
+ pi->PhysAddr |= ((desc >> 5) & 0x7) << 36;
+ pi->Size = 24;
+ pi->Domain = 0; // Superpages default to zero
+ return 0;
+ }
+
+ // Section
+ pi->PhysAddr = desc & 0xFFF80000;
+ pi->Size = 20;
+ pi->Domain = (desc >> 5) & 7;
+ return 0;
+
+ // 3: Reserved (invalid)
+ case 3:
+ pi->PhysAddr = 0;
+ pi->Size = 20;
+ pi->Domain = 0;
+ return 2;
+ }
+}
+
+// --- Exports ---
+tPAddr MM_GetPhysAddr(tVAddr VAddr)
+{
+ tMM_PageInfo pi;
+ if( MM_int_GetPageInfo(VAddr, &pi) )
+ return 0;
+ return pi.PhysAddr;
+}