-#ifndef __NTOSKRNL_INCLUDE_INTERNAL_ARM_MM_H
-#define __NTOSKRNL_INCLUDE_INTERNAL_ARM_MM_H
+#pragma once
-//
-// Number of bits corresponding to the area that a PDE entry represents (1MB)
-//
#define PDE_SHIFT 20
-#define PDE_SIZE (1 << PDE_SHIFT)
//
// Number of bits corresponding to the area that a coarse page table entry represents (4KB)
//
#define PTE_SHIFT 12
-//#define PAGE_SIZE (1 << PTE_SHIFT) // FIXME: This conflicts with ndk/arm/mmtypes.h which does #define PAGE_SIZE 0x1000 -- use PTE_SIZE here instead?
+#define PTE_SIZE (1 << PTE_SHIFT)
//
// Number of bits corresponding to the area that a coarse page table occupies (1KB)
#define CPT_SHIFT 10
#define CPT_SIZE (1 << CPT_SHIFT)
-typedef union _ARM_PTE
+//
+// Base Addresses
+//
+#define PTE_BASE 0xC0000000
+#define PTE_TOP 0xC03FFFFF
+#define PDE_BASE 0xC0400000
+#define PDE_TOP 0xC04FFFFF
+#define HYPER_SPACE 0xC0500000
+
+#if 0
+typedef struct _HARDWARE_PDE_ARMV6
{
- union
- {
- struct
- {
- ULONG Type:2;
- ULONG Unused:30;
- } Fault;
- struct
- {
- ULONG Type:2;
- ULONG Ignored:2;
- ULONG Reserved:1;
- ULONG Domain:4;
- ULONG Ignored1:1;
- ULONG BaseAddress:22;
- } Coarse;
- struct
- {
- ULONG Type:2;
- ULONG Buffered:1;
- ULONG Cached:1;
- ULONG Reserved:1;
- ULONG Domain:4;
- ULONG Ignored:1;
- ULONG Access:2;
- ULONG Ignored1:8;
- ULONG BaseAddress:12;
- } Section;
- struct
- {
- ULONG Type:2;
- ULONG Reserved:3;
- ULONG Domain:4;
- ULONG Ignored:3;
- ULONG BaseAddress:20;
- } Fine;
- } L1;
- union
- {
- struct
- {
- ULONG Type:2;
- ULONG Unused:30;
- } Fault;
- struct
- {
- ULONG Type:2;
- ULONG Buffered:1;
- ULONG Cached:1;
- ULONG Access0:2;
- ULONG Access1:2;
- ULONG Access2:2;
- ULONG Access3:2;
- ULONG Ignored:4;
- ULONG BaseAddress:16;
- } Large;
- struct
- {
- ULONG Type:2;
- ULONG Buffered:1;
- ULONG Cached:1;
- ULONG Access0:2;
- ULONG Access1:2;
- ULONG Access2:2;
- ULONG Access3:2;
- ULONG BaseAddress:20;
- } Small;
- struct
- {
- ULONG Type:2;
- ULONG Buffered:1;
- ULONG Cached:1;
- ULONG Access0:2;
- ULONG Ignored:4;
- ULONG BaseAddress:22;
- } Tiny;
- } L2;
- ULONG AsUlong;
-} ARM_PTE, *PARM_PTE;
-
-typedef struct _ARM_TRANSLATION_TABLE
+ ULONG Valid:1; // Only for small pages
+ ULONG LargePage:1; // Note, if large then Valid = 0
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG NoExecute:1;
+ ULONG Domain:4;
+ ULONG Ecc:1;
+ ULONG PageFrameNumber:22;
+} HARDWARE_PDE_ARMV6, *PHARDWARE_PDE_ARMV6;
+
+typedef struct _HARDWARE_LARGE_PTE_ARMV6
{
- ARM_PTE Pte[4096];
-} ARM_TRANSLATION_TABLE, *PARM_TRANSLATION_TABLE;
-
-typedef struct _ARM_COARSE_PAGE_TABLE
+ ULONG Valid:1; // Only for small pages
+ ULONG LargePage:1; // Note, if large then Valid = 0
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG NoExecute:1;
+ ULONG Domain:4;
+ ULONG Ecc:1;
+ ULONG Accessed:1;
+ ULONG Owner:1;
+ ULONG CacheAttributes:3;
+ ULONG ReadOnly:1;
+ ULONG Shared:1;
+ ULONG NonGlobal:1;
+ ULONG SuperLagePage:1;
+ ULONG Reserved:1;
+ ULONG PageFrameNumber:12;
+} HARDWARE_LARGE_PTE_ARMV6, *PHARDWARE_LARGE_PTE_ARMV6;
+
+typedef struct _HARDWARE_PTE_ARMV6
{
- ARM_PTE Pte[256];
- ULONG Padding[768];
-} ARM_COARSE_PAGE_TABLE, *PARM_COARSE_PAGE_TABLE;
+ ULONG NoExecute:1;
+ ULONG Valid:1;
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG Accessed:1;
+ ULONG Owner:1;
+ ULONG CacheAttributes:3;
+ ULONG ReadOnly:1;
+ ULONG Shared:1;
+ ULONG NonGlobal:1;
+ ULONG PageFrameNumber:20;
+} HARDWARE_PTE_ARMV6, *PHARDWARE_PTE_ARMV6;
+
+C_ASSERT(sizeof(HARDWARE_PDE_ARMV6) == sizeof(ULONG));
+C_ASSERT(sizeof(HARDWARE_LARGE_PTE_ARMV6) == sizeof(ULONG));
+C_ASSERT(sizeof(HARDWARE_PTE_ARMV6) == sizeof(ULONG));
+#endif
-typedef enum _ARM_L1_PTE_TYPE
+/* For FreeLDR */
+typedef struct _PAGE_TABLE_ARM
{
- FaultPte,
- CoarsePte,
- SectionPte,
- FinePte
-} ARM_L1_PTE_TYPE;
+ HARDWARE_PTE_ARMV6 Pte[1024];
+} PAGE_TABLE_ARM, *PPAGE_TABLE_ARM;
-typedef enum _ARM_L2_PTE_TYPE
+typedef struct _PAGE_DIRECTORY_ARM
{
- LargePte = 1,
- SmallPte,
- TinyPte
-} ARM_L2_PTE_TYPE;
+ union
+ {
+ HARDWARE_PDE_ARMV6 Pde[4096];
+ HARDWARE_LARGE_PTE_ARMV6 Pte[4096];
+ };
+} PAGE_DIRECTORY_ARM, *PPAGE_DIRECTORY_ARM;
-typedef enum _ARM_PTE_ACCESS
-{
- FaultAccess,
- SupervisorAccess,
- SharedAccess,
- UserAccess
-} ARM_PTE_ACCESS;
+C_ASSERT(sizeof(PAGE_TABLE_ARM) == PAGE_SIZE);
+C_ASSERT(sizeof(PAGE_DIRECTORY_ARM) == (4 * PAGE_SIZE));
typedef enum _ARM_DOMAIN
{
ManagerDomain
} ARM_DOMAIN;
-//
-// Take 0x80812345 and extract:
-// PTE_BASE[0x808][0x12]
-//
-#define MiGetPteAddress(x) \
- (PMMPTE)(PTE_BASE + \
- (((ULONG)(x) >> 20) << 12) + \
- ((((ULONG)(x) >> 12) & 0xFF) << 2))
-
-#define MiGetPdeAddress(x) \
- (PMMPTE)(PDE_BASE + \
- (((ULONG)(x) >> 20) << 2))
-
-#define MiGetPdeOffset(x) (((ULONG)(x)) >> 22)
-
-#define PTE_BASE 0xC0000000
-#define PDE_BASE 0xC1000000
-#define HYPER_SPACE 0xC1100000
-
struct _EPROCESS;
PULONG MmGetPageDirectory(VOID);
-#endif
+#define MI_MAKE_LOCAL_PAGE(x) ((x)->u.Hard.NonGlobal = 1)
+#define MI_MAKE_DIRTY_PAGE(x)
+#define MI_MAKE_ACCESSED_PAGE(x)
+#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
+#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.ReadOnly = 0)
+#define MI_PAGE_DISABLE_CACHE(x) ((x)->u.Hard.Cached = 0)
+#define MI_PAGE_WRITE_THROUGH(x) ((x)->u.Hard.Buffered = 0)
+#define MI_PAGE_WRITE_COMBINED(x) ((x)->u.Hard.Buffered = 1)
+#define MI_IS_PAGE_WRITEABLE(x) ((x)->u.Hard.ReadOnly == 0)
+#define MI_IS_PAGE_COPY_ON_WRITE(x)FALSE
+#define MI_IS_PAGE_DIRTY(x) TRUE
+
+/* Easy accessing PFN in PTE */
+#define PFN_FROM_PTE(v) ((v)->u.Hard.PageFrameNumber)
+
+#define NR_SECTION_PAGE_TABLES 1024
+#define NR_SECTION_PAGE_ENTRIES 256
+
+/* See PDR definition */
+#define MI_HYPERSPACE_PTES (256 - 1)
+#define MI_ZERO_PTES (32)
+#define MI_MAPPING_RANGE_START ((ULONG)HYPER_SPACE)
+#define MI_MAPPING_RANGE_END (MI_MAPPING_RANGE_START + \
+ MI_HYPERSPACE_PTES * PAGE_SIZE)
+#define MI_ZERO_PTE (PMMPTE)(MI_MAPPING_RANGE_END + \
+ PAGE_SIZE)
+
+/* Retrives the PDE entry for the given VA */
+#define MiGetPdeAddress(x) ((PMMPDE)(PDE_BASE + (((ULONG)(x) >> 20) << 2)))
+#define MiAddressToPde(x) MiGetPdeAddress(x)
+
+/* Retrieves the PTE entry for the given VA */
+#define MiGetPteAddress(x) ((PMMPTE)(PTE_BASE + (((ULONG)(x) >> 12) << 2)))
+#define MiAddressToPte(x) MiGetPteAddress(x)
+
+/* Retrives the PDE offset for the given VA */
+#define MiGetPdeOffset(x) (((ULONG)(x)) >> 20)
+
+/* Convert a PTE into a corresponding address */
+#define MiPteToAddress(x) ((PVOID)((ULONG)(x) << 10))
+#define MiPdeToAddress(x) ((PVOID)((ULONG)(x) << 18))
+
+#define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \
+ ((x) / (4*1024*1024))
+
+#define PAGE_TO_SECTION_PAGE_TABLE_OFFSET(x) \
+ ((((x)) % (4*1024*1024)) / (4*1024))
+
+#define MM_CACHE_LINE_SIZE 64