OSDN Git Service

first commit
[winexe-harib/winexe-harib.git] / haribote / MemMan.cpp
1 #include "MemMan.h"
2 #include "naskfunc.h"
3 #include "debug.h"
4 #include "vector.h"
5
6 #define EFLAGS_AC_BIT           0x00040000
7 #define CR0_CACHE_DISABLE       0x60000000
8
9 BYTE MemMan::buf[sizeof(MemMan)];
10
11 void MemMan::Init(){
12         new ((void *)buf) MemMan();
13 }
14
15 MemMan::MemMan(void)
16 {
17         debugprint("memory checking...\n");
18         memsize = memtest(SECOND_BEGIN, 0xbfffffff);
19         if(memsize >= 0x80000000){
20                 memsize = 0x80000000;
21         }
22         debugprint("memory:%d (max mem is 2G byte)\n", memsize);
23
24         //0~memsize-1\82Ü\82Å\8eg\82¦\82é
25         pagecount = (FIRST_END - FIRST_BEGIN) / PAGE_SIZE + memsize / PAGE_SIZE;
26         pages_for_pageinfo = (pagecount * sizeof(PAGEINFO) + PAGE_SIZE - 1) / PAGE_SIZE;
27         //0x00001000 - 0x0009efff\82É\93ü\82éBLOCKINFO\82Ì\90\94\82ð\8cv\8eZ
28         maxfirst = (FIRST_END - FIRST_BEGIN) / sizeof(PAGEINFO);
29
30         for(int i = 0; i < pagecount; i++){
31                 PAGEINFO &pi = *getpageinfo(i);
32                 if(i < pages_for_pageinfo){
33                         //PAGEINFO\8ai\94[\82É\97\98\97p\82³\82ê\82é\83y\81[\83W
34                         pi.commited = 1;
35                         pi.unpageoutable = 1;
36                         pi.system = 1;
37                         pi.pid = 0;
38                 }else{
39                         pi.commited = 0;
40                         pi.unpageoutable = 0;
41                         pi.system = 0;
42                         pi.pid = 0;
43                 }
44         }
45
46         minfo = new Vector<MEMINFO>(0);
47 }
48
49
50 MemMan::~MemMan(void)
51 {
52         delete minfo;
53 }
54
55 MemMan::PAGEINFO *MemMan::getpageinfo(DWORD i){
56         if(pagecount <= i){
57                 return NULL;
58         }
59         if(i < maxfirst){
60                 //\88ê\82Â\96Ú\82Ì\8bó\82«\97Ì\88æ
61                 return (PAGEINFO *)(FIRST_BEGIN + i * sizeof(PAGEINFO));
62         }else{
63                 return (PAGEINFO *)(SECOND_BEGIN + (i - maxfirst) * sizeof(PAGEINFO));
64         }
65 }
66
67 DWORD MemMan::getpageaddr(DWORD i){
68         if(pagecount <= i){
69                 return -1;
70         }
71         if(FIRST_BEGIN + i * PAGE_SIZE < FIRST_END){
72                 return FIRST_BEGIN + i * PAGE_SIZE;
73         }else{
74                 return SECOND_BEGIN + (i - (FIRST_END - FIRST_BEGIN) / PAGE_SIZE) * PAGE_SIZE;
75         }
76 }
77
78 DWORD MemMan::getpageindex(DWORD addr){
79         DWORD pageindex = 0;
80         if(addr < FIRST_END){
81                 pageindex = (addr - FIRST_BEGIN) / PAGE_SIZE;
82         }else{
83                 pageindex = (FIRST_END - FIRST_BEGIN) / PAGE_SIZE + (addr - SECOND_BEGIN) / PAGE_SIZE;
84         }
85         return pageindex;
86 }
87
88 DWORD MemMan::malloc(bool unpageoutable, bool system, DWORD pid, DWORD count){
89         for(int i = 0; i < pagecount - count + 1; i++){
90                 bool allocable = true;
91                 for(DWORD j = 0; j < count; j++){
92                         if(getpageinfo(i + j)->commited){
93                                 allocable = false;
94                                 break;
95                         }
96                 }
97                 if(allocable){
98                         for(DWORD j = 0; j < count; j++){
99                                 //debugprint("malloc phy:%p\n", getpageaddr(i + j));
100                                 PAGEINFO &pi = *getpageinfo(i + j);
101                                 pi.commited = 1;
102                                 pi.unpageoutable = unpageoutable;
103                                 pi.pid = pid;
104                                 pi.system = system;
105                         }
106
107                         return getpageaddr(i);
108                 }
109         }
110 }
111
112 void MemMan::free(DWORD addr, DWORD count){
113         DWORD pageindex = getpageindex(addr);
114         for(DWORD i = 0; i < count; i++){
115                 //debugprint("free phy:%p\n", getpageaddr(pageindex + i));
116                 getpageinfo(pageindex + i)->commited = 0;
117         }
118 }
119
120
121 DWORD MemMan::memtest(DWORD start, DWORD end)
122 {
123         bool flg486 = false;
124         DWORD eflg, cr0, i;
125
126         /* 386\82©\81A486\88È\8d~\82È\82Ì\82©\82Ì\8am\94F */
127         eflg = io_load_eflags();
128         eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
129         io_store_eflags(eflg);
130         eflg = io_load_eflags();
131         if ((eflg & EFLAGS_AC_BIT) != 0) { /* 386\82Å\82ÍAC=1\82É\82µ\82Ä\82à\8e©\93®\82Å0\82É\96ß\82Á\82Ä\82µ\82Ü\82¤ */
132                 flg486 = true;
133         }
134         eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
135         io_store_eflags(eflg);
136
137         if (flg486) {
138                 cr0 = load_cr0();
139                 cr0 |= CR0_CACHE_DISABLE; /* \83L\83\83\83b\83V\83\85\8bÖ\8e~ */
140                 store_cr0(cr0);
141         }
142
143         i = memtest_sub(start, end);
144
145         if (flg486) {
146                 cr0 = load_cr0();
147                 cr0 &= ~CR0_CACHE_DISABLE; /* \83L\83\83\83b\83V\83\85\8b\96\89 */
148                 store_cr0(cr0);
149         }
150
151         return i;
152 }
153
154 DWORD MemMan::memtest_sub(DWORD start, DWORD end)
155 {
156         volatile DWORD i, *p, old, pat0 = 0xaa55aa55, pat1 = 0x55aa55aa;
157         for (i = start; i <= end; i += 0x1000) {
158                 p = (DWORD *) (i + 0xffc);
159                 old = *p;                       /* \82¢\82\82é\91O\82Ì\92l\82ð\8ao\82¦\82Ä\82¨\82­ */
160                 *p = pat0;                      /* \82½\82ß\82µ\82É\8f\91\82¢\82Ä\82Ý\82é */
161                 *p ^= 0xffffffff;       /* \82»\82µ\82Ä\82»\82ê\82ð\94½\93]\82µ\82Ä\82Ý\82é */
162                 if (*p != pat1) {       /* \94½\93]\8c\8b\89Ê\82É\82È\82Á\82½\82©\81H */
163 not_memory:
164                         *p = old;
165                         break;
166                 }
167                 *p ^= 0xffffffff;       /* \82à\82¤\88ê\93x\94½\93]\82µ\82Ä\82Ý\82é */
168                 if (*p != pat0) {       /* \8c³\82É\96ß\82Á\82½\82©\81H */
169                         goto not_memory;
170                 }
171                 *p = old;                       /* \82¢\82\82Á\82½\92l\82ð\8c³\82É\96ß\82· */
172         }
173         return i;
174 }
175
176
177
178 void *MemMan::sys_malloc(size_t size){
179         MEMINFO m;
180         m.addr = malloc(true, true, 0, (size + PAGE_SIZE - 1) / PAGE_SIZE);
181         m.size = size;
182         minfo->Add(m);
183         debugprint("malloced:%p %p %p\n", m.addr, m.size, (size + PAGE_SIZE - 1) / PAGE_SIZE);
184
185         return (void *)m.addr;
186 }
187
188 void MemMan::sys_free(void *p){
189         DWORD i = 0;
190         for(i = 0; i < minfo->GetCount(); i++){
191                 if((*minfo)[i]->addr == (DWORD)p){
192                         break;
193                 }
194         }
195         if(i == minfo->GetCount()){
196                 debugprint("sys_free error");
197                 hung();
198                 return;
199         }
200         MEMINFO m = *((*minfo)[i]);
201         free(m.addr, (m.size + PAGE_SIZE - 1) / PAGE_SIZE);
202         debugprint("freed:%p %p\n", m.addr, m.size);
203
204         minfo->Remove(i);
205 }