#include "default_pager_internal.h"
#include <default_pager/default_pager_object_server.h>
#include <kern/host.h>
#include <kern/ledger.h>
#include <mach/host_info.h>
#include <mach/host_priv.h>
#include <mach/vm_map.h>
#include <ipc/ipc_space.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
#include <vm/vm_protos.h>
char my_name[] = "(default pager): ";
#if DEFAULT_PAGER_DEBUG
int debug_mask = 0;
#endif
vm_size_t cthread_stack_size = 16 *1024;
extern vm_size_t cthread_wait_stack_size;
unsigned long long vm_page_mask;
int vm_page_shift;
int norma_mk;
boolean_t verbose;
mutex_t dpt_lock;
default_pager_thread_t **dpt_array;
memory_object_default_t default_pager_object;
MACH_PORT_FACE default_pager_default_set;
MACH_PORT_FACE default_pager_internal_set;
MACH_PORT_FACE default_pager_external_set;
#define DEFAULT_PAGER_INTERNAL_COUNT (4)
#define DEFAULT_PAGER_EXTERNAL_COUNT (2)
int default_pager_internal_count = DEFAULT_PAGER_INTERNAL_COUNT;
int default_pager_external_count = DEFAULT_PAGER_EXTERNAL_COUNT;
boolean_t default_pager_notify_server(mach_msg_header_t *,
mach_msg_header_t *);
boolean_t default_pager_demux_object(mach_msg_header_t *,
mach_msg_header_t *);
boolean_t default_pager_demux_default(mach_msg_header_t *,
mach_msg_header_t *);
default_pager_thread_t *start_default_pager_thread(int, boolean_t);
void default_pager(void);
void default_pager_thread(void *);
void default_pager_initialize(void);
boolean_t dp_parse_argument(char *);
unsigned int d_to_i(char *);
extern int vstruct_def_clshift;
void
default_pager(void)
{
int i, id;
__unused static char here[] = "default_pager";
default_pager_thread_t dpt;
kern_return_t kr;
i = default_pager_internal_count + default_pager_external_count + 1;
dpt_array = (default_pager_thread_t **)
kalloc(i * sizeof(default_pager_thread_t *));
memset(dpt_array, 0, i * sizeof(default_pager_thread_t *));
id = 0;
dpt.dpt_buffer = 0;
dpt.dpt_internal = FALSE;
dpt.dpt_initialized_p = TRUE;
dpt_array[0] = &dpt;
for (i = 0; i < default_pager_internal_count; i++) {
dpt_array[id] = (default_pager_thread_t *)
kalloc(sizeof (default_pager_thread_t));
if (dpt_array[id] == NULL)
Panic("alloc pager thread");
kr = vm_allocate(kernel_map, &((dpt_array[id])->dpt_buffer),
vm_page_size << vstruct_def_clshift, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS)
Panic("alloc thread buffer");
kr = vm_map_wire(kernel_map, (dpt_array[id])->dpt_buffer,
((dpt_array[id])->dpt_buffer)
+(vm_page_size << vstruct_def_clshift),
VM_PROT_DEFAULT,
FALSE);
if (kr != KERN_SUCCESS)
Panic("wire thread buffer");
(dpt_array[id])->dpt_internal = TRUE;
(dpt_array[id])->dpt_initialized_p = TRUE;
(dpt_array[id])->checked_out = FALSE;
id++;
}
DPT_LOCK_INIT(dpt_lock);
}
int
local_log2(
unsigned int n)
{
register int i = 0;
if(n == 0) return 0;
while ((n & 1) == 0) {
i++;
n >>= 1;
}
return i;
}
unsigned int
d_to_i(char * arg)
{
unsigned int rval = 0;
char ch;
while ((ch = *arg++) && ch >= '0' && ch <= '9') {
rval *= 10;
rval += ch - '0';
}
return(rval);
}
boolean_t dp_parse_argument(char *av)
{
char *rhs = av;
__unused static char here[] = "dp_parse_argument";
if (av[0] == '-' && av[1] == 'v' && av[2] == 0) {
verbose = TRUE ;
return TRUE;
}
while (*rhs && *rhs != '=')
rhs++;
if (*rhs && *++rhs) {
if (strprefix(av,"cl")) {
if (!bs_set_default_clsize(d_to_i(rhs)))
dprintf(("Bad argument (%s) - ignored\n", av));
return(TRUE);
}
}
return(FALSE);
}
int
start_def_pager( __unused char *bs_device )
{
__unused static char here[] = "main";
#if NORMA_VM
norma_mk = 1;
#else
norma_mk = 0;
#endif
default_pager_initialize();
default_pager();
default_pager_backing_store_monitor_callout =
thread_call_allocate(default_pager_backing_store_monitor, NULL);
if (!default_pager_backing_store_monitor_callout)
panic("can't start backing store monitor thread");
thread_call_enter(default_pager_backing_store_monitor_callout);
return (0);
}
kern_return_t
default_pager_info(
memory_object_default_t pager,
default_pager_info_t *infop)
{
vm_size_t pages_total, pages_free;
if (pager != default_pager_object)
return KERN_INVALID_ARGUMENT;
bs_global_info(&pages_total, &pages_free);
infop->dpi_total_space = ptoa_32(pages_total);
infop->dpi_free_space = ptoa_32(pages_free);
infop->dpi_page_size = vm_page_size;
return KERN_SUCCESS;
}
kern_return_t
default_pager_info_64(
memory_object_default_t pager,
default_pager_info_64_t *infop)
{
vm_size_t pages_total, pages_free;
if (pager != default_pager_object)
return KERN_INVALID_ARGUMENT;
bs_global_info(&pages_total, &pages_free);
infop->dpi_total_space = ptoa_64(pages_total);
infop->dpi_free_space = ptoa_64(pages_free);
infop->dpi_page_size = vm_page_size;
infop->dpi_flags = 0;
if (dp_encryption_inited && dp_encryption == TRUE) {
infop->dpi_flags |= DPI_ENCRYPTED;
}
return KERN_SUCCESS;
}
void
default_pager_initialize(void)
{
kern_return_t kr;
__unused static char here[] = "default_pager_initialize";
vm_page_mask = vm_page_size - 1;
vm_page_shift = local_log2(vm_page_size);
vstruct_zone = zinit(sizeof(struct vstruct),
10000 * sizeof(struct vstruct),
8192, "vstruct zone");
VSL_LOCK_INIT();
queue_init(&vstruct_list.vsl_queue);
vstruct_list.vsl_count = 0;
VSTATS_LOCK_INIT(&global_stats.gs_lock);
bs_initialize();
default_pager_object = ipc_port_alloc_kernel();
#ifdef USER_PAGER
if ((kr = netname_check_in(name_server_port, "UserPager",
default_pager_self,
default_pager_object))
!= KERN_SUCCESS) {
dprintf(("netname_check_in returned 0x%x\n", kr));
exit(1);
}
#else
{
int clsize;
memory_object_default_t dmm;
dmm = default_pager_object;
clsize = (vm_page_size << vstruct_def_clshift);
kr = host_default_memory_manager(host_priv_self(), &dmm, clsize);
if ((kr != KERN_SUCCESS) ||
(dmm != MEMORY_OBJECT_DEFAULT_NULL))
Panic("default memory manager");
}
#endif
}