Commit a9dc4a9d authored by 某某某's avatar 某某某
Browse files

feat: impl removeMapping;

feat: impl mappingtype and sharing type;
chore: PageMgr.alloc typo
Showing with 102 additions and 5 deletions
+102 -5
......@@ -14,7 +14,7 @@ namespace alloc
PageMgr(xlen_t start,xlen_t end);
~PageMgr();
xlen_t alloc(size_t pages);
xlen_t free(xlen_t pages,int order);
xlen_t free(PageNum ppn,int order);
inline void print(){
printf("buddy: |"); for(xlen_t i=0;i<buddyTreeSize;i++)printf("%d | ",buddyNodes[i]-1);printf("\n");
}
......
......@@ -3,6 +3,7 @@
#include "common.h"
#include "klib.hh"
#include "TINYSTL/vector.h"
#define moduleLevel LogLevel::debug
namespace vm
......@@ -49,6 +50,7 @@ namespace vm
};
inline bool isValid(){ return fields.v; }
inline void setValid(){ fields.v=1; }
inline void setInvalid(){ raw.perm=0; }
inline void setPTNode(){ fields.r=fields.w=fields.x=0; }
inline bool isLeaf(){ return fields.r|fields.w|fields.x; }
inline perm_t perm(){ return raw.perm; }
......@@ -98,28 +100,51 @@ namespace vm
inline PageNum pages() const{return pages_;}
inline PageNum ppn() const{return ppn_;}
inline klib::string toString() const{return klib::format("<VMO>@0x%lx[%lx]\n",ppn(),pages());}
static VMO alloc(PageNum pages,CloneType type=CloneType::clone);
static VMO alloc(PageNum pages,CloneType=CloneType::clone);
bool operator==(const VMO& other){return ppn_==other.ppn_&&pages_==other.pages_;}
private:
};
struct PageMapping{
enum Prot{
none=0x0,read=0x4,write=0x2,exec=0x1
};
enum class MappingType:uint8_t{
Normal,MMap,
normal=0x0,file=0x1,anon=0x2
};
enum class SharingType:uint8_t{
/// @brief changes aren't visible to others, copy on write
privt=0x0,
/// @brief not implemented
copy=0x1,
/// @brief changes are shared
shared=0x2
};
PageNum vpn;
VMO vmo;
const perm_t perm;
const MappingType type=MappingType::Normal;
const MappingType mapping=MappingType::normal;
const SharingType sharing=SharingType::privt;
inline PageNum ppn() const{return vmo.ppn();}
inline PageNum pages() const{return vmo.pages();}
inline klib::string toString() const{return klib::format("%lx=>%s",vpn,vmo.toString());}
inline PageMapping clone() const{return PageMapping{vpn,vmo.clone(),perm};}
inline static perm_t prot2perm(Prot prot){
perm_t rt=0;
using masks=PageTableEntry::fieldMasks;
if(prot&read)rt|=masks::r;
if(prot&write)rt|=masks::w;
if(prot&exec)rt|=masks::x;
return rt;
}
bool operator==(const PageMapping &other){return vpn==other.vpn&&vmo==other.vmo&&perm==other.perm&&mapping==other.mapping&&sharing==other.sharing;}
};
class PageTable{
private:
pgtbl_t root;
static pgtbl_t createPTNode();
static bool freePTNode(pgtbl_t);
public:
inline PageTable(pgtbl_t root=nullptr){
if(root==nullptr)this->root=createPTNode();
......@@ -143,6 +168,10 @@ namespace vm
inline void createMapping(const PageMapping &mapping){
createMapping(mapping.vpn,mapping.ppn(),mapping.pages(),mapping.perm);
}
void removeMapping(pgtbl_t table,PageNum vpn,xlen_t pages,int level=2);
inline void removeMapping(const PageMapping &mapping){
removeMapping(root,mapping.vpn,mapping.pages());
}
PageNum trans(PageNum vpn);
inline xlen_t transaddr(xlen_t addr){
return pn2addr(trans(addr2pn(addr)))+addr2offset(addr);
......@@ -177,6 +206,21 @@ namespace vm
}
inline void map(PageNum vpn,PageNum ppn,PageNum pages,perm_t perm,CloneType ct=CloneType::clone){map(PageMapping{vpn,VMO{ppn,pages,ct},perm});}
inline void unmap();
inline void reset(){
Log(debug,"before reset, VMAR:%s",mappings.toString().c_str());
tinystl::vector<PageMapping> toremove;
for(auto mapping:mappings){
if(mapping.mapping!=PageMapping::MappingType::normal){
Log(info,"unmap %s",mapping.toString().c_str());
toremove.push_back(mapping);
pagetable.removeMapping(mapping);
}
}
/// @todo better efficiency
for(auto &mapping:toremove)
mappings.remove(mapping);
Log(debug,"after reset, VMAR:%s",mappings.toString().c_str());
}
inline xlen_t satp(){return PageTable::toSATP(pagetable);}
// @todo @bug what if region is on border?
inline klib::ByteArray copyinstr(xlen_t addr, size_t len) {
......
......@@ -15,7 +15,7 @@ xlen_t ld::loadElf(const uint8_t *buff,vm::VMAR &vmar){
int pages=vm::bytes2pages(entry.p_memsz);
vm::PageNum ppn=(kGlobObjs.pageMgr->alloc(pages));
Log(debug,"%x<=%x[%d pages@%x]",vm::addr2pn(entry.p_vaddr),ppn,pages,ld::elf::flags2perm(entry.p_flags));
vmar.map(vm::addr2pn(entry.p_vaddr),ppn,pages,ld::elf::flags2perm(entry.p_flags));
vmar.map(vm::PageMapping{vm::addr2pn(entry.p_vaddr),vm::VMO{ppn,pages},ld::elf::flags2perm(entry.p_flags),vm::PageMapping::MappingType::file});
memcpy((ptr_t)vm::pn2addr(ppn),buff+entry.p_offset,entry.p_filesz);
}
return elfHeader->e_entry;
......
......@@ -85,6 +85,51 @@ void PageTable::createMapping(pgtbl_t table,PageNum vpn,PageNum ppn,xlen_t pages
createMapping(subTable,vpn,ppn,pages,perm,level-1);
}
}
void PageTable::removeMapping(pgtbl_t table,PageNum vpn,xlen_t pages,int level){
xlen_t bigPageSize=1l<<(9*level);
xlen_t unaligned=vpn&(bigPageSize-1);
Log(debug,"removeMapping(table,vpn=0x%lx,pages=0x%lx,level=%d)\n",vpn,pages,level);
Log(debug,"bigPageSize=%lx,unaligned=%lx\n",bigPageSize,unaligned);
// align vpn to boundary
if(unaligned){
auto partial=klib::min(bigPageSize-unaligned,pages);
PageTableEntry &entry=table[(vpn/bigPageSize)&vpnMask];
assert(entry.isValid() && !entry.isLeaf());
pgtbl_t subTable=entry.child();
DBG_ENTRY
Log(debug,"subtable=%lx\n",subTable);
removeMapping(subTable,vpn,partial,level-1); // actual create mapping
if(freePTNode(subTable))entry.setInvalid();
vpn+=partial,pages-=partial;
}
// unmap aligned whole pages
for(int i=(vpn/bigPageSize)&vpnMask;pages>=bigPageSize;i++){
PageTableEntry &entry=table[i];
assert(entry.isValid());
// big page entry
if(entry.isLeaf())entry.setInvalid();
else {
// pushed down
removeMapping(entry.child(),vpn,pages,level-1);
assert(freePTNode(entry.child()));
entry.setInvalid();
}
vpn+=bigPageSize;
pages-=bigPageSize;
}
// unmap rest pages
if(pages){
assert(pages>0);
PageTableEntry &entry=table[(vpn/bigPageSize)&vpnMask];
assert(entry.isValid() && !entry.isLeaf());
pgtbl_t subTable=entry.child();
DBG_ENTRY
Log(debug,"subtable=%lx\n",subTable);
removeMapping(subTable,vpn,pages,level-1); // actual create mapping
if(freePTNode(subTable))entry.setInvalid();
}
}
klib::string PageTable::toString(pgtbl_t table,xlen_t vpnBase,xlen_t entrySize){
assert(entrySize>0);
klib::string s;
......@@ -107,6 +152,14 @@ pgtbl_t PageTable::createPTNode(){
Log(debug,"createPTNode=0x%lx",rt);
return rt;
}
bool PageTable::freePTNode(pgtbl_t table){
for(int i=0;i<pageEntriesPerPage;i++){
auto &entry=table[i];
if(entry.isValid())return false;
}
kGlobObjs.pageMgr->free(addr2pn((xlen_t)table),0);
return true;
}
xlen_t PageTable::toSATP(PageTable &table){
csr::satp satp;
satp.mode=8;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment