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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// IBM_PROLOG_BEGIN_TAG
// This is an automatically generated prolog.
//
// $Source: src/include/kernel/segmentmgr.H $
//
// IBM CONFIDENTIAL
//
// COPYRIGHT International Business Machines Corp. 2011
//
// p1
//
// Object Code Only (OCO) source materials
// Licensed Internal Code Source Materials
// IBM HostBoot Licensed Internal Code
//
// The source code for this program is not published or other-
// wise divested of its trade secrets, irrespective of what has
// been deposited with the U.S. Copyright Office.
//
// Origin: 30
//
// IBM_PROLOG_END
/** @file segmentmgr.H
* Provides definition of the SegmentManager class.
*/
#ifndef __KERNEL_SEGMENTMGR_H
#define __KERNEL_SEGMENTMGR_H
#include <kernel/task.H>
#include <builtins.h>
#include <kernel/ptmgr.H>
#include <usr/vmmconst.h>
// Forward declaration.
class Segment;
/** @class SegmentManager
* @brief Container of Segments. Responsible for managing the SLB.
*
* @note This class is not thread-safe on its own. Expectation is that
* the virtual memory manager will serialize internal operations.
*/
class SegmentManager
{
public:
/** Segment Identifiers */
enum SegmentIds
{
/** Base Segment (0-1TB). */
BASE_SEGMENT_ID = 0,
/** Task Stack Segment (1-2TB). */
STACK_SEGMENT_ID = 1,
/** MMIO Space Segments (2-11TB). */
MMIO_FIRST_SEGMENT_ID = 2,
MMIO_LAST_SEGMENT_ID = MMIO_FIRST_SEGMENT_ID + 8,
MAX_SEGMENTS = 16
};
enum
{
CI_ACCESS = 0xFFFFFFFF
// Set to all F's to identify this type
};
/**
* Constructor. Initializes instance variables.
*/
SegmentManager()
{
for(int i = 0; i < MAX_SEGMENTS; i++)
iv_segments[i] = NULL;
};
/**
* Destructor.
* No action necessary. Associated segments are owned externally,
* such as in Singletons.
*/
~SegmentManager() {};
/**
* @brief Responsible for directing page faults to the owning segment.
*
* @param[in] i_task - Task causing the page fault.
* @param[in] i_addr - Effective address accessed to cause fault.
* @param[in] i_store - The page fault was due to a store.
*
* @return true - Page fault was successfully handled.
*
* If the page fault is not successfully handled the expectation is
* that the VMM will perform appropriate action, such as killing the
* task.
*/
static bool handlePageFault(task_t* i_task, uint64_t i_addr,
bool i_store);
/**
* @brief Adds a segment to the container.
*
* @param[in] i_segment - Segment object to associate to segment.
* @param[in] i_segId - Segment identifier (which TB) to associate.
*
* @note Ownership of the Segment object (for freeing memory) remains
* with the callee.
*/
static void addSegment(Segment* i_segment, size_t i_segId);
/**
* @brief Update SLB on this hardware thread with associated segments.
*/
static void initSLB();
/**
* @brief Find the phyiscal address bound to the given address
* @param[in] i_vaddr The address
* @return the physical address or -EFAULT @see errno.h
*/
static uint64_t findPhysicalAddress(uint64_t i_vaddr);
/**
* @brief Update LRU statistics on the block that owns the page
*
* @param[in] i_vaddr - Virtual Address of page
* @param[in] i_stats - Usage statistics
*/
static void updateRefCount( uint64_t i_vaddr,
PageTableManager::UsageStats_t i_stats );
/**
* @brief Cast out oldest physical memory pages
* @param[in] castout type
*/
static void castOutPages(uint64_t i_type);
/**
* @brief Map a device into the device segment
* @param ra[in] - Void pointer to real address to be mapped in
* @param i_devDataSize[in] - Size of device segment block
* @return void* - Pointer to beginning virtual address, NULL otherwise
*/
static void* devMap(void* ra, uint64_t i_devDataSize);
/**
* @brief Unmap a device from the device segment
* @param ea[in] - Void pointer to effective address
* @return int - 0 for successful unmap, non-zero otherwise
*/
static int devUnmap(void* ea);
private:
/** See handlePageFault. */
bool _handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store);
/** See addSegment. */
void _addSegment(Segment* i_segment, size_t i_segId);
/** See getSegment. */
Segment* _getSegment(size_t i_segId);
/** See initSLB. */
void _initSLB();
/** See updateRefCount. */
void _updateRefCount( uint64_t i_vaddr,
PageTableManager::UsageStats_t i_stats );
/** See castOutPages */
void _castOutPages(uint64_t i_type);
/** See devMap */
void* _devMap(void* ra, uint64_t i_devDataSize);
/** See devUnmap */
int _devUnmap(void* ea);
/** See findPhysicalAddress */
uint64_t _findPhysicalAddress(uint64_t i_vaddr) const;
ALWAYS_INLINE
static size_t getSegmentIdFromAddress(uint64_t i_addr)
{
return i_addr >> SLBE_s;
}
/** Array of segment objects to associated segment IDs. */
Segment* iv_segments[MAX_SEGMENTS];
};
#endif
|