git://scm.lunaixsky.com
/
lunaix-os.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
A Total Overhaul on the Lunaix's Virtual Memory Model (#26)
[lunaix-os.git]
/
lunaix-os
/
kernel
/
mm
/
pmm.c
diff --git
a/lunaix-os/kernel/mm/pmm.c
b/lunaix-os/kernel/mm/pmm.c
index efb9dc8d36c67f169bec85ff80ff4b5ac1e035f2..72b57d750cbf0b39ee54f734d202673e1cd254c6 100644
(file)
--- a/
lunaix-os/kernel/mm/pmm.c
+++ b/
lunaix-os/kernel/mm/pmm.c
@@
-1,110
+1,107
@@
-#include <lunaix/mm/page.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/status.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/status.h>
+#include <lunaix/mm/pagetable.h>
+#include <lunaix/spike.h>
// This is a very large array...
static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
// This is a very large array...
static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
+export_symbol(debug, pmm, pm_table);
-static uintptr_t max_pg;
+static ptr_t max_pg;
+export_symbol(debug, pmm, max_pg);
void
void
-pmm_mark_page_free(
uint
ptr_t ppn)
+pmm_mark_page_free(ptr_t ppn)
{
{
+ if ((pm_table[ppn].attr & PP_FGLOCKED)) {
+ return;
+ }
pm_table[ppn].ref_counts = 0;
}
void
pm_table[ppn].ref_counts = 0;
}
void
-pmm_mark_page_occupied(p
id_t owner, uintp
tr_t ppn, pp_attr_t attr)
+pmm_mark_page_occupied(ptr_t ppn, pp_attr_t attr)
{
{
- pm_table[ppn] = (struct pp_struct) {
- .owner = owner,
- .ref_counts = 1,
- .attr = attr
- };
+ pm_table[ppn] =
+ (struct pp_struct){ .ref_counts = 1, .attr = attr };
}
void
}
void
-pmm_mark_chunk_free(
uint
ptr_t start_ppn, size_t page_count)
+pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count)
{
{
- for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
- {
+ for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
+ if ((pm_table[i].attr & PP_FGLOCKED)) {
+ continue;
+ }
pm_table[i].ref_counts = 0;
}
}
void
pm_table[i].ref_counts = 0;
}
}
void
-pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr)
+pmm_mark_chunk_occupied(u32_t start_ppn,
+ size_t page_count,
+ pp_attr_t attr)
{
{
- for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
- {
- pm_table[i] = (struct pp_struct) {
- .owner = owner,
- .ref_counts = 1,
- .attr = attr
- };
+ for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
+ pm_table[i] =
+ (struct pp_struct){ .ref_counts = 1, .attr = attr };
}
}
// 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
#define LOOKUP_START 1
}
}
// 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
#define LOOKUP_START 1
-size_t pg_lookup_ptr;
+
volatile
size_t pg_lookup_ptr;
void
void
-pmm_init(
uint
ptr_t mem_upper_lim)
+pmm_init(ptr_t mem_upper_lim)
{
{
- max_pg =
(PG_ALIGN(mem_upper_lim) >> 12
);
+ max_pg =
pfn(mem_upper_lim
);
pg_lookup_ptr = LOOKUP_START;
// mark all as occupied
for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
pg_lookup_ptr = LOOKUP_START;
// mark all as occupied
for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
- pm_table[i] = (struct pp_struct) {
- .owner = 0,
- .attr = 0,
- .ref_counts = 1
- };
+ pm_table[i] =
+ (struct pp_struct){ .attr = 0, .ref_counts = 1 };
}
}
}
}
-void*
-pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) {
+ptr_t
+pmm_alloc_cpage(size_t num_pages, pp_attr_t attr)
+{
size_t p1 = 0;
size_t p2 = 0;
size_t p1 = 0;
size_t p2 = 0;
- while (p2 < max_pg && p2 - p1 < num_pages)
- {
- (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2);
+ while (p2 < max_pg && p2 - p1 < num_pages) {
+ (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = ++p2);
}
}
- if (p2
< max_pg
) {
- return NULL;
+ if (p2
== max_pg && p2 - p1 < num_pages
) {
+ return NULL
PTR
;
}
}
- pmm_mark_chunk_occupied(
owner,
p1, num_pages, attr);
+ pmm_mark_chunk_occupied(p1, num_pages, attr);
return p1 << 12;
}
return p1 << 12;
}
-void*
-pmm_alloc_page(p
id_t owner, p
p_attr_t attr)
+ptr_t
+pmm_alloc_page(pp_attr_t attr)
{
// Next fit approach. Maximize the throughput!
{
// Next fit approach. Maximize the throughput!
-
uintptr_t good_page_found = (uint
ptr_t)NULL;
+
ptr_t good_page_found = (
ptr_t)NULL;
size_t old_pg_ptr = pg_lookup_ptr;
size_t upper_lim = max_pg;
struct pp_struct* pm;
while (!good_page_found && pg_lookup_ptr < upper_lim) {
pm = &pm_table[pg_lookup_ptr];
size_t old_pg_ptr = pg_lookup_ptr;
size_t upper_lim = max_pg;
struct pp_struct* pm;
while (!good_page_found && pg_lookup_ptr < upper_lim) {
pm = &pm_table[pg_lookup_ptr];
- // skip the fully occupied chunk, reduce # of iterations
if (!pm->ref_counts) {
if (!pm->ref_counts) {
- *pm = (struct pp_struct) {
- .attr = attr,
- .owner = owner,
- .ref_counts = 1
- };
+ *pm = (struct pp_struct){ .attr = attr,
+ .ref_counts = 1 };
good_page_found = pg_lookup_ptr << 12;
good_page_found = pg_lookup_ptr << 12;
+ break;
} else {
pg_lookup_ptr++;
} else {
pg_lookup_ptr++;
@@
-118,51
+115,55
@@
pmm_alloc_page(pid_t owner, pp_attr_t attr)
}
}
}
}
}
}
- if (!good_page_found) {
- __current->k_status = LXOUTOFMEM;
- }
- return (void*)good_page_found;
+ return good_page_found;
}
int
}
int
-pmm_free_
page(pid_t owner, void* page
)
+pmm_free_
one(ptr_t page, pp_attr_t attr_mask
)
{
{
- struct pp_struct* pm = &pm_table[(intptr_t)page >> 12];
-
- // Oops, double free!
- if (!(pm->ref_counts)) {
+ pfn_t ppfn = pfn(page);
+ struct pp_struct* pm = &pm_table[ppfn];
+
+ assert(ppfn < max_pg && pm->ref_counts);
+ if (pm->attr && !(pm->attr & attr_mask)) {
return 0;
}
return 0;
}
- // 检查权限,保证:1) 用户只能释放用户页; 2) 内核可释放所有页。
- if ((pm->owner & owner) == pm->owner) {
- pm->ref_counts--;
- return 1;
- }
- return 0;
+ pm->ref_counts--;
+ return 1;
}
}
-int
pmm_ref_page(pid_t owner, void* page) {
- (void*) owner; // TODO: do smth with owner
-
- u
int32_t ppn = (uintptr_t)page >> 12
;
-
+int
+pmm_ref_page(ptr_t page)
+{
+ u
32_t ppn = pfn(page)
;
+
if (ppn >= PM_BMP_MAX_SIZE) {
return 0;
}
struct pp_struct* pm = &pm_table[ppn];
if (ppn >= PM_BMP_MAX_SIZE) {
return 0;
}
struct pp_struct* pm = &pm_table[ppn];
- if (!pm->ref_counts) {
- return 0;
- }
+ assert(ppn < max_pg && pm->ref_counts);
pm->ref_counts++;
return 1;
}
pm->ref_counts++;
return 1;
}
-struct pp_struct* pmm_query(void* pa) {
- uint32_t ppn = (uintptr_t)pa >> 12;
+void
+pmm_set_attr(ptr_t page, pp_attr_t attr)
+{
+ struct pp_struct* pp = &pm_table[pfn(page)];
+ if (pp->ref_counts) {
+ pp->attr = attr;
+ }
+}
+
+struct pp_struct*
+pmm_query(ptr_t pa)
+{
+ u32_t ppn = pa >> 12;
+
if (ppn >= PM_BMP_MAX_SIZE) {
return NULL;
}
if (ppn >= PM_BMP_MAX_SIZE) {
return NULL;
}