| /* Copyright (c) 2009, 2010 The Regents of the University of California. |
| * See the COPYRIGHT files at the top of this source tree for full |
| * license information. |
| * |
| * Kevin Klues <klueska@cs.berkeley.edu> |
| * Barret Rhoden <brho@cs.berkeley.edu> */ |
| |
| #pragma once |
| |
| #include <atomic.h> |
| #include <sys/queue.h> |
| #include <error.h> |
| #include <arch/mmu.h> |
| #include <process.h> |
| #include <kref.h> |
| #include <kthread.h> |
| #include <multiboot.h> |
| |
| struct page_map; /* preprocessor games */ |
| |
| /****************** Page Structures *********************/ |
| struct page; |
| typedef size_t ppn_t; |
| typedef struct page page_t; |
| typedef BSD_LIST_HEAD(PageList, page) page_list_t; |
| typedef BSD_LIST_ENTRY(page) page_list_entry_t; |
| |
| /* Per-page flag bits related to their state in the page cache */ |
| #define PG_LOCKED 0x001 /* involved in an IO op */ |
| #define PG_UPTODATE 0x002 /* page map, filled with file data */ |
| #define PG_DIRTY 0x004 /* page map, data is dirty */ |
| #define PG_BUFFER 0x008 /* is a buffer page, has BHs */ |
| #define PG_PAGEMAP 0x010 /* belongs to a page map */ |
| #define PG_REMOVAL 0x020 /* Working flag for page map removal */ |
| |
| /* TODO: this struct is not protected from concurrent operations in some |
| * functions. If you want to lock on it, use the spinlock in the semaphore. |
| * This structure is getting pretty big (and we're wasting RAM). If it becomes |
| * an issue, we can dynamically allocate some of these things when we're a |
| * buffer page (in a page mapping) */ |
| struct page { |
| BSD_LIST_ENTRY(page) pg_link; |
| atomic_t pg_flags; |
| struct page_map *pg_mapping; /* for debugging... */ |
| unsigned long pg_index; |
| void **pg_tree_slot; |
| void *pg_private; |
| struct semaphore pg_sem; |
| uint64_t gpa; /* physical address in guest */ |
| |
| bool pg_is_free; /* TODO: will remove */ |
| }; |
| |
| /******** Externally visible global variables ************/ |
| extern spinlock_t page_list_lock; |
| extern page_list_t page_free_list; |
| |
| /*************** Functional Interface *******************/ |
| void base_arena_init(struct multiboot_info *mbi); |
| |
| error_t upage_alloc(struct proc *p, page_t **page, bool zero); |
| error_t kpage_alloc(page_t **page); |
| void *kpage_alloc_addr(void); |
| void *kpage_zalloc_addr(void); |
| |
| /* Direct allocation from the kpages arena (instead of kmalloc). These will |
| * give you PGSIZE quantum. */ |
| void *kpages_alloc(size_t size, int flags); |
| void *kpages_zalloc(size_t size, int flags); |
| void kpages_free(void *addr, size_t size); |
| |
| void *get_cont_pages(size_t order, int flags); |
| void free_cont_pages(void *buf, size_t order); |
| |
| void page_decref(page_t *page); |
| |
| int page_is_free(size_t ppn); |
| void lock_page(struct page *page); |
| void unlock_page(struct page *page); |
| void print_pageinfo(struct page *page); |
| static inline bool page_is_pagemap(struct page *page); |
| |
| static inline bool page_is_pagemap(struct page *page) |
| { |
| return atomic_read(&page->pg_flags) & PG_PAGEMAP ? true : false; |
| } |