simplified macros

This commit is contained in:
Steffen Vogel 2014-05-14 15:13:11 +02:00
parent c1e52dc8c2
commit 1f641e440c
3 changed files with 49 additions and 33 deletions

View file

@ -68,11 +68,29 @@
/// The number of entries in a page map table /// The number of entries in a page map table
#define PAGE_MAP_ENTRIES (1L << PAGE_MAP_BITS) #define PAGE_MAP_ENTRIES (1L << PAGE_MAP_BITS)
// Base addresses of the self-mapped pagetables
#ifdef CONFIG_X86_32
#define PAGE_MAP_PGD 0xFFFFF000
#define PAGE_MAP_PGT 0xFFC00000
#elif defined(CONFIG_X86_64)
#define PAGE_MAP_PML4 0xFFFFFFFFFFFFF000
#define PAGE_MAP_PDPT 0xFFFFFFFFFFE00000
#define PAGE_MAP_PGD 0xFFFFFFFFC0000000
#define PAGE_MAP_PGT 0xFFFFFF8000000000
#endif
/// Align to next page /// Align to next page
#define PAGE_FLOOR(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) #define PAGE_FLOOR(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
/// Align to page /// Align to page
#define PAGE_CEIL(addr) ( (addr) & PAGE_MASK) #define PAGE_CEIL(addr) ( (addr) & PAGE_MASK)
// Canonical address format
#ifdef CONFIG_x86_32
#define CANONICAL(addr) (addr)
#elif defined(CONFIG_X86_64)
#define CANONICAL(addr) sign_extend(addr, VIRT_BITS)
#endif
/// Page is present /// Page is present
#define PG_PRESENT (1 << 0) #define PG_PRESENT (1 << 0)
/// Page is read- and writable /// Page is read- and writable

View file

@ -37,36 +37,38 @@
*/ */
static inline size_t sign_extend(ssize_t addr, int bits) static inline size_t sign_extend(ssize_t addr, int bits)
{ {
return (addr << -bits) >> -bits; // sign bit is maintained during arithmetic right shift int shift = BITS - bits;
return (addr << shift) >> shift; // sign bit gets copied during arithmetic right shift
} }
/** @brief */ /** @brief Get the base address of the child table
*
* @param entry The parent entry
* @return The child entry
*/
static inline page_entry_t* get_child_entry(page_entry_t *entry) static inline page_entry_t* get_child_entry(page_entry_t *entry)
{ {
size_t child = (size_t) entry; size_t child = (size_t) entry;
child <<= PAGE_MAP_BITS; child <<= PAGE_MAP_BITS;
#ifdef CONFIG_X86_32 return (page_entry_t*) CANONICAL(child);
return (page_entry_t*) child;
#elif defined(CONFIG_X86_64)
return (page_entry_t*) sign_extend(child, VIRT_BITS);
#endif
} }
/** @brief */ /** @brief Get the base address of the parent entry
*
* @param entry The child entry
* @return The parent entry
*/
static inline page_entry_t* get_parent_entry(page_entry_t *entry) static inline page_entry_t* get_parent_entry(page_entry_t *entry)
{ {
size_t parent = (size_t) entry; ssize_t parent = (size_t) entry;
parent >>= PAGE_MAP_BITS; parent >>= PAGE_MAP_BITS;
parent |= (PAGE_MAP_ENTRIES-1) << (PAGE_MAP_LEVELS * PAGE_MAP_BITS + 3); // TODO parent |= PAGE_MAP_PGT;
parent &= ~(sizeof(size_t) - 1); // align to page_entry_t
#ifdef CONFIG_X86_32 return (page_entry_t*) CANONICAL(parent);
return (page_entry_t*) (parent & ~0x3);
#elif defined(CONFIG_X86_64)
return (page_entry_t*) sign_extend(parent & ~0x7, VIRT_BITS);
#endif
} }
/** @brief Get the corresponding page map entry to a given virtual address /** @brief Get the corresponding page map entry to a given virtual address
@ -74,18 +76,15 @@ static inline page_entry_t* get_parent_entry(page_entry_t *entry)
* Please note: this implementation requires that the tables are mapped * Please note: this implementation requires that the tables are mapped
* at the end of VAS! * at the end of VAS!
*/ */
static inline page_entry_t* virt_to_entry(size_t addr, int level) static inline page_entry_t* virt_to_entry(ssize_t addr, int level)
{ {
do {
addr >>= PAGE_MAP_BITS; addr >>= PAGE_MAP_BITS;
addr |= (PAGE_MAP_ENTRIES-1) << (PAGE_MAP_LEVELS * PAGE_MAP_BITS + 3); // TODO addr |= PAGE_MAP_PGT;
} while (level--);
#ifdef CONFIG_X86_32 addr >>= level * PAGE_MAP_BITS;
return (page_entry_t*) (addr & ~0x3); addr &= ~(sizeof(size_t) - 1); // align to page_entry_t
#elif defined(CONFIG_X86_64)
return (page_entry_t*) sign_extend(addr & ~0x7, VIRT_BITS); return (page_entry_t*) CANONICAL(addr);
#endif
} }
/** @brief Get the corresponding virtual address to a page map entry */ /** @brief Get the corresponding virtual address to a page map entry */
@ -95,11 +94,7 @@ static inline size_t entry_to_virt(page_entry_t* entry, int level)
addr <<= (level+1) * PAGE_MAP_BITS; addr <<= (level+1) * PAGE_MAP_BITS;
#ifdef CONFIG_X86_32 return CANONICAL(addr);
return addr;
#elif defined(CONFIG_X86_64)
return sign_extend(addr, VIRT_BITS); // sign extend
#endif
} }
/** @brief Converts a virtual address to a physical /** @brief Converts a virtual address to a physical
@ -150,6 +145,7 @@ size_t get_page_flags(size_t viraddr)
int i; int i;
for (i=1; i<PAGE_MAP_LEVELS; i++) { for (i=1; i<PAGE_MAP_LEVELS; i++) {
entry = virt_to_entry(viraddr, i); entry = virt_to_entry(viraddr, i);
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
flags |= (*entry & PG_XD); flags |= (*entry & PG_XD);
#endif #endif

View file

@ -59,9 +59,9 @@ extern page_entry_t boot_pml4[PAGE_MAP_ENTRIES];
static spinlock_t kslock = SPINLOCK_INIT; static spinlock_t kslock = SPINLOCK_INIT;
/// Mapping of self referenced page map (at the end of the VAS) /// Mapping of self referenced page map (at the end of the VAS)
static page_entry_t* const current_map = (page_entry_t*) (-1*PAGE_SIZE); static page_entry_t* const current_map = (page_entry_t*) (1 * PAGE_MAP_PML4);
static page_entry_t* const src_map = (page_entry_t*) (-2*PAGE_SIZE); static page_entry_t* const src_map = (page_entry_t*) (2 * PAGE_MAP_PML4);
static page_entry_t* const dest_map = (page_entry_t*) (-3*PAGE_SIZE); static page_entry_t* const dest_map = (page_entry_t*) (3 * PAGE_MAP_PML4);
page_entry_t* get_boot_page_map(void) page_entry_t* get_boot_page_map(void)
{ {
@ -159,10 +159,12 @@ void page_stats(int reset)
if (*entry & (1 << i)) if (*entry & (1 << i))
stats[i]++; stats[i]++;
} }
#ifdef CONFIG_X86_64
for (i=0; i<1; i++) { // IA-32e / PAE bits for (i=0; i<1; i++) { // IA-32e / PAE bits
if (*entry & (1 << (63-i))) if (*entry & (1 << (63-i)))
stats[i+PAGE_BITS]++; stats[i+PAGE_BITS]++;
} }
#endif
if (reset) { // reset accessed and dirty bits if (reset) { // reset accessed and dirty bits
*entry &= ~(PG_ACCESSED|PG_DIRTY); *entry &= ~(PG_ACCESSED|PG_DIRTY);