haiku/headers/private/kernel/arch/m68k/arch_040_mmu.h
François Revol afa453ee2a Make the page table types scalar, to make them simpler to use with atomic ops, and define the corresponding bitmasks.
While structs looked cleaner at first sight, it didn't really was any simpler.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43140 a95241bf-73f2-0310-859d-f6bbb57e9c96
2011-11-02 22:56:20 +00:00

188 lines
5.9 KiB
C

/*
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#ifndef _KERNEL_ARCH_M68K_040_MMU_H
#define _KERNEL_ARCH_M68K_040_MMU_H
#include <SupportDefs.h>
#include <string.h>
#include <arch_mmu.h>
// global pages only available on 040/060
// check this
#define MMU_HAS_GLOBAL_PAGES
enum _mmu040_cache_mode {
CM_CACHABLE_WRITETHROUGH,
CM_CACHABLE_COPYBACK,
CM_DISABLED_SERIALIZED,
CM_DISABLED,
};
/* This is the normal layout of the descriptors, as per documentation.
* When page size > 256, several bits are unused in the LSB of page
* addresses, which we can use in addition of other unused bits.
* the structs dedlared later reflect this for 4K pages.
*/
// = names in MC user's manual
// or comments
struct short_page_directory_entry {
// upper 32 bits
uint32 addr : 28; // address
uint32 accessed : 1; // = used
uint32 write_protect : 1;
uint32 type : 2; // DT_*
};
struct short_page_table_entry {
uint32 addr : 20; // address
uint32 user_reserved : 1;
uint32 global : 1;
uint32 upa0 : 1; // User Page Attribute 0
uint32 upa1 : 1; // User Page Attribute 1
uint32 supervisor : 1;
uint32 cache_mode : 2;
uint32 dirty : 1; // = modified
uint32 accessed : 1; // = used
uint32 write_protect : 1;
uint32 type : 2;
};
/* rarely used */
struct short_indirect_entry {
// upper 32 bits
uint32 addr : 30; // address
uint32 type : 2; // DT_*
};
/* for clarity:
- the top level page directory will be called "page root", (root or rtdir)
- the 2nd level will be "page directory" like on x86, (pgdir)
- the 3rd level is a "page table" as on x86. (pgtbl)
*/
/* struct types suffixed with _s */
typedef struct short_page_directory_entry page_root_entry_s;
typedef struct short_page_directory_entry page_directory_entry_s;
typedef struct short_page_table_entry page_table_entry_s;
typedef struct short_indirect_entry page_indirect_entry_s;
/* scalar storage type that maps them */
typedef uint32 page_root_entry;
typedef uint32 page_directory_entry;
typedef uint32 page_table_entry;
typedef uint32 page_indirect_entry;
#define DT_ROOT DT_VALID_4
#define DT_DIR DT_VALID_4
//#define DT_PAGE DT_PAGE :)
#define DT_INDIRECT DT_VALID_4
/* bitmask access */
/* those are valid for all entries */
#define M68K_PE_READONLY 0x00000004
#define M68K_PE_ACCESSED 0x00000008
#define M68K_PRE_READONLY T M68K_PE_READONLY
#define M68K_PRE_ACCESSED M68K_PE_ACCESSED
#define M68K_PRE_ADDRESS_MASK 0xfffffff0
#define M68K_PDE_READONLY M68K_PE_READONLY
#define M68K_PDE_ACCESSED M68K_PE_ACCESSED
#define M68K_PDE_ADDRESS_MASK 0xfffffff0
#define M68K_PTE_READONLY M68K_PE_READONLY
#define M68K_PTE_ACCESSED M68K_PE_ACCESSED
#define M68K_PTE_DIRTY 0x00000010
#define M68K_PTE_CACHE_MODE_MASK 0x00000060
#define M68K_PTE_CACHE_MODE_SHIFT 5
#define M68K_PTE_SUPERVISOR 0x00000080
#define M68K_PTE_UPA1 0x00000100
#define M68K_PTE_UPA0 0x00000200
#define M68K_PTE_GLOBAL 0x00000400
#define M68K_PTE_USER_RESERVED 0x00000800
#define M68K_PTE_ADDRESS_MASK 0xfffff000
#define M68K_PIE_ADDRESS_MASK 0xfffffffc
/* default scalar values for entries */
#define DFL_ROOTENT_VAL 0x00000000
#define DFL_DIRENT_VAL 0x00000000
#define DFL_PAGEENT_VAL 0x00000000
#define NUM_ROOTENT_PER_TBL 128
#define NUM_DIRENT_PER_TBL 128
#define NUM_PAGEENT_PER_TBL 64
/* unlike x86, the root/dir/page table sizes are different than B_PAGE_SIZE
* so we will have to fit more than one on a page to avoid wasting space.
* We will allocate a group of tables with the one we want inside, and
* add them from the aligned index needed, to make it easy to free them.
*/
#define SIZ_ROOTTBL (NUM_ROOTENT_PER_TBL * sizeof(page_root_entry))
#define SIZ_DIRTBL (NUM_DIRENT_PER_TBL * sizeof(page_directory_entry))
#define SIZ_PAGETBL (NUM_PAGEENT_PER_TBL * sizeof(page_table_entry))
//#define NUM_ROOTTBL_PER_PAGE (B_PAGE_SIZE / SIZ_ROOTTBL)
#define NUM_DIRTBL_PER_PAGE (B_PAGE_SIZE / SIZ_DIRTBL)
#define NUM_PAGETBL_PER_PAGE (B_PAGE_SIZE / SIZ_PAGETBL)
/* macros to get the physical page or table number and address of tables from
* descriptors */
// TA: table address
// PN: page number
// PA: page address
// PO: page offset (offset of table in page)
// PI: page index (index of table relative to page start)
// from a root entry
#define PRE_TYPE(e) ((e) & M68K_PE_DT_MASK)
#define PRE_TO_TA(e) (((uint32)(e)) & ~((1<<9)-1))
#define PRE_TO_PN(e) (((uint32)(e)) >> 12)
#define PRE_TO_PA(e) (((uint32)(e)) & ~((1<<12)-1))
//#define PRE_TO_PO(e) (((uint32)(e)) & ((1<<12)-1))
//#define PRE_TO_PI(e) ((((uint32)(e)) & ((1<<12)-1)) / SIZ_DIRTBL)
#define TA_TO_PREA(a) ((a) & M68K_PRE_ADDRESS_MASK)
// from a directory entry
#define PDE_TYPE(e) ((e) & M68K_PE_DT_MASK)
#define PDE_TO_TA(e) (((uint32)(e)) & ~((1<<8)-1))
#define PDE_TO_PN(e) (((uint32)(e)) >> 12)
#define PDE_TO_PA(e) (((uint32)(e)) & ~((1<<12)-1))
//#define PDE_TO_PO(e) (((uint32)(e)) & ((1<<12)-1))
//#define PDE_TO_PI(e) ((((uint32)(e)) & ((1<<12)-1)) / SIZ_PAGETBL)
#define TA_TO_PDEA(a) ((a) & M68K_PDE_ADDRESS_MASK)
// from a table entry
#define PTE_TYPE(e) ((e) & M68K_PE_DT_MASK)
#define PTE_TO_TA(e) (((uint32)(e)) & ~((1<<12)-1))
#define PTE_TO_PN(e) (((uint32)(e)) >> 12)
#define PTE_TO_PA(e) (((uint32)(e)) & ~((1<<12)-1))
#define TA_TO_PTEA(a) ((a) & M68K_PTE_ADDRESS_MASK)
// from an indirect entry
#define PIE_TYPE(e) ((e) & M68K_PE_DT_MASK)
#define PIE_TO_TA(e) (((uint32)(e)) & ~((1<<2)-1))
#define PIE_TO_PN(e) (((uint32)(e)) >> 12)
#define PIE_TO_PA(e) (((uint32)(e)) & ~((1<<12)-1))
#define PIE_TO_PO(e) (((uint32)(e)) & ((1<<12)-(1<<2)))
#define TA_TO_PIEA(a) ((a) & M68K_PIE_ADDRESS_MASK)
/* 7/7/6 split */
#define VADDR_TO_PRENT(va) (((va) / B_PAGE_SIZE) / (64*128))
#define VADDR_TO_PDENT(va) ((((va) / B_PAGE_SIZE) / 64) % 128)
#define VADDR_TO_PTENT(va) (((va) / B_PAGE_SIZE) % 64)
#endif /* _KERNEL_ARCH_M68K_040_MMU_H */