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_030_MMU_H
6#define _KERNEL_ARCH_M68K_030_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//#define MMU_HAS_GLOBAL_PAGES
16
17/* This is the normal layout of the descriptors, as per documentation.
18 * When page size > 256, several bits are unused in the LSB of page
19 * addresses, which we can use in addition of other unused bits.
20 * the structs dedlared later reflect this for 4K pages.
21 */
22											// = names in MC user's manual
23											// or comments
24struct short_page_directory_entry {
25	// upper 32 bits
26	uint32 addr : 28;						// address
27	uint32 accessed : 1;					// = used
28	uint32 write_protect : 1;
29	uint32 type : 2;						// DT_*
30};
31
32struct long_page_directory_entry {
33	// upper 32 bits
34	uint32 low_up : 1;						// limit is lower(1)/upper(0)
35	uint32 limit : 15;
36	uint32 _ones : 6;
37	uint32 _zero2 : 1;
38	uint32 supervisor : 1;
39	uint32 _zero1 : 4;
40	uint32 accessed : 1;					// = used
41	uint32 write_protect : 1;
42	uint32 type : 2;
43	// lower 32 bits
44	uint32 addr : 28;						// address
45	uint32 unused : 4;						//
46};
47
48struct short_page_table_entry {
49	uint32 addr : 24;						// address
50	uint32 _zero2 : 1;
51	uint32 cache_disabled : 1;				// = cache_inhibit
52	uint32 _zero1 : 1;
53	uint32 dirty : 1;						// = modified
54	uint32 accessed : 1;					// = used
55	uint32 write_protect : 1;
56	uint32 type : 2;
57};
58
59struct long_page_table_entry {
60	// upper 32 bits
61	uint32 low_up : 1;						// limit is lower(1)/upper(0)
62	// limit only used on early table terminators, else unused
63	uint32 limit : 15;
64	uint32 _ones : 6;
65	uint32 _zero3 : 1;
66	uint32 supervisor : 1;
67	uint32 _zero2 : 1;
68	uint32 cache_disabled : 1;				// = cache_inhibit
69	uint32 _zero1 : 1;
70	uint32 dirty : 1;						// = modified
71	uint32 accessed : 1;					// = used
72	uint32 write_protect : 1;
73	uint32 type : 2;
74	// lower 32 bits
75	uint32 addr : 24;						// address
76	uint32 unused : 8;						//
77};
78
79/* rarely used */
80struct short_indirect_entry {
81	// upper 32 bits
82	uint32 addr : 30;						// address
83	uint32 type : 2;						// DT_*
84};
85
86struct long_indirect_entry {
87	// upper 32 bits
88	uint32 unused1 : 30;
89	uint32 type : 2;
90	// lower 32 bits
91	uint32 addr : 30;						// address
92	uint32 unused2 : 2;						//
93};
94
95/* for clarity:
96   - the top level page directory will be called "page root", (root or rtdir)
97   - the 2nd level will be "page directory" like on x86, (pgdir)
98   - the 3rd level is a "page table" as on x86. (pgtbl)
99*/
100
101typedef struct short_page_directory_entry page_root_entry;
102typedef struct short_page_directory_entry page_directory_entry;
103typedef struct long_page_table_entry page_table_entry;
104typedef struct long_indirect_entry page_indirect_entry;
105
106/* scalar storage type that maps them */
107typedef uint32 page_root_entry_scalar;
108typedef uint32 page_directory_entry_scalar;
109typedef uint64 page_table_entry_scalar;
110typedef uint64 page_indirect_entry_scalar;
111
112#define DT_ROOT DT_VALID_4
113#define DT_DIR DT_VALID_8
114//#define DT_PAGE DT_PAGE :)
115#define DT_INDIRECT DT_VALID_8
116
117/* default scalar values for entries */
118#define DFL_ROOTENT_VAL 0x00000000
119#define DFL_DIRENT_VAL 0x00000000
120// limit disabled, 6bits at 1
121// (limit isn't used on that level, but just in case)
122#define DFL_PAGEENT_VAL 0x7FFFFC0000000000LL
123
124#define NUM_ROOTENT_PER_TBL 128
125#define NUM_DIRENT_PER_TBL 128
126#define NUM_PAGEENT_PER_TBL 64
127
128/* unlike x86, the root/dir/page table sizes are different than B_PAGE_SIZE
129 * so we will have to fit more than one on a page to avoid wasting space.
130 * We will allocate a group of tables with the one we want inside, and
131 * add them from the aligned index needed, to make it easy to free them.
132 */
133
134#define SIZ_ROOTTBL (NUM_ROOTENT_PER_TBL * sizeof(page_root_entry))
135#define SIZ_DIRTBL (NUM_DIRENT_PER_TBL * sizeof(page_directory_entry))
136#define SIZ_PAGETBL (NUM_PAGEENT_PER_TBL * sizeof(page_table_entry))
137
138//#define NUM_ROOTTBL_PER_PAGE (B_PAGE_SIZE / SIZ_ROOTTBL)
139#define NUM_DIRTBL_PER_PAGE (B_PAGE_SIZE / SIZ_DIRTBL)
140#define NUM_PAGETBL_PER_PAGE (B_PAGE_SIZE / SIZ_PAGETBL)
141
142/* macros to get the physical page or table number and address of tables from
143 * descriptors */
144#if 0
145/* XXX:
146   suboptimal:
147   struct foo {
148   int a:2;
149   int b:30;
150   } v = {...};
151   *(int *)0 = (v.b) << 2;
152   generates:
153   sarl    $2, %eax
154   sall    $2, %eax
155   We use a cast + bitmasking, since all address fields are already shifted
156*/
157// from a root entry
158#define PREA_TO_TA(a) ((a) << 4)
159#define PREA_TO_PN(a) ((a) >> (12-4))
160#define PREA_TO_PA(a) ((a) << 4)
161#define TA_TO_PREA(a) ((a) >> 4)
162//...
163#endif
164
165// TA: table address
166// PN: page number
167// PA: page address
168// PO: page offset (offset of table in page)
169// PI: page index (index of table relative to page start)
170
171// from a root entry
172#define PRE_TO_TA(a) ((*(uint32 *)(&(a))) & ~((1<<4)-1))
173#define PRE_TO_PN(e) ((*(uint32 *)(&(e))) >> 12)
174#define PRE_TO_PA(e) ((*(uint32 *)(&(e))) & ~((1<<12)-1))
175//#define PRE_TO_PO(e) ((*(uint32 *)(&(e))) & ((1<<12)-1))
176//#define PRE_TO_PI(e) (((*(uint32 *)(&(e))) & ((1<<12)-1)) / SIZ_DIRTBL)
177#define TA_TO_PREA(a) ((a) >> 4)
178// from a directory entry
179#define PDE_TO_TA(a) ((*(uint32 *)(&(a))) & ~((1<<4)-1))
180#define PDE_TO_PN(e) ((*(uint32 *)(&(e))) >> 12)
181#define PDE_TO_PA(e) ((*(uint32 *)(&(e))) & ~((1<<12)-1))
182//#define PDE_TO_PO(e) ((*(uint32 *)(&(e))) & ((1<<12)-1))
183//#define PDE_TO_PI(e) (((*(uint32 *)(&(e))) & ((1<<12)-1)) / SIZ_PAGETBL)
184#define TA_TO_PDEA(a) ((a) >> 4)
185// from a table entry
186#define PTE_TO_TA(a) ((((uint32 *)(&(a)))[1]) & ~((1<<8)-1))
187#define PTE_TO_PN(e) ((((uint32 *)(&(e)))[1]) >> 12)
188#define PTE_TO_PA(e) ((((uint32 *)(&(e)))[1]) & ~((1<<12)-1))
189#define TA_TO_PTEA(a) ((a) >> 8)
190// from an indirect entry
191#define PIE_TO_TA(a) ((((uint32 *)(&(a)))[1]) & ~((1<<2)-1))
192#define PIE_TO_PN(e) ((((uint32 *)(&(e)))[1]) >> 12)
193#define PIE_TO_PA(e) ((((uint32 *)(&(e)))[1]) & ~((1<<12)-1))
194#define PIE_TO_PO(e) ((((uint32 *)(&(e)))[1]) & ((1<<12)-(1<<2)))
195#define TA_TO_PIEA(a) ((a) >> 2)
196
197/* 7/7/6 split */
198#define VADDR_TO_PRENT(va) (((va) / B_PAGE_SIZE) / (64*128))
199#define VADDR_TO_PDENT(va) ((((va) / B_PAGE_SIZE) / 64) % 128)
200#define VADDR_TO_PTENT(va) (((va) / B_PAGE_SIZE) % 64)
201
202#endif	/* _KERNEL_ARCH_M68K_030_MMU_H */
203