blob: 1e1632751b72b4dcc8f1c0b910f24757672fde06 [file] [edit]
// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2014 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_VM_INCLUDE_VM_VM_H_
#define ZIRCON_KERNEL_VM_INCLUDE_VM_VM_H_
#include <align.h>
#include <arch.h>
#include <lib/ktrace.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <zircon/compiler.h>
#include <arch/kernel_aspace.h>
#include <arch/vm.h>
#include <ktl/span.h>
#include <vm/arch_vm_aspace.h>
#ifndef VM_TRACING_LEVEL
#define VM_TRACING_LEVEL 0
#endif
// Evaluates to true if tracing is enabled for the given level.
#define VM_KTRACE_LEVEL_ENABLED(level) ((VM_TRACING_LEVEL) >= (level))
#define VM_MAKE_UNIQUE_TOKEN3(a, b) a##b
#define VM_MAKE_UNIQUE_TOKEN2(a, b) VM_MAKE_UNIQUE_TOKEN3(a, b)
#define VM_MAKE_UNIQUE_TOKEN(a) VM_MAKE_UNIQUE_TOKEN2(a, __LINE__)
#define VM_KTRACE_DURATION(level, string, args...) \
ktrace::Scope VM_MAKE_UNIQUE_TOKEN(_duration_) = \
KTRACE_BEGIN_SCOPE_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, ##args)
// In builds with verbose VM tracing enabled (VM_TRACING_LEVEL >= 1), we emit these events under the
// "kernel:vm" category at the specified VM tracing level. In standard/production builds
// (VM_TRACING_LEVEL = 0), we fallback to emitting under the lightweight "kernel:oom" category
// instead.
//
// The general expectation is that users will enable "kernel:oom" in cases where "kernel:vm" is
// too expensive. Using a compile-time selection here prevents duplicate overlapping slices in
// the trace visualizer when both categories are enabled at runtime, while still providing a
// single category for developers opting for more verbose VM tracing.
#if VM_TRACING_LEVEL >= 1
#define OOM_KTRACE_DURATION(level, string, args...) VM_KTRACE_DURATION(level, string, ##args)
#else
#define OOM_KTRACE_DURATION(level, string, args...) \
ktrace::Scope VM_MAKE_UNIQUE_TOKEN(_duration_) = KTRACE_BEGIN_SCOPE("kernel:oom", string, ##args)
#endif
#define VM_KTRACE_DURATION_BEGIN(level, string, args...) \
KTRACE_DURATION_BEGIN_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, ##args)
#define VM_KTRACE_DURATION_END(level, string, args...) \
KTRACE_DURATION_END_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, ##args)
#define VM_KTRACE_FLOW_BEGIN(level, string, flow_id, args...) \
KTRACE_FLOW_BEGIN_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, flow_id, ##args)
#define VM_KTRACE_FLOW_END(level, string, flow_id, args...) \
KTRACE_FLOW_END_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, flow_id, ##args)
#define VM_KTRACE_INSTANT(level, string, args...) \
KTRACE_INSTANT_ENABLE(VM_KTRACE_LEVEL_ENABLED(level), "kernel:vm", string, ##args)
class VmAspace;
// kernel address space
static_assert(KERNEL_ASPACE_BASE + (KERNEL_ASPACE_SIZE - 1) > KERNEL_ASPACE_BASE, "");
// user address space, defaults to below kernel space with a 16MB guard gap on either side
static_assert(USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1) > USER_ASPACE_BASE, "");
// linker script provided variables for various virtual kernel addresses
extern const char __executable_start[];
extern const char __code_start[];
extern const char __code_end[];
extern const char __rodata_start[];
extern const char __rodata_end[];
extern const char __relro_start[];
extern const char __relro_end[];
extern char __data_start[];
extern char __data_end[];
extern char __bss_start[];
extern char _end[];
extern paddr_t zero_page_paddr;
extern vm_page_t* zero_page;
// Ends the VM's role within the context of phys handoff: it destroys the VMAR
// containing the mappings backing temporary hand-off data.
void vm_end_handoff();
// return a pointer to the zero page
static inline vm_page_t* vm_get_zero_page(void) { return zero_page; }
// return the physical address of the zero page
static inline paddr_t vm_get_zero_page_paddr(void) { return zero_page_paddr; }
// Whether the virtual heap is enabled.
bool vm_using_virtual_heap();
// Request the heap dimensions.
vaddr_t vm_get_kernel_heap_base();
size_t vm_get_kernel_heap_size();
// internal kernel routines below, do not call directly
// internal routine by the scheduler to swap mmu contexts
void vmm_context_switch(VmAspace* oldspace, VmAspace* newaspace);
// set the current user aspace as active on the current thread.
// NULL is a valid argument, which unmaps the current user address space
void vmm_set_active_aspace(VmAspace* aspace);
#endif // ZIRCON_KERNEL_VM_INCLUDE_VM_VM_H_