summaryrefslogtreecommitdiffstats
path: root/src/include/kernel/vmmmgr.H
blob: 18d1f08622c91058c96760e7501a62f9fb5431eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#ifndef __KERNEL_VMMMGR_H
#define __KERNEL_VMMMGR_H

#include <kernel/types.h>

class VmmManager
{
    public:
	struct pte_t
	{
	    uint64_t a,b;
	};

	enum VMM_CONSTS
	{
	    FULL_MEM_SIZE = 8 * 1024 * 1024,
	    PAGESIZE = 4096,

	    PTSIZE = (1 << 18),
	    PTEG_SIZE = 8,
	    PTEG_COUNT = (PTSIZE / sizeof(pte_t)) / PTEG_SIZE,

	    HTABORG = (FULL_MEM_SIZE - PTSIZE),
	};

	enum ACCESS_TYPES
	{
	    NO_USER_ACCESS,
	    NORMAL_ACCESS,
	    CI_ACCESS,
	};

	enum PID_ALLOCATIONS
	{
	    LinearSpace = 0,
	    MMIOSpace = 1,
	    FirstPid,
	};

	static void init();

    protected:
	VmmManager();
	~VmmManager() {};
    
    private:
	void initSLB();
	void initPTEs();	
	void initSDR1();

	static pte_t* page_table;

	inline pte_t& getPte(uint64_t pteg, uint64_t idx)
	{
	    return page_table[pteg * PTEG_SIZE + idx];
	}
	
	inline void defaultPte(pte_t& pte)
	{
	    pte.a = 0x4000000000000000; // B = 01 (1TB).
	    pte.b = 0x0;
	}

	inline void setValid(bool valid, pte_t& pte)
	{
	    // Adding a page requires EIEIO to ensure update of PTE prior
	    // to making valid and PTESYNC afterwards.  
	    // Removing a page just requires PTESYNC afterwards.
	    if (valid)
	    {
		asm volatile("eieio" ::: "memory");
	    }
	    
	    pte.a &= ~0x01;
	    pte.a |= (valid ? 0x1 : 0x0);
	    
	    asm volatile("ptesync" ::: "memory");
	}

	inline bool isValid(pte_t& pte)
	{
	    return ((pte.a & 0x01) == 0x01);
	}

	inline void setTid(tid_t tid, pte_t& pte)
	{
	    pte.a &= 0xC00000000000007F;
	    pte.a |= ((uint64_t) tid) << 7;
	}

	inline tid_t getTid(pte_t& pte)
	{
	    return (tid_t) ((pte.a & 0xC00000000000007F) >> 7);
	}

	inline void setAccess(ACCESS_TYPES t, pte_t& pte)
	{
	    uint64_t pteMask = ~0x800000000000007B;
	    pte.b &= pteMask;
	    pte.b |= (NO_USER_ACCESS == t ? 0x0000000000000010 :
		     (NORMAL_ACCESS == t ?  0x0000000000000012 :
		     (CI_ACCESS == t ?      0x000000000000002A :
		      0x0)));
	}

	inline void setPage(uint64_t page, pte_t& pte)
	{
	    pte.b &= ~0x0FFFFFFFFFFFF000;
	    pte.b |= page << 12;
	}

	inline uint64_t getPage(pte_t& pte)
	{
	    return (pte.b & 0x0FFFFFFFFFFFF000) >> 12;
	}

	inline void pteSync()
	{
	    asm volatile("ptesync" ::: "memory");
	}

};

#endif
OpenPOWER on IntegriCloud