summaryrefslogtreecommitdiff
path: root/kern/kmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/kmem.c')
-rw-r--r--kern/kmem.c140
1 files changed, 107 insertions, 33 deletions
diff --git a/kern/kmem.c b/kern/kmem.c
index 5cce5589..d98be0d6 100644
--- a/kern/kmem.c
+++ b/kern/kmem.c
@@ -41,15 +41,15 @@
* TODO Rework the CPU pool layer to use the SLQB algorithm by Nick Piggin.
*/
+#include <assert.h>
+#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include <kern/assert.h>
#include <kern/init.h>
-#include <kern/limits.h>
#include <kern/list.h>
#include <kern/log2.h>
#include <kern/kmem.h>
@@ -57,9 +57,10 @@
#include <kern/macros.h>
#include <kern/mutex.h>
#include <kern/panic.h>
-#include <kern/param.h>
+#include <kern/shell.h>
#include <kern/thread.h>
#include <machine/cpu.h>
+#include <machine/page.h>
#include <machine/pmap.h>
#include <vm/vm_kmem.h>
#include <vm/vm_page.h>
@@ -1092,41 +1093,28 @@ kmem_cache_info(struct kmem_cache *cache)
{
char flags_str[64];
- if (cache == NULL) {
- mutex_lock(&kmem_cache_list_lock);
-
- list_for_each_entry(&kmem_cache_list, cache, node) {
- kmem_cache_info(cache);
- }
-
- mutex_unlock(&kmem_cache_list_lock);
-
- return;
- }
-
snprintf(flags_str, sizeof(flags_str), "%s%s",
(cache->flags & KMEM_CF_SLAB_EXTERNAL) ? " SLAB_EXTERNAL" : "",
(cache->flags & KMEM_CF_VERIFY) ? " VERIFY" : "");
mutex_lock(&cache->lock);
- printf("kmem: name: %s\n"
- "kmem: flags: 0x%x%s\n"
- "kmem: obj_size: %zu\n"
- "kmem: align: %zu\n"
- "kmem: buf_size: %zu\n"
- "kmem: bufctl_dist: %zu\n"
- "kmem: slab_size: %zu\n"
- "kmem: color_max: %zu\n"
+ printf("kmem: flags: 0x%x%s\n"
+ "kmem: obj_size: %zu\n"
+ "kmem: align: %zu\n"
+ "kmem: buf_size: %zu\n"
+ "kmem: bufctl_dist: %zu\n"
+ "kmem: slab_size: %zu\n"
+ "kmem: color_max: %zu\n"
"kmem: bufs_per_slab: %lu\n"
- "kmem: nr_objs: %lu\n"
- "kmem: nr_bufs: %lu\n"
- "kmem: nr_slabs: %lu\n"
+ "kmem: nr_objs: %lu\n"
+ "kmem: nr_bufs: %lu\n"
+ "kmem: nr_slabs: %lu\n"
"kmem: nr_free_slabs: %lu\n"
- "kmem: buftag_dist: %zu\n"
- "kmem: redzone_pad: %zu\n"
- "kmem: cpu_pool_size: %d\n", cache->name, cache->flags, flags_str,
- cache->obj_size, cache->align, cache->buf_size, cache->bufctl_dist,
+ "kmem: buftag_dist: %zu\n"
+ "kmem: redzone_pad: %zu\n"
+ "kmem: cpu_pool_size: %d\n", cache->flags, flags_str, cache->obj_size,
+ cache->align, cache->buf_size, cache->bufctl_dist,
cache->slab_size, cache->color_max, cache->bufs_per_slab,
cache->nr_objs, cache->nr_bufs, cache->nr_slabs,
cache->nr_free_slabs, cache->buftag_dist, cache->redzone_pad,
@@ -1135,8 +1123,71 @@ kmem_cache_info(struct kmem_cache *cache)
mutex_unlock(&cache->lock);
}
-void __init
-kmem_setup(void)
+#ifdef X15_SHELL
+
+static struct kmem_cache *
+kmem_lookup_cache(const char *name)
+{
+ struct kmem_cache *cache;
+
+ mutex_lock(&kmem_cache_list_lock);
+
+ list_for_each_entry(&kmem_cache_list, cache, node) {
+ if (strcmp(cache->name, name) == 0) {
+ goto out;
+ }
+ }
+
+ cache = NULL;
+
+out:
+ mutex_unlock(&kmem_cache_list_lock);
+
+ return cache;
+}
+
+static void
+kmem_shell_info(int argc, char **argv)
+{
+ struct kmem_cache *cache;
+
+ if (argc < 2) {
+ kmem_info();
+ } else {
+ cache = kmem_lookup_cache(argv[1]);
+
+ if (cache == NULL) {
+ printf("kmem: info: invalid argument\n");
+ return;
+ }
+
+ kmem_cache_info(cache);
+ }
+}
+
+static struct shell_cmd kmem_shell_cmds[] = {
+ SHELL_CMD_INITIALIZER("kmem_info", kmem_shell_info,
+ "kmem_info [<cache_name>]",
+ "display information about kernel memory and caches"),
+};
+
+static int __init
+kmem_setup_shell(void)
+{
+ SHELL_REGISTER_CMDS(kmem_shell_cmds);
+ return 0;
+}
+
+INIT_OP_DEFINE(kmem_setup_shell,
+ INIT_OP_DEP(kmem_setup, true),
+ INIT_OP_DEP(printf_setup, true),
+ INIT_OP_DEP(shell_setup, true),
+ INIT_OP_DEP(thread_setup, true));
+
+#endif /* X15_SHELL */
+
+static int __init
+kmem_bootstrap(void)
{
struct kmem_cpu_pool_type *cpu_pool_type;
char name[KMEM_NAME_SIZE];
@@ -1170,8 +1221,24 @@ kmem_setup(void)
kmem_cache_init(&kmem_caches[i], name, size, 0, NULL, 0);
size <<= 1;
}
+
+ return 0;
+}
+
+INIT_OP_DEFINE(kmem_bootstrap,
+ INIT_OP_DEP(thread_bootstrap, true),
+ INIT_OP_DEP(vm_page_setup, true));
+
+static int __init
+kmem_setup(void)
+{
+ return 0;
}
+INIT_OP_DEFINE(kmem_setup,
+ INIT_OP_DEP(kmem_bootstrap, true),
+ INIT_OP_DEP(vm_kmem_setup, true));
+
static inline size_t
kmem_get_index(unsigned long size)
{
@@ -1282,8 +1349,11 @@ kmem_free(void *ptr, size_t size)
void
kmem_info(void)
{
+ size_t mem_usage, mem_reclaimable, total, total_reclaimable;
struct kmem_cache *cache;
- size_t mem_usage, mem_reclaimable;
+
+ total = 0;
+ total_reclaimable = 0;
printf("kmem: cache obj slab bufs objs bufs "
" total reclaimable\n"
@@ -1297,6 +1367,8 @@ kmem_info(void)
mem_usage = (cache->nr_slabs * cache->slab_size) >> 10;
mem_reclaimable = (cache->nr_free_slabs * cache->slab_size) >> 10;
+ total += mem_usage;
+ total_reclaimable += mem_reclaimable;
printf("kmem: %-19s %6zu %3zuk %4lu %6lu %6lu %7zuk %10zuk\n",
cache->name, cache->obj_size, cache->slab_size >> 10,
@@ -1307,4 +1379,6 @@ kmem_info(void)
}
mutex_unlock(&kmem_cache_list_lock);
+
+ printf("total: %zuk reclaimable: %zuk\n", total, total_reclaimable);
}