All pastes #1508993 Raw Edit

richard

public text v1 · immutable
#1508993 ·published 2009-07-27 15:52 UTC
rendered paste body
class PhysMem {	u32 get_page();	void free_page();};class AddressSpace {	void map(u32 phys,u32 virt);	u32 unmap(u32 virt);	void destroy();	void clone();	directory_entry& get_dir_entry(u32 index);	table_entry* get_page_table(u32 virt);	u32 virt_to_phys(u32 virt);};u32 AddressSpace::virt_to_phys(u32 virt) {	u32 pte = (virt>>12) & 0x3ff;	return get_page_table(virt)[pte].frame<<12;}PhysMem physmem;static table_entry** page_tables(0xffc00000);// 1111 1111 1100 0000 0000 | 0000 0000 0000static directory_entry* current_page_dir=0xFFFFF000;static directory_entry* other_page_dir=0xFFFFF000;static table_entry* other_page_tables=0xFF800000;static int kernel_start_directory_entry=768;void copy_page_table(int pt) {	table_entry* other=other_page_tables+(pt<<10);	table_entry* current=page_tables+(pt<<10);	for(int i=0;i<1024;++i) {		other[i].zero();		if(current[i].present) {			u32 newp=get_page();			other[i]=current[i];			other[i].frame=newp>>12;			copy_4k_page(current[i].frame<<12,newp);		}	}}u32 AddressSpace::clone() {	u32 npd=get_page();	current_page_dir[1022].set(npd,0,1);	for(int i=0;i<1022;++i) {		if(current_page_dir[i].present) {			u32 npt=get_page();			other_page_dir[i]=current_page_dir[i];			other_page_dir[i].frame=npt>>12;			copy_page_table(i);		} else {			other_page_dir[i].zero();		}	}	other_page_dir[1023].set(npd,0,1);}// gets the page directory entry associated with the virtual address addr.directory_entry& AddressSpace::get_dir_entry(u32 virt) {	return current_page_dir[virt>>22];}table_entry* AddressSpace::get_page_table(u32 virt) {	u32 offset = virt&0xfff;	u32 pde = virt>>22;	u32 pte = (virt>>12) & 0x3ff;	return page_tables+(pde<<12);}// make sure there's a page table at the relevant address.void ensure_page_table(u32 virt) {	directory_entry& entry=get_dir_entry(virt);	if(!entry.present) {		u32 pt=physmem.get_page();		entry.set_base_address(pt);		table_entry*t=get_page_table(virt);		memset(t,0,4096);	}}// map phys at virt with the relevant protections.void AddressSpace::map(u32 phys,u32 virt,bool user,bool writable) {	directory_entry& entry=get_dir_entry(virt);	ensure_page_table(virt);	table_entry*pt=get_page_table(virt);	pt[virt&0xfff].set(phys,user,writable);}u32 AddressSpace::unmap(u32 virt) {	table_entry*pt = get_page_table(virt)+(virt&0xfff);	u32 frame = pt->frame;	pt->present=0;	return frame>>12;}struct table_entry{	void zero() {		memset(this,0,sizeof(*this));	}	void set(u32 frame,bool user,bool writable) {		Page p;		p.zero();		p.preset=1;		p.rw=writable?1:0;		p.user=user?1:0;		p.frame=frame>>12;		*this = p; // we want to set this atomically.	}   u32 present    : 1;   // Page present in memory   u32 rw         : 1;   // Read-only if clear, readwrite if set   u32 user       : 1;   // Supervisor level only if clear   u32 accessed   : 1;   // Has the page been accessed since last refresh?   u32 dirty      : 1;   // Has the page been written to since last refresh?   u32 unused     : 7;   // Amalgamation of unused and reserved bits   u32 frame      : 20;  // Frame address (shifted right 12 bits)};typedef struct directory_entry {	bool is_present() { return present; }	u32 present:1;	// whether it is in memory.	u32 readwrite:1;	// 1 if it's writable.	u32 user:1;		// 1 if it's a user page, 0 for supervisor.	u32 write_through:1;	// don't bother	u32 cache_disabled:1;	// don't bother	u32 accessed:1;		// whether the 4mb block has been accessed since clearing this flag.	u32 dirty:1;	// whether it's been written to.	u32 superpage:1;	// 1 for 4mb, 2 otherwise.	u32 global:1;	u32 available:3;	// must think of something to put here (reference count?)	u32 PAT :1;			// always 0 atm.	u32 reserved:9;		// always 0 atm.	u32 frame:10;		// top 10 bit of address in physical ram.	/**	 * Gets where this points in physical ram */	u32 get_base_address() const {		return frame<<22;	}	/** Sets where this points in physical ram */	void set_base_address(u32 addr) {		frame=addr>>22;	}	void clear() {		memset(this,0,sizeof(directory_entry));	}	void set(u32 frame,bool user,bool writable) {		directory_entry d;		d.clear();		d.frame=frame>>22;		d.present=1;		d.writable=writable?1:0;		d.user=user?1:0;		*this=d;	}};