#ifndef __ASSEMBLER__
#include <stdint.h>
+#include "debug.h"
#endif
-// An Address:
-// +--------10------+-------10-------+---------12----------+
-// | Page Directory | Page Table | Offset within Page |
-// +----------------+----------------+---------------------+
-
-#define PGSHIFT 12 /* LOG2(NBPG) */
-#define NBPG (1 << PGSHIFT) /* bytes/page */
-
-/* Page tables (selected by VA[31:22] and indexed by VA[21:12]) */
-#define PGMASK (NBPG - 1) /* Mask for page offset. Terrible name! */
-#define PGOFS(va) ((va) & PGMASK)
-/* Page number of virtual page in the virtual page table. */
-#define PGNO(va) ((uint32_t) (va) >> PGSHIFT)
-/* Index of PTE for VA within the corresponding page table */
-#define PTENO(va) (((uint32_t) (va) >> PGSHIFT) & 0x3ff)
-/* Round up to a page */
-#define PGROUNDUP(va) (((va) + PGMASK) & ~PGMASK)
-/* Round down to a page */
-#define PGROUNDDOWN(va) ((va) & ~PGMASK)
-/* Page directories (indexed by VA[31:22]) */
-#define PDSHIFT 22 /* LOG2(NBPD) */
-#define NBPD (1 << PDSHIFT) /* bytes/page dir */
-#define PDMASK (NBPD-1) /* byte offset into region mapped by
- a page table */
-#define PDENO(va) ((uint32_t) (va) >> PDSHIFT)
-/* Round up */
-#define PDROUNDUP(va) (((va) + PDMASK) & ~PDMASK)
-/* Round down */
-#define PDROUNDDOWN(va) ((va) & ~PDMASK)
+#include "loader.h"
-/* At IOPHYSMEM (640K) there is a 384K hole for I/O. From the kernel,
- * IOPHYSMEM can be addressed at KERNBASE + IOPHYSMEM. The hole ends
- * at physical address EXTPHYSMEM. */
-#define IOPHYSMEM 0xa0000
-#define EXTPHYSMEM 0x100000
+#define MASK(SHIFT, CNT) (((1ul << (CNT)) - 1) << (SHIFT))
+/* Page offset (bits 0:11). */
+#define PGSHIFT 0 /* First offset bit. */
+#define PGBITS 12 /* Number of offset bits. */
+#define PGMASK MASK(PGSHIFT, PGBITS)
+#define PGSIZE (1 << PGBITS)
-/*
- * Virtual memory map: Permissions
- * kernel/user
- *
- * 4 Gig --------> +------------------------------+
- * | | RW/--
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * : . :
- * : . :
- * : . :
- * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| RW/--
- * | | RW/--
- * | Physical Memory | RW/--
- * | | RW/--
- * KERNBASE -----> +------------------------------+
- * | Kernel Virtual Page Table | RW/-- NBPD
- * VPT,KSTACKTOP--> +------------------------------+ --+
- * | Kernel Stack | RW/-- KSTKSIZE |
- * | - - - - - - - - - - - - - - -| NBPD
- * | Invalid memory | --/-- |
- * ULIM ------> +------------------------------+ --+
- * | R/O User VPT | R-/R- NBPD
- * UVPT ----> +------------------------------+
- * | R/O PPAGE | R-/R- NBPD
- * UPPAGES ----> +------------------------------+
- * | R/O UENVS | R-/R- NBPD
- * UTOP,UENVS -------> +------------------------------+
- * UXSTACKTOP -/ | user exception stack | RW/RW NBPG
- * +------------------------------+
- * | Invalid memory | --/-- NBPG
- * USTACKTOP ----> +------------------------------+
- * | normal user stack | RW/RW NBPG
- * +------------------------------+
- * | |
- * | |
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * . .
- * . .
- * . .
- * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
- * | |
- * UTEXT -------> +------------------------------+
- * | | 2 * NBPD
- * 0 ------------> +------------------------------+
- */
+/* Page table (bits 12:21). */
+#define PTSHIFT PGBITS /* First page table bit. */
+#define PTBITS 10 /* Number of page table bits. */
+#define PTMASK MASK(PTSHIFT, PTBITS)
+/* Page directory (bits 22:31). */
+#define PDSHIFT (PTSHIFT + PTBITS) /* First page dir bit. */
+#define PDBITS 10 /* Number of page dir bits. */
+#define PDMASK MASK(PDSHIFT, PDBITS)
-#define PHYS_BASE 0xc0000000 /* All physical memory mapped here. */
-#define KERN_BASE 0xc0100000 /* Kernel loaded here. */
-
-/* Virtual page table. Last entry of all PDEs contains a pointer to
- * the PD itself, thereby turning the PD into a page table which
- * maps all PTEs over the last 4 Megs of the virtual address space */
-#define VPT (KERNBASE - NBPD)
-#define KSTACKTOP VPT
-#define KSTKSIZE (8 * NBPG) /* size of a kernel stack */
-#define ULIM (KSTACKTOP - NBPD)
-
-/*
- * User read-only mappings! Anything below here til UTOP are readonly to user.
- * They are global pages mapped in at env allocation time.
- */
+#ifndef __ASSEMBLER__
+/* Offset within a page. */
+static inline unsigned pg_ofs (void *va) { return (uintptr_t) va & PGMASK; }
-/* Same as VPT but read-only for users */
-#define UVPT (ULIM - NBPD)
-/* Read-only copies of all ppage structures */
-#define UPPAGES (UVPT - NBPD)
-/* Read only copy of the global env structures */
-#define UENVS (UPPAGES - NBPD)
+/* Page number. */
+static inline uintptr_t pg_no (void *va) { return (uintptr_t) va >> PTSHIFT; }
+/* Page table number. */
+static inline unsigned pt_no (void *va) {
+ return ((uintptr_t) va & PTMASK) >> PTSHIFT;
+}
+/* Page directory number. */
+static inline uintptr_t pd_no (void *va) { return (uintptr_t) va >> PDSHIFT; }
-/*
- * Top of user VM. User can manipulate VA from UTOP-1 and down!
- */
-#define UTOP UENVS
-#define UXSTACKTOP (UTOP) /* one page user exception stack */
-/* leave top page invalid to guard against exception stack overflow */
-#define USTACKTOP (UTOP - 2*NBPG) /* top of the normal user stack */
-#define UTEXT (2*NBPD)
+/* Round up to nearest page boundary. */
+static inline void *pg_round_up (void *va) {
+ return (void *) (((uintptr_t) va + PGSIZE - 1) & ~PGMASK);
+}
-/* Number of page tables for mapping physical memory at KERNBASE.
- * (each PT contains 1K PTE's, for a total of 128 Megabytes mapped) */
-#define NPPT ((-KERNBASE)>>PDSHIFT)
+/* Round down to nearest page boundary. */
+static inline void *pg_round_down (void *va) {
+ return (void *) ((uintptr_t) va & ~PGMASK);
+}
-#ifndef __ASSEMBLER__
-#include "debug.h"
+#define PHYS_BASE ((void *) LOADER_PHYS_BASE)
-/* Kernel virtual address at which physical address PADDR is
- mapped. */
+/* Returns kernel virtual address at which physical address PADDR
+ is mapped. */
static inline void *
-ptov (uint32_t paddr)
+ptov (uintptr_t paddr)
{
- ASSERT (paddr < PHYS_BASE);
+ ASSERT ((void *) paddr < PHYS_BASE);
return (void *) (paddr + PHYS_BASE);
}
-/* Physical address at which kernel virtual address VADDR is
- mapped. */
-static inline uint32_t
+/* Returns physical address at which kernel virtual address VADDR
+ is mapped. */
+static inline uintptr_t
vtop (void *vaddr)
{
- ASSERT ((uint32_t) vaddr >= PHYS_BASE);
+ ASSERT (vaddr >= PHYS_BASE);
- return (uint32_t) vaddr - PHYS_BASE;
+ return (uintptr_t) vaddr - (uintptr_t) PHYS_BASE;
}
#endif
-#define PFM_NONE 0x0 /* No page faults expected. Must be a kernel bug */
-#define PFM_KILL 0x1 /* On fault kill user process. */
-
-
-/*
- * Macros to build GDT entries in assembly.
- */
-#define SEG_NULL \
- .word 0, 0; \
- .byte 0, 0, 0, 0
-#define SEG(type,base,lim) \
- .word ((lim)&0xffff), ((base)&0xffff); \
- .byte (((base)>>16)&0xff), (0x90|(type)), \
- (0xc0|(((lim)>>16)&0xf)), (((base)>>24)&0xff)
-
-
-
/* Page Table/Directory Entry flags
* these are defined by the hardware
*/
#define PG_P 0x1 /* Present */
#define PG_W 0x2 /* Writeable */
#define PG_U 0x4 /* User */
-#define PG_PWT 0x8 /* Write-Through */
-#define PG_PCD 0x10 /* Cache-Disable */
#define PG_A 0x20 /* Accessed */
#define PG_D 0x40 /* Dirty */
-#define PG_PS 0x80 /* Page Size */
-#define PG_MBZ 0x180 /* Bits must be zero */
-#define PG_USER 0xe00 /* Bits for user processes */
-/*
- * The PG_USER bits are not used by the kernel and they are
- * not interpreted by the hardware. The kernel allows
- * user processes to set them arbitrarily.
- */
-
-
-
-/* Control Register flags */
-#define CR0_PE 0x1 /* Protection Enable */
-#define CR0_MP 0x2 /* Monitor coProcessor */
-#define CR0_EM 0x4 /* Emulation */
-#define CR0_TS 0x8 /* Task Switched */
-#define CR0_ET 0x10 /* Extension Type */
-#define CR0_NE 0x20 /* Numeric Errror */
-#define CR0_WP 0x10000 /* Write Protect */
-#define CR0_AM 0x40000 /* Alignment Mask */
-#define CR0_NW 0x20000000 /* Not Writethrough */
-#define CR0_CD 0x40000000 /* Cache Disable */
-#define CR0_PG 0x80000000 /* Paging */
-
-#define CR4_PCE 0x100 /* Performance counter enable */
-#define CR4_MCE 0x40 /* Machine Check Enable */
-#define CR4_PSE 0x10 /* Page Size Extensions */
-#define CR4_DE 0x08 /* Debugging Extensions */
-#define CR4_TSD 0x04 /* Time Stamp Disable */
-#define CR4_PVI 0x02 /* Protected-Mode Virtual Interrupts */
-#define CR4_VME 0x01 /* V86 Mode Extensions */
/* EFLAGS Register. */
-#define FLAG_CF 0x00000001 /* Carry Flag. */
-#define FLAG_PF 0x00000004 /* Parity Flag. */
-#define FLAG_AF 0x00000010 /* Auxiliary Carry Flag. */
-#define FLAG_ZF 0x00000040 /* Zero Flag. */
-#define FLAG_SF 0x00000080 /* Sign Flag. */
-#define FLAG_TF 0x00000100 /* Trap Flag. */
+#define FLAG_MBS 0x00000002 /* Must be set. */
#define FLAG_IF 0x00000200 /* Interrupt Flag. */
-#define FLAG_DF 0x00000400 /* Direction Flag. */
-#define FLAG_OF 0x00000800 /* Overflow Flag. */
-#define FLAG_IOPL 0x00003000 /* I/O Privilege Level (2 bits). */
-#define FLAG_IOPL_SHIFT 12
-#define FLAG_NT 0x00004000 /* Nested Task. */
-#define FLAG_RF 0x00010000 /* Resume Flag. */
-#define FLAG_VM 0x00020000 /* Virtual 8086 Mode. */
-#define FLAG_AC 0x00040000 /* Alignment Check. */
-#define FLAG_VIF 0x00080000 /* Virtual Interrupt Flag. */
-#define FLAG_VIP 0x00100000 /* Virtual Interrupt Pending. */
-#define FLAG_ID 0x00200000 /* ID Flag. */
/* Page fault error codes */
#define FEC_PR 0x1 /* Page fault caused by protection violation */
#define STA_W 0x2 /* Writeable (non-executable segments) */
-/* Segment selectors. */
-#define SEL_NULL 0x00 /* Null selector. */
-#define SEL_KCSEG 0x08 /* Kernel code selector. */
-#define SEL_KDSEG 0x10 /* Kernel data selector. */
-#define SEL_UCSEG 0x18 /* Kernel code selector. */
-#define SEL_UDSEG 0x20 /* Kernel data selector. */
-#define SEL_TSS 0x28 /* Task-state segment. */
-#define SEL_CNT 6 /* Number of segments. */
-
-#ifndef __ASSEMBLER__
-struct tss
- {
- uint16_t back_link, :16;
- uint32_t esp0;
- uint16_t ss0, :16;
- uint32_t esp1;
- uint16_t ss1, :16;
- uint32_t esp2;
- uint16_t ss2, :16;
- uint32_t cr3;
- uint32_t eip;
- uint32_t eflags;
- uint32_t eax, ecx, edx, ebx;
- uint32_t esp, ebp, esi, edi;
- uint16_t es, :16;
- uint16_t cs, :16;
- uint16_t ss, :16;
- uint16_t ds, :16;
- uint16_t fs, :16;
- uint16_t gs, :16;
- uint16_t ldt, :16;
- uint16_t trace, bitmap;
- };
-
-enum seg_system
- {
- SYS_SYSTEM = 0, /* System segment. */
- SYS_CODE_DATA = 1 /* Code or data segment. */
- };
-
-enum seg_granularity
- {
- GRAN_BYTE = 0, /* Limit has 1-byte granularity. */
- GRAN_PAGE = 1 /* Limit has 4 kB granularity. */
- };
-
-enum seg_type
- {
- /* System segment types. */
- TYPE_TSS_16_A = 1, /* 16-bit TSS (available). */
- TYPE_LDT = 2, /* LDT. */
- TYPE_TSS_16_B = 3, /* 16-bit TSS (busy). */
- TYPE_CALL_16 = 4, /* 16-bit call gate. */
- TYPE_TASK = 5, /* Task gate. */
- TYPE_INT_16 = 6, /* 16-bit interrupt gate. */
- TYPE_TRAP_16 = 7, /* 16-bit trap gate. */
- TYPE_TSS_32_A = 9, /* 32-bit TSS (available). */
- TYPE_TSS_32_B = 11, /* 32-bit TSS (busy). */
- TYPE_CALL_32 = 12, /* 32-bit call gate. */
- TYPE_INT_32 = 14, /* 32-bit interrupt gate. */
- TYPE_TRAP_32 = 15, /* 32-bit trap gate. */
-
- /* Code/data segment types. */
- TYPE_CODE = 8, /* 1=Code segment, 0=data segment. */
- TYPE_ACCESSED = 1, /* Set if accessed. */
-
- /* Data segment types. */
- TYPE_EXPAND_DOWN = 4, /* 1=Expands up, 0=expands down. */
- TYPE_WRITABLE = 2, /* 1=Read/write, 0=read-only. */
-
- /* Code segment types. */
- TYPE_CONFORMING = 4, /* 1=Conforming, 0=nonconforming. */
- TYPE_READABLE = 2 /* 1=Exec/read, 0=exec-only. */
- };
-
-static inline uint64_t
-make_dtr_operand (uint16_t limit, void *base)
-{
- return limit | ((uint64_t) (uint32_t) base << 16);
-}
-#endif
#endif /* !_MMU_H_ */