1 /*
2  * Copyright (c) 2015 Google, Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <lib/page_alloc.h>
25 
26 #include <debug.h>
27 #include <assert.h>
28 #include <string.h>
29 #include <trace.h>
30 #if WITH_KERNEL_VM
31 #include <kernel/vm.h>
32 #else
33 #include <kernel/novm.h>
34 #endif
35 
36 /* A simple page-aligned wrapper around the pmm or novm implementation of
37  * the underlying physical page allocator. Used by system heaps or any
38  * other user that wants pages of memory but doesn't want to use LK
39  * specific apis.
40  */
41 #define LOCAL_TRACE 0
42 
43 #if WITH_STATIC_HEAP
44 
45 #error "fix static heap post page allocator and novm stuff"
46 
47 #if !defined(HEAP_START) || !defined(HEAP_LEN)
48 #error WITH_STATIC_HEAP set but no HEAP_START or HEAP_LEN defined
49 #endif
50 
51 #endif
52 
page_alloc(size_t pages,int arena)53 void *page_alloc(size_t pages, int arena)
54 {
55 #if WITH_KERNEL_VM
56     void *result = pmm_alloc_kpages(pages, NULL);
57     return result;
58 #else
59     void *result = novm_alloc_pages(pages, arena);
60     return result;
61 #endif
62 }
63 
page_free(void * ptr,size_t pages)64 void page_free(void *ptr, size_t pages)
65 {
66 #if WITH_KERNEL_VM
67     DEBUG_ASSERT(IS_PAGE_ALIGNED((uintptr_t)ptr));
68 
69     pmm_free_kpages(ptr, pages);
70 #else
71     novm_free_pages(ptr, pages);
72 #endif
73 }
74 
page_get_arenas(struct page_range * ranges,int number_of_ranges)75 int page_get_arenas(struct page_range *ranges, int number_of_ranges)
76 {
77 #if WITH_KERNEL_VM
78     ranges[0].address = kvaddr_get_range(&ranges[0].size);
79     return 1;
80 #else
81     return novm_get_arenas(ranges, number_of_ranges);
82 #endif  // WITH_KERNEL_VM
83 }
84 
page_first_alloc(size_t * size_return)85 void *page_first_alloc(size_t *size_return)
86 {
87 #if WITH_KERNEL_VM
88     *size_return = PAGE_SIZE;
89     return page_alloc(1, PAGE_ALLOC_ANY_ARENA);
90 #else
91     return novm_alloc_unaligned(size_return);
92 #endif
93 }
94 
95 #if LK_DEBUGLEVEL > 1
96 #if WITH_LIB_CONSOLE
97 
98 #include <lib/console.h>
99 
100 static int cmd_page_alloc(int argc, const cmd_args *argv);
101 static void page_alloc_dump(void);
102 
103 STATIC_COMMAND_START
104 STATIC_COMMAND("page_alloc", "page allocator debug commands", &cmd_page_alloc)
105 STATIC_COMMAND_END(page_alloc);
106 
cmd_page_alloc(int argc,const cmd_args * argv)107 static int cmd_page_alloc(int argc, const cmd_args *argv)
108 {
109     if (argc != 2) {
110 notenoughargs:
111         printf("not enough arguments\n");
112 usage:
113         printf("usage:\n");
114         printf("\t%s info\n", argv[0].str);
115         return -1;
116     }
117 
118     if (strcmp(argv[1].str, "info") == 0) {
119         page_alloc_dump();
120     } else {
121         printf("unrecognized command\n");
122         goto usage;
123     }
124 
125     return 0;
126 }
127 
page_alloc_dump(void)128 static void page_alloc_dump(void)
129 {
130 #ifdef WITH_KERNEL_VM
131     dprintf(INFO, "Page allocator is based on pmm\n");
132 #else
133     dprintf(INFO, "Page allocator is based on novm\n");
134 #endif
135 }
136 
137 #endif
138 #endif
139