|  | /* 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> */ | 
|  |  | 
|  | #ifndef PAGE_ALLOC_H | 
|  | #define PAGE_ALLOC_H | 
|  |  | 
|  | #include <atomic.h> | 
|  | #include <sys/queue.h> | 
|  | #include <error.h> | 
|  | #include <arch/mmu.h> | 
|  | #include <colored_page_alloc.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 LIST_HEAD(PageList, page) page_list_t; | 
|  | typedef 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 { | 
|  | LIST_ENTRY(page)			pg_link;	/* membership in various lists */ | 
|  | struct kref					pg_kref; | 
|  | atomic_t					pg_flags; | 
|  | struct page_map				*pg_mapping; /* for debugging... */ | 
|  | unsigned long				pg_index; | 
|  | void						**pg_tree_slot; | 
|  | void						*pg_private;	/* type depends on page usage */ | 
|  | struct semaphore 			pg_sem;		/* for blocking on IO */ | 
|  | uint64_t				gpa;		/* physical address in guest */ | 
|  | /* pg_private is overloaded. */ | 
|  | }; | 
|  |  | 
|  | /******** Externally visible global variables ************/ | 
|  | extern uint8_t* global_cache_colors_map; | 
|  | extern spinlock_t colored_page_free_list_lock; | 
|  | extern page_list_t LCKD(&colored_page_free_list_lock) * RO CT(llc_num_colors) | 
|  | colored_page_free_list; | 
|  |  | 
|  | /*************** Functional Interface *******************/ | 
|  | void page_alloc_init(struct multiboot_info *mbi); | 
|  | void colored_page_alloc_init(void); | 
|  |  | 
|  | error_t upage_alloc(struct proc* p, page_t *SAFE *page, int zero); | 
|  | error_t kpage_alloc(page_t *SAFE *page); | 
|  | void *kpage_alloc_addr(void); | 
|  | void *kpage_zalloc_addr(void); | 
|  | error_t upage_alloc_specific(struct proc* p, page_t *SAFE *page, size_t ppn); | 
|  | error_t kpage_alloc_specific(page_t *SAFE *page, size_t ppn); | 
|  |  | 
|  | void *CT(1 << order) get_cont_pages(size_t order, int flags); | 
|  | void *CT(1 << order) get_cont_pages_node(int node, size_t order, int flags); | 
|  | void *get_cont_phys_pages_at(size_t order, physaddr_t at, int flags); | 
|  | void free_cont_pages(void *buf, size_t order); | 
|  |  | 
|  | void page_incref(page_t *SAFE page); | 
|  | void page_decref(page_t *SAFE page); | 
|  | void page_setref(page_t *SAFE page, size_t val); | 
|  |  | 
|  | 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); | 
|  |  | 
|  | #endif //PAGE_ALLOC_H | 
|  |  |