1 /*
2  * Copyright (c) 2015 Google, Inc. All rights reserved
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <lib/page_alloc.h>
10 
11 #include <lk/debug.h>
12 #include <assert.h>
13 #include <string.h>
14 #include <lk/trace.h>
15 #include <lk/console_cmd.h>
16 #if WITH_KERNEL_VM
17 #include <kernel/vm.h>
18 #else
19 #include <kernel/novm.h>
20 #endif
21 
22 /* A simple page-aligned wrapper around the pmm or novm implementation of
23  * the underlying physical page allocator. Used by system heaps or any
24  * other user that wants pages of memory but doesn't want to use LK
25  * specific apis.
26  */
27 #define LOCAL_TRACE 0
28 
29 #if WITH_STATIC_HEAP
30 
31 #error "fix static heap post page allocator and novm stuff"
32 
33 #if !defined(HEAP_START) || !defined(HEAP_LEN)
34 #error WITH_STATIC_HEAP set but no HEAP_START or HEAP_LEN defined
35 #endif
36 
37 #endif
38 
page_alloc(size_t pages,int arena)39 void *page_alloc(size_t pages, int arena) {
40 #if WITH_KERNEL_VM
41     void *result = pmm_alloc_kpages(pages, NULL);
42     return result;
43 #else
44     void *result = novm_alloc_pages(pages, arena);
45     return result;
46 #endif
47 }
48 
page_free(void * ptr,size_t pages)49 void page_free(void *ptr, size_t pages) {
50 #if WITH_KERNEL_VM
51     DEBUG_ASSERT(IS_PAGE_ALIGNED((uintptr_t)ptr));
52 
53     pmm_free_kpages(ptr, pages);
54 #else
55     novm_free_pages(ptr, pages);
56 #endif
57 }
58 
page_get_arenas(struct page_range * ranges,int number_of_ranges)59 int page_get_arenas(struct page_range *ranges, int number_of_ranges) {
60 #if WITH_KERNEL_VM
61     ranges[0].address = kvaddr_get_range(&ranges[0].size);
62     return 1;
63 #else
64     return novm_get_arenas(ranges, number_of_ranges);
65 #endif  // WITH_KERNEL_VM
66 }
67 
page_first_alloc(size_t * size_return)68 void *page_first_alloc(size_t *size_return) {
69 #if WITH_KERNEL_VM
70     *size_return = PAGE_SIZE;
71     return page_alloc(1, PAGE_ALLOC_ANY_ARENA);
72 #else
73     return novm_alloc_unaligned(size_return);
74 #endif
75 }
76 
77 #if LK_DEBUGLEVEL > 1
78 
79 static int cmd_page_alloc(int argc, const console_cmd_args *argv);
80 static void page_alloc_dump(void);
81 
82 STATIC_COMMAND_START
83 STATIC_COMMAND("page_alloc", "page allocator debug commands", &cmd_page_alloc)
84 STATIC_COMMAND_END(page_alloc);
85 
cmd_page_alloc(int argc,const console_cmd_args * argv)86 static int cmd_page_alloc(int argc, const console_cmd_args *argv) {
87     if (argc != 2) {
88 notenoughargs:
89         printf("not enough arguments\n");
90 usage:
91         printf("usage:\n");
92         printf("\t%s info\n", argv[0].str);
93         return -1;
94     }
95 
96     if (strcmp(argv[1].str, "info") == 0) {
97         page_alloc_dump();
98     } else {
99         printf("unrecognized command\n");
100         goto usage;
101     }
102 
103     return 0;
104 }
105 
page_alloc_dump(void)106 static void page_alloc_dump(void) {
107 #ifdef WITH_KERNEL_VM
108     dprintf(INFO, "Page allocator is based on pmm\n");
109 #else
110     dprintf(INFO, "Page allocator is based on novm\n");
111 #endif
112 }
113 
114 #endif
115