00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018 #include "src/thread/process.hpp"
00019 #include "src/memory/alloc4k.hpp"
00020 #include "src/memory/memset.hpp"
00021 #include "src/memory/align.hpp"
00022 #include "src/memory/heap.hpp"
00023 #include "src/memory/pager.hpp"
00024 #include "src/memory/shmem.hpp"
00025
00026 namespace Memory {
00027 namespace Shmem {
00028
00029
00030
00031
00032
00033 int shmem_create(struct shmem_t *sh, class Memory::Pager::memtree *tree, uint32 virtaddr, uint32 size, bool cow, bool super)
00034 {
00035 struct shmem_s s;
00036 struct blist_s *b;
00037 uint32 n;
00038
00039 if (virtaddr & 0xfff) return EINVAL;
00040 if (size & 0xfff) return EINVAL;
00041
00042 memset(sh, 0, sizeof(struct shmem_t));
00043 sh->li.init("shmem", &Memory::Heap::heap0);
00044 sh->cnt=1;
00045 sh->cows=(cow?1:0);
00046 sh->size=size;
00047 sh->super=super;
00048
00049 memset(&s,0,sizeof(struct shmem_s));
00050 s.cow=cow;
00051 s.lgth=size;
00052 s.offset=0;
00053 s.sm=sh;
00054 s.virtaddr=virtaddr;
00055 s.tree=tree;
00056 b=sh->li.add((void*)&s,sizeof(struct shmem_s),NULL);
00057 if (b==NULL) sysfail("b=null");
00058
00059 tree->memory_map.add(virtaddr, size, ME_SHMEM, b->data, 0, 0, &shmem_mapdone);
00060
00061 sh->pgs= (uint32*)Memory::Heap::heap0.malloc(sizeof(uint32)*size/PAGE_SIZE, NO_ALIGN, 123, NULL);
00062 uint32 i=0;
00063 for(n=0;n<size;n+=PAGE_SIZE)
00064 {
00065 uint32 ph;
00066 ph= tree->pte_val(virtaddr+n);
00067 sh->pgs[i]=ph;
00068 i++;
00069 }
00070
00071 i=0;
00072 if (cow)
00073 for(n=0;n<size;n+=PAGE_SIZE)
00074 {
00075 uint32 ph,nph;
00076 nph=ph= sh->pgs[i];
00077 nph&=0xFFFFFFFF-PTE_WRITEABLE-PTE_USER;
00078 nph|= super?0:PTE_USER;
00079 nph|=PTE_SHMEM;
00080 if (ph&PTE_PRESENT)
00081 tree->pte_map(virtaddr+n, nph);
00082 i++;
00083 }
00084
00085 return ESUCCESS;
00086 }
00087
00088
00089 int shmem_mapdone(mmap_t *mpt, mmap_s *mps)
00090 {
00091 notimpl(-1);
00092 }
00093
00094
00095 int shmem_attach(struct shmem_t *sh, class Memory::Pager::memtree *tree, uint32 virtaddr, uint32 offset, uint32 lgth, bool cow)
00096 {
00097 struct shmem_s shm;
00098 struct blist_s *b;
00099 uint32 n;
00100
00101 sh->cnt++;
00102 if (cow) sh->cows++;
00103
00104 if (cow)
00105 if (sh->cows == 1)
00106 shmem_roall(sh);
00107
00108 uint32 i=offset/PAGE_SIZE;
00109 for (n=0;n<lgth;n+=PAGE_SIZE)
00110 {
00111 uint32 ph;
00112 ph= sh->pgs[i];
00113 cout(ph);cout(const_cast<char*>("|"));
00114 if (ph & PTE_PRESENT)
00115 tree->pte_map(virtaddr+n, (ph&0xfffff000)|(sh->super?0:PTE_USER)|PTE_SHMEM|((sh->cows||cow)?PTE_RO:PTE_WRITEABLE)|PTE_PRESENT);
00116 else
00117 tree->pte_map(virtaddr+n, ph);
00118 i++;
00119 }
00120
00121 memset(&shm,0,sizeof(struct shmem_s));
00122 shm.sm=sh;
00123 shm.tree=tree;
00124 shm.cow=cow;
00125 shm.offset=offset;
00126 shm.virtaddr=virtaddr;
00127 shm.lgth=lgth;
00128 b=sh->li.add((void*)&shm, sizeof(struct shmem_s), NULL);
00129 if (b==NULL) sysfail("b==NULL2");
00130
00131 tree->memory_map.add(virtaddr, lgth, ME_SHMEM, b->data, 0, 0, &shmem_mapdone);
00132
00133 return ESUCCESS;
00134 }
00135
00136
00137 int shmem_roall(struct shmem_t *sh)
00138 {
00139 blist_s *item;
00140 struct shmem_s *sm;
00141 uint32 n;
00142 for (item=sh->li.head;item;item=item->next)
00143 {
00144 sm= bli_dt(item,struct shmem_s*);
00145 for (n=0;n<sm->lgth;n+=PAGE_SIZE)
00146 {
00147 uint32 ph, nph;
00148 nph=ph= sm->tree->pte_val(sm->virtaddr+n);
00149 if (!(ph & PTE_PRESENT)) continue;
00150 if (!(ph & PTE_WRITEABLE)) continue;
00151 nph&=0xffffffff-PTE_WRITEABLE;
00152 sm->tree->pte_map(sm->virtaddr+n, nph);
00153 }
00154 }
00155
00156 return ESUCCESS;
00157 }
00158
00159
00160 int shmem_map(struct shmem_s *sh)
00161 {
00162 uint32 n;
00163 for (n=0; n<sh->lgth; n+=PAGE_SIZE)
00164
00165 sh->tree->pte_map(sh->virtaddr+n,NULL|PTE_SHMEM|(sh->sm->super?0:PTE_USER));
00166 return ESUCCESS;
00167 }
00168
00169 };
00170 };
00171
00172
00173 int shmem_paging_pfh(struct env_t *en, uint32 virt, uint32 phys)
00174 {
00175 struct Memory::Shmem::shmem_s *shs;
00176 struct Memory::Shmem::shmem_s *sh2;
00177 struct Memory::Shmem::shmem_t *sht;
00178 uint32 ofs;
00179
00180 if (!(phys & PTE_SHMEM)) return EINVAL;
00181
00182
00183 struct blist_s *item;
00184 if (en->mtree==NULL) sysfail("en->tree==NULL");
00185 item= en->mtree->memory_map.mmap_find(ME_SHMEM, virt);
00186 if (item==NULL) return EFAIL;
00187 shs= (struct Memory::Shmem::shmem_s*)bli_dt(item,struct mmap_s*)->dt;
00188
00189 sht= shs->sm;
00190
00191 ofs= (virt&0xfffff000)-shs->virtaddr+shs->offset;
00192
00193
00194 if (phys & PTE_PRESENT)
00195
00196 {
00197 if (shs->cow)
00198 {
00199
00200 uint32 ph= alloc4k(1,false);
00201 if (ph==0) { complain("shmem_paging_pfh: cow: insufficient memory!"); return EFAIL; }
00202
00203 en->mtree->pte_map(virt&0xfffff000, ph|(sht->super?0:PTE_USER)|PTE_WRITEABLE|PTE_PRESENT|PTE_SHMEM);
00204
00205 Memory::Pager::cpypage(ph, sht->pgs[ofs/PAGE_SIZE]&0xfffff000);
00206
00207
00208
00209
00210 } else
00211 {
00212
00213 struct blist_s *item;
00214 for (item=sht->li.head;item;item=item->next)
00215 {
00216
00217 sh2= bli_dt(item,struct Memory::Shmem::shmem_s*);
00218 if ((sh2->offset > ofs)||(sh2->offset+sh2->lgth)<ofs) continue;
00219
00220 if (!sh2->cow) continue;
00221
00222 uint32 ph= alloc4k(1,false);
00223 if (ph==0) { complain("shmem_paging_pfh: cow: insufficient memory!"); return EFAIL; }
00224
00225 Memory::Pager::cpypage(ph,phys&0xfffff000);
00226 sh2->tree->pte_map(sh2->virtaddr+ofs-sh2->offset, ph|PTE_PRESENT|PTE_WRITEABLE|(sht->super?0:PTE_USER)|PTE_SHMEM);
00227 }
00228
00229 en->mtree->pte_map(virt&0xfffff000, phys|PTE_WRITEABLE);
00230 }
00231 } else
00232
00233 {
00234 if (phys&PTE_LAZY)
00235 {
00236 uint32 new_phys;
00237 struct blist_s *item;
00238 new_phys= alloc4k(1,false);
00239 if ((new_phys==NULL)||(new_phys==0xffffffff))
00240 { complain("shmem_paging_pfh: insufficient memory!"); return EFAIL; }
00241
00242 sht->pgs[ofs/PAGE_SIZE]=new_phys|PTE_PRESENT;
00243
00244 for (item=sht->li.head;item;item=item->next)
00245 {
00246 sh2= bli_dt(item,struct Memory::Shmem::shmem_s*);
00247 if ((sh2->offset <= ofs)&&(sh2->offset+sh2->lgth)>ofs)
00248 sh2->tree->pte_map(sh2->virtaddr+ofs-sh2->offset, new_phys|PTE_PRESENT|((sht->cows||shs->cow)?PTE_RO:PTE_WRITEABLE)|(sht->super?0:PTE_USER)|PTE_SHMEM);
00249 }
00250 } else
00251 {
00252 write_bochs("e");
00253 uint32 ph;
00254
00255 write_bochs("h");
00256
00257 ph= sht->pgs[ofs/PAGE_SIZE];
00258 ph&=0xfffff000;
00259 ph|=PTE_SHMEM|PTE_PRESENT|((sht->cows||shs->cow)?PTE_RO:PTE_WRITEABLE)|(sht->super?0:PTE_USER);
00260 write_bochs("i");
00261
00262
00263 write_bochs("j");
00264
00265 shs->tree->pte_map(virt&0xfffff000, ph);
00266 write_bochs("g");
00267 }
00268 }
00269
00270 return ESUCCESS;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279