1/*
2** Copyright 2003, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3** Distributed under the terms of the MIT License.
4*/
5#ifndef _KERNEL_ARCH_M68K_040_MMU_H
6#define _KERNEL_ARCH_M68K_040_MMU_H
7
8
9#include <SupportDefs.h>
10#include <string.h>
11
12#include <arch_mmu.h>
13
14// global pages only available on 040/060
15// check this
16#define MMU_HAS_GLOBAL_PAGES
17
18
19enum _mmu040_cache_mode {
20	CM_CACHABLE_WRITETHROUGH,
21	CM_CACHABLE_COPYBACK,
22	CM_DISABLED_SERIALIZED,
23	CM_DISABLED,
24};
25
26/* This is the normal layout of the descriptors, as per documentation.
27 * When page size > 256, several bits are unused in the LSB of page
28 * addresses, which we can use in addition of other unused bits.
29 * the structs dedlared later reflect this for 4K pages.
30 */
31											// = names in MC user's manual
32											// or comments
33struct short_page_directory_entry {
34	// upper 32 bits
35	uint32 addr : 28;						// address
36	uint32 accessed : 1;					// = used
37	uint32 write_protect : 1;
38	uint32 type : 2;						// DT_*
39};
40
41struct short_page_table_entry {
42	uint32 addr : 20;						// address
43	uint32 user_reserved : 1;
44	uint32 global : 1;
45	uint32 upa0 : 1;						// User Page Attribute 0
46	uint32 upa1 : 1;						// User Page Attribute 1
47	uint32 supervisor : 1;
48	uint32 cache_mode : 2;
49	uint32 dirty : 1;						// = modified
50	uint32 accessed : 1;					// = used
51	uint32 write_protect : 1;
52	uint32 type : 2;
53};
54
55/* rarely used */
56struct short_indirect_entry {
57	// upper 32 bits
58	uint32 addr : 30;						// address
59	uint32 type : 2;						// DT_*
60};
61
62/* for clarity:
63   - the top level page directory will be called "page root", (root or rtdir)
64   - the 2nd level will be "page directory" like on x86, (pgdir)
65   - the 3rd level is a "page table" as on x86. (pgtbl)
66*/
67
68/* struct types suffixed with _s */
69typedef struct short_page_directory_entry page_root_entry_s;
70typedef struct short_page_directory_entry page_directory_entry_s;
71typedef struct short_page_table_entry page_table_entry_s;
72typedef struct short_indirect_entry page_indirect_entry_s;
73
74/* scalar storage type that maps them */
75typedef uint32 page_root_entry;
76typedef uint32 page_directory_entry;
77typedef uint32 page_table_entry;
78typedef uint32 page_indirect_entry;
79
80#define DT_ROOT DT_VALID_4
81#define DT_DIR DT_VALID_4
82//#define DT_PAGE DT_PAGE :)
83#define DT_INDIRECT DT_VALID_4
84
85/* bitmask access */
86
87/* those are valid for all entries */
88#define M68K_PE_READONLY			0x00000004
89#define M68K_PE_ACCESSED			0x00000008
90
91#define M68K_PRE_READONLY		T	M68K_PE_READONLY
92#define M68K_PRE_ACCESSED			M68K_PE_ACCESSED
93#define M68K_PRE_ADDRESS_MASK		0xfffffff0
94
95#define M68K_PDE_READONLY			M68K_PE_READONLY
96#define M68K_PDE_ACCESSED			M68K_PE_ACCESSED
97#define M68K_PDE_ADDRESS_MASK		0xfffffff0
98
99#define M68K_PTE_READONLY			M68K_PE_READONLY
100#define M68K_PTE_ACCESSED			M68K_PE_ACCESSED
101#define M68K_PTE_DIRTY				0x00000010
102#define M68K_PTE_CACHE_MODE_MASK	0x00000060
103#define M68K_PTE_CACHE_MODE_SHIFT	5
104
105#define M68K_PTE_SUPERVISOR			0x00000080
106#define M68K_PTE_UPA1				0x00000100
107#define M68K_PTE_UPA0				0x00000200
108#define M68K_PTE_GLOBAL				0x00000400
109#define M68K_PTE_USER_RESERVED		0x00000800
110#define M68K_PTE_ADDRESS_MASK		0xfffff000
111
112
113#define M68K_PIE_ADDRESS_MASK		0xfffffffc
114
115
116
117/* default scalar values for entries */
118#define DFL_ROOTENT_VAL 0x00000000
119#define DFL_DIRENT_VAL 0x00000000
120#define DFL_PAGEENT_VAL 0x00000000
121
122#define NUM_ROOTENT_PER_TBL 128
123#define NUM_DIRENT_PER_TBL 128
124#define NUM_PAGEENT_PER_TBL 64
125
126/* unlike x86, the root/dir/page table sizes are different than B_PAGE_SIZE
127 * so we will have to fit more than one on a page to avoid wasting space.
128 * We will allocate a group of tables with the one we want inside, and
129 * add them from the aligned index needed, to make it easy to free them.
130 */
131
132#define SIZ_ROOTTBL (NUM_ROOTENT_PER_TBL * sizeof(page_root_entry))
133#define SIZ_DIRTBL (NUM_DIRENT_PER_TBL * sizeof(page_directory_entry))
134#define SIZ_PAGETBL (NUM_PAGEENT_PER_TBL * sizeof(page_table_entry))
135
136//#define NUM_ROOTTBL_PER_PAGE (B_PAGE_SIZE / SIZ_ROOTTBL)
137#define NUM_DIRTBL_PER_PAGE (B_PAGE_SIZE / SIZ_DIRTBL)
138#define NUM_PAGETBL_PER_PAGE (B_PAGE_SIZE / SIZ_PAGETBL)
139
140/* macros to get the physical page or table number and address of tables from
141 * descriptors */
142
143// TA: table address
144// PN: page number
145// PA: page address
146// PO: page offset (offset of table in page)
147// PI: page index (index of table relative to page start)
148
149// from a root entry
150#define PRE_TYPE(e)  	((e) & M68K_PE_DT_MASK)
151#define PRE_TO_TA(e)	(((uint32)(e)) & ~((1<<9)-1))
152#define PRE_TO_PN(e)	(((uint32)(e)) >> 12)
153#define PRE_TO_PA(e)	(((uint32)(e)) & ~((1<<12)-1))
154//#define PRE_TO_PO(e)	(((uint32)(e)) & ((1<<12)-1))
155//#define PRE_TO_PI(e)	((((uint32)(e)) & ((1<<12)-1)) / SIZ_DIRTBL)
156#define TA_TO_PREA(a)	((a) & M68K_PRE_ADDRESS_MASK)
157
158// from a directory entry
159#define PDE_TYPE(e)  	((e) & M68K_PE_DT_MASK)
160#define PDE_TO_TA(e)	(((uint32)(e)) & ~((1<<8)-1))
161#define PDE_TO_PN(e)	(((uint32)(e)) >> 12)
162#define PDE_TO_PA(e)	(((uint32)(e)) & ~((1<<12)-1))
163//#define PDE_TO_PO(e)	(((uint32)(e)) & ((1<<12)-1))
164//#define PDE_TO_PI(e)	((((uint32)(e)) & ((1<<12)-1)) / SIZ_PAGETBL)
165#define TA_TO_PDEA(a)	((a) & M68K_PDE_ADDRESS_MASK)
166
167// from a table entry
168#define PTE_TYPE(e)  	((e) & M68K_PE_DT_MASK)
169#define PTE_TO_TA(e)	(((uint32)(e)) & ~((1<<12)-1))
170#define PTE_TO_PN(e)	(((uint32)(e)) >> 12)
171#define PTE_TO_PA(e)	(((uint32)(e)) & ~((1<<12)-1))
172#define TA_TO_PTEA(a)	((a) & M68K_PTE_ADDRESS_MASK)
173
174// from an indirect entry
175#define PIE_TYPE(e)  	((e) & M68K_PE_DT_MASK)
176#define PIE_TO_TA(e)	(((uint32)(e)) & ~((1<<2)-1))
177#define PIE_TO_PN(e)	(((uint32)(e)) >> 12)
178#define PIE_TO_PA(e)	(((uint32)(e)) & ~((1<<12)-1))
179#define PIE_TO_PO(e)	(((uint32)(e)) & ((1<<12)-(1<<2)))
180#define TA_TO_PIEA(a)	((a) & M68K_PIE_ADDRESS_MASK)
181
182/* 7/7/6 split */
183#define VADDR_TO_PRENT(va)	(((va) / B_PAGE_SIZE) / (64*128))
184#define VADDR_TO_PDENT(va)	((((va) / B_PAGE_SIZE) / 64) % 128)
185#define VADDR_TO_PTENT(va)	(((va) / B_PAGE_SIZE) % 64)
186
187#endif	/* _KERNEL_ARCH_M68K_040_MMU_H */
188