3030
3131size_t total_phys_memory ;
3232
33+ static list_head_t frames ;
34+ static unsigned long total_free_frames = 0 ;
35+ #define MIN_FREE_FRAMES_THRESHOLD 2
36+ #define MAX_FREE_FRAMES_THRESHOLD (2 * ARRAY_SIZE(memberof(frames_array_t, frames)))
37+ static frames_array_t early_frames ;
38+
3339static list_head_t free_frames [MAX_PAGE_ORDER + 1 ];
3440static list_head_t busy_frames [MAX_PAGE_ORDER + 1 ];
3541
36- static frame_t early_frames [2 * PAGE_SIZE ];
37- static unsigned int free_frame_idx ;
38-
3942static size_t frames_count [MAX_PAGE_ORDER + 1 ];
4043
4144static spinlock_t lock = SPINLOCK_INIT ;
@@ -51,15 +54,159 @@ void display_frames_count(void) {
5154 }
5255}
5356
54- static inline frame_t * new_frame (mfn_t mfn , unsigned int order ) {
55- frame_t * frame = & early_frames [free_frame_idx ++ ];
57+ static inline void init_frame (frame_t * frame ) {
58+ ASSERT (frame );
59+
60+ memset (frame , 0 , sizeof (* frame ));
61+ frame -> order = PAGE_ORDER_INVALID ;
62+ frame -> flags .free = true;
63+ }
64+
65+ static inline void init_frames_array (frames_array_t * array ) {
66+ memset (array , 0 , sizeof (* array ));
67+ array -> meta .free_count = ARRAY_SIZE (array -> frames );
68+ for (unsigned i = 0 ; i < ARRAY_SIZE (array -> frames ); i ++ )
69+ init_frame (& array -> frames [i ]);
70+ list_add (& array -> list , & frames );
71+ }
72+
73+ static frames_array_t * new_frames_array (void ) {
74+ frame_t * frame = get_free_frame ();
75+ frames_array_t * array ;
76+
77+ if (!frame )
78+ panic ("PMM: Unable to allocate new frame for frame array\n" );
79+
80+ array = (frames_array_t * ) mfn_to_virt_kern (frame -> mfn );
81+ init_frames_array (array );
82+
83+ dprintk ("%s: allocated new frames array: %p\n" , __func__ , array );
84+
85+ total_free_frames += array -> meta .free_count ;
86+ return array ;
87+ }
88+
89+ static void del_frames_array (frames_array_t * array ) {
90+ ASSERT (array );
91+
92+ list_unlink (& array -> list );
93+ total_free_frames -= array -> meta .free_count ;
94+ put_free_frame (virt_to_mfn (array ));
95+
96+ dprintk ("%s: freed frames array: %p\n" , __func__ , array );
97+ }
98+
99+ static bool is_frames_array_free (const frames_array_t * array ) {
100+ ASSERT (array );
101+
102+ if (array -> meta .free_count < ARRAY_SIZE (array -> frames ))
103+ return false;
104+ else if (array -> meta .free_count > ARRAY_SIZE (array -> frames ))
105+ panic ("PMM: incorrect number of free slots: %d in array: %p\n" ,
106+ array -> meta .free_count , array );
107+
108+ for (unsigned i = 0 ; i < ARRAY_SIZE (array -> frames ); i ++ ) {
109+ const frame_t * frame = & array -> frames [i ];
110+
111+ if (!is_frame_free (frame ))
112+ panic ("PMM: found occupied slot in an empty array: %p\n" , array );
113+ }
114+
115+ return true;
116+ }
117+
118+ static inline frames_array_t * get_frames_array (void ) {
119+ frames_array_t * array ;
120+
121+ list_for_each_entry (array , & frames , list ) {
122+ if (array -> meta .free_count > 0 )
123+ return array ;
124+ }
125+
126+ return new_frames_array ();
127+ }
128+
129+ static inline bool put_frames_array (frames_array_t * array ) {
130+ if (is_frames_array_free (array )) {
131+ del_frames_array (array );
132+ return true;
133+ }
134+
135+ return false;
136+ }
56137
57- if (free_frame_idx > ARRAY_SIZE (early_frames ))
58- panic ("Not enough initial frames for PMM allocation!\n" );
138+ static inline frames_array_t * find_frames_array (const frame_t * frame ) {
139+ frames_array_t * array ;
140+ mfn_t frame_mfn = virt_to_mfn (frame );
141+
142+ list_for_each_entry (array , & frames , list ) {
143+ if (virt_to_mfn (array ) == frame_mfn )
144+ return array ;
145+ }
146+
147+ return NULL ;
148+ }
149+
150+ static inline frame_t * take_frame (frame_t * frame , frames_array_t * array ) {
151+ ASSERT (frame );
152+
153+ if (!array )
154+ array = find_frames_array (frame );
155+ BUG_ON (!array );
156+
157+ frame -> flags .free = false;
158+ array -> meta .free_count -- ;
159+
160+ if (-- total_free_frames <= MIN_FREE_FRAMES_THRESHOLD )
161+ new_frames_array ();
162+
163+ return frame ;
164+ }
165+
166+ static inline frame_t * put_frame (frame_t * frame , frames_array_t * array ) {
167+ ASSERT (!frame );
168+
169+ if (!array )
170+ array = find_frames_array (frame );
171+ BUG_ON (!array );
172+
173+ array -> meta .free_count ++ ;
174+
175+ if (++ total_free_frames >= MAX_FREE_FRAMES_THRESHOLD )
176+ put_frames_array (array );
177+
178+ init_frame (frame );
179+ return frame ;
180+ }
181+
182+ static inline frame_t * get_frames_array_entry (void ) {
183+ frames_array_t * array = get_frames_array ();
184+
185+ if (!array )
186+ panic ("PMM: Unable to get a free array of frames' metadata\n" );
187+
188+ for (unsigned i = 0 ; i < ARRAY_SIZE (array -> frames ); i ++ ) {
189+ frame_t * frame = & array -> frames [i ];
190+
191+ if (is_frame_free (frame ))
192+ return take_frame (frame , array );
193+ }
194+
195+ return NULL ;
196+ }
197+
198+ static inline void put_frames_array_entry (frame_t * frame ) {
199+ if (is_frame_free (frame ))
200+ return ;
201+
202+ put_frame (frame , NULL );
203+ }
204+
205+ static inline frame_t * new_frame (mfn_t mfn , unsigned int order ) {
206+ frame_t * frame = get_frames_array_entry ();
59207
60208 frame -> order = order ;
61209 frame -> mfn = mfn ;
62- frame -> flags .free = true;
63210
64211 frames_count [order ]++ ;
65212 return frame ;
@@ -158,7 +305,11 @@ void reclaim_frame(mfn_t mfn, unsigned int order) { add_frame(mfn, order); }
158305void init_pmm (void ) {
159306 printk ("Initialize Physical Memory Manager\n" );
160307
161- BUG_ON (ARRAY_SIZE (free_frames ) != ARRAY_SIZE (busy_frames ));
308+ BUILD_BUG_ON (sizeof (frames_array_t ) > PAGE_SIZE );
309+ list_init (& frames );
310+ init_frames_array (& early_frames );
311+
312+ BUILD_BUG_ON (ARRAY_SIZE (free_frames ) != ARRAY_SIZE (busy_frames ));
162313 for_each_order (order ) {
163314 list_init (& free_frames [order ]);
164315 list_init (& busy_frames [order ]);
0 commit comments