VM information interface
This commit is contained in:
parent
7d51b0cce1
commit
61bb82a44b
18 changed files with 412 additions and 64 deletions
|
@ -200,7 +200,7 @@ service is
|
||||||
SYSCTL # 44
|
SYSCTL # 44
|
||||||
;
|
;
|
||||||
vm
|
vm
|
||||||
CTL
|
INFO
|
||||||
;
|
;
|
||||||
uid 0;
|
uid 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -974,13 +974,17 @@
|
||||||
# define VM_NOTIFY_SIG_ENDPOINT m1_i1
|
# define VM_NOTIFY_SIG_ENDPOINT m1_i1
|
||||||
# define VM_NOTIFY_SIG_IPC m1_i2
|
# define VM_NOTIFY_SIG_IPC m1_i2
|
||||||
|
|
||||||
#define VM_CTL (VM_RQ_BASE+40)
|
#define VM_INFO (VM_RQ_BASE+40)
|
||||||
#define VCTL_WHAT m1_i1
|
# define VMI_WHAT m2_i1
|
||||||
#define VCTL_PARAM m1_i2
|
# define VMI_EP m2_i2
|
||||||
|
# define VMI_COUNT m2_i3
|
||||||
|
# define VMI_PTR m2_p1
|
||||||
|
# define VMI_NEXT m2_l1
|
||||||
|
|
||||||
/* VCTL_PARAMs */
|
/* VMI_WHAT values. */
|
||||||
#define VCTLP_STATS_MEM 1
|
#define VMIW_STATS 1
|
||||||
#define VCTLP_STATS_EP 2
|
#define VMIW_USAGE 2
|
||||||
|
#define VMIW_REGION 3
|
||||||
|
|
||||||
/* Total. */
|
/* Total. */
|
||||||
#define NR_VM_CALLS 41
|
#define NR_VM_CALLS 41
|
||||||
|
|
|
@ -27,5 +27,34 @@ _PROTOTYPE( int vm_ctl, (int what, int param));
|
||||||
_PROTOTYPE( int vm_set_priv, (int procnr, void *buf));
|
_PROTOTYPE( int vm_set_priv, (int procnr, void *buf));
|
||||||
_PROTOTYPE( int vm_query_exit, (int *endpt));
|
_PROTOTYPE( int vm_query_exit, (int *endpt));
|
||||||
|
|
||||||
|
struct vm_stats_info {
|
||||||
|
int vsi_pagesize; /* page size */
|
||||||
|
int vsi_total; /* total number of memory pages */
|
||||||
|
int vsi_free; /* number of free pages */
|
||||||
|
int vsi_largest; /* largest number of consecutive free pages */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vm_usage_info {
|
||||||
|
vir_bytes vui_total; /* total amount of process memory */
|
||||||
|
vir_bytes vui_common; /* part of memory mapped in more than once */
|
||||||
|
vir_bytes vui_shared; /* shared (non-COW) part of common memory */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vm_region_info {
|
||||||
|
int vri_seg; /* segment of virtual region (T or D) */
|
||||||
|
vir_bytes vri_addr; /* base address of region */
|
||||||
|
vir_bytes vri_length; /* length of region */
|
||||||
|
int vri_prot; /* protection flags (PROT_) */
|
||||||
|
int vri_flags; /* memory flags (subset of MAP_) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_VRI_COUNT 64 /* max. number of regions provided at once */
|
||||||
|
|
||||||
|
_PROTOTYPE( int vm_info_stats, (struct vm_stats_info *vfi) );
|
||||||
|
_PROTOTYPE( int vm_info_usage, (endpoint_t who,
|
||||||
|
struct vm_usage_info *vui) );
|
||||||
|
_PROTOTYPE( int vm_info_region, (endpoint_t who,
|
||||||
|
struct vm_region_info *vri, int count, vir_bytes *next) );
|
||||||
|
|
||||||
#endif /* _MINIX_VM_H */
|
#endif /* _MINIX_VM_H */
|
||||||
|
|
||||||
|
|
|
@ -80,11 +80,11 @@ libsys_FILES=" \
|
||||||
taskcall.c \
|
taskcall.c \
|
||||||
ds.c \
|
ds.c \
|
||||||
vm_brk.c \
|
vm_brk.c \
|
||||||
vm_ctl.c \
|
|
||||||
vm_exec_newmem.c \
|
vm_exec_newmem.c \
|
||||||
vm_exit.c \
|
vm_exit.c \
|
||||||
vm_notify_sig.c \
|
vm_notify_sig.c \
|
||||||
vm_fork.c \
|
vm_fork.c \
|
||||||
|
vm_info.c \
|
||||||
vm_map_phys.c \
|
vm_map_phys.c \
|
||||||
vm_umap.c \
|
vm_umap.c \
|
||||||
vm_push_sig.c"
|
vm_push_sig.c"
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
#include "syslib.h"
|
|
||||||
|
|
||||||
#include <minix/vm.h>
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* vm_umap *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int vm_ctl(int what, int param)
|
|
||||||
{
|
|
||||||
message m;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
m.VCTL_WHAT = what;
|
|
||||||
m.VCTL_PARAM = param;
|
|
||||||
return _taskcall(VM_PROC_NR, VM_CTL, &m);
|
|
||||||
}
|
|
||||||
|
|
54
lib/syslib/vm_info.c
Normal file
54
lib/syslib/vm_info.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
#include "syslib.h"
|
||||||
|
|
||||||
|
#include <minix/vm.h>
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* vm_info_stats *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int vm_info_stats(struct vm_stats_info *vsi)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
m.VMI_WHAT = VMIW_STATS;
|
||||||
|
m.VMI_PTR = (void *) vsi;
|
||||||
|
|
||||||
|
return _taskcall(VM_PROC_NR, VM_INFO, &m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* vm_info_usage *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int vm_info_usage(endpoint_t who, struct vm_usage_info *vui)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
m.VMI_WHAT = VMIW_USAGE;
|
||||||
|
m.VMI_EP = who;
|
||||||
|
m.VMI_PTR = (void *) vui;
|
||||||
|
|
||||||
|
return _taskcall(VM_PROC_NR, VM_INFO, &m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* vm_info_region *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int vm_info_region(endpoint_t who, struct vm_region_info *vri,
|
||||||
|
int count, vir_bytes *next)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
m.VMI_WHAT = VMIW_REGION;
|
||||||
|
m.VMI_EP = who;
|
||||||
|
m.VMI_COUNT = count;
|
||||||
|
m.VMI_PTR = (void *) vri;
|
||||||
|
m.VMI_NEXT = *next;
|
||||||
|
|
||||||
|
if ((result = _taskcall(VM_PROC_NR, VM_INFO, &m)) != OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
*next = m.VMI_NEXT;
|
||||||
|
return m.VMI_COUNT;
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ CFLAGS = $(CPROFILE) $(CPPFLAGS)
|
||||||
LDFLAGS = -i
|
LDFLAGS = -i
|
||||||
LIBS = -lsys
|
LIBS = -lsys
|
||||||
|
|
||||||
OBJ = main.o dmp.o dmp_kernel.o dmp_pm.o dmp_fs.o dmp_rs.o dmp_ds.o
|
OBJ = main.o dmp.o dmp_kernel.o dmp_pm.o dmp_fs.o dmp_rs.o dmp_ds.o dmp_vm.o
|
||||||
|
|
||||||
# build local binary
|
# build local binary
|
||||||
all build: $(SERVER)
|
all build: $(SERVER)
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct hook_entry {
|
||||||
{ F5, monparams_dmp, "Boot monitor parameters" },
|
{ F5, monparams_dmp, "Boot monitor parameters" },
|
||||||
{ F6, irqtab_dmp, "IRQ hooks and policies" },
|
{ F6, irqtab_dmp, "IRQ hooks and policies" },
|
||||||
{ F7, kmessages_dmp, "Kernel messages" },
|
{ F7, kmessages_dmp, "Kernel messages" },
|
||||||
{ F8, vm_dmp, "VM status" },
|
{ F8, vm_dmp, "VM status and process maps" },
|
||||||
{ F10, kenv_dmp, "Kernel parameters" },
|
{ F10, kenv_dmp, "Kernel parameters" },
|
||||||
{ F11, timing_dmp, "Timing details (if enabled)" },
|
{ F11, timing_dmp, "Timing details (if enabled)" },
|
||||||
{ SF1, mproc_dmp, "Process manager process table" },
|
{ SF1, mproc_dmp, "Process manager process table" },
|
||||||
|
@ -126,12 +126,3 @@ PUBLIC void mapping_dmp(void)
|
||||||
printf(" %10s. %s\n", key_name(hooks[h].key), hooks[h].name);
|
printf(" %10s. %s\n", key_name(hooks[h].key), hooks[h].name);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* vm_dmp *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC void vm_dmp(void)
|
|
||||||
{
|
|
||||||
vm_ctl(VCTLP_STATS_MEM, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
#include "../ds/store.h"
|
#include "../ds/store.h"
|
||||||
|
|
||||||
|
#define LINES 22
|
||||||
|
|
||||||
PRIVATE struct data_store ds_store[NR_DS_KEYS];
|
PRIVATE struct data_store ds_store[NR_DS_KEYS];
|
||||||
|
|
||||||
PUBLIC void data_store_dmp()
|
PUBLIC void data_store_dmp()
|
||||||
|
@ -16,7 +18,7 @@ PUBLIC void data_store_dmp()
|
||||||
|
|
||||||
printf("Data store contents:\n");
|
printf("Data store contents:\n");
|
||||||
printf("-slot- ------key------ -----owner----- ---type--- ----value---\n");
|
printf("-slot- ------key------ -----owner----- ---type--- ----value---\n");
|
||||||
for(i = prev_i; i < NR_DS_KEYS; i++) {
|
for(i = prev_i; i < NR_DS_KEYS && n < LINES; i++) {
|
||||||
p = &ds_store[i];
|
p = &ds_store[i];
|
||||||
if(!(p->flags & DSF_IN_USE))
|
if(!(p->flags & DSF_IN_USE))
|
||||||
continue;
|
continue;
|
||||||
|
@ -43,8 +45,7 @@ PUBLIC void data_store_dmp()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n++ == 21)
|
n++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= NR_DS_KEYS) i = 0;
|
if (i >= NR_DS_KEYS) i = 0;
|
||||||
|
|
119
servers/is/dmp_vm.c
Normal file
119
servers/is/dmp_vm.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* Debugging dump procedures for the VM server. */
|
||||||
|
|
||||||
|
#include "inc.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <minix/vm.h>
|
||||||
|
#include <timers.h>
|
||||||
|
#include "../../kernel/proc.h"
|
||||||
|
|
||||||
|
#define LINES 24
|
||||||
|
|
||||||
|
PRIVATE void print_region(struct vm_region_info *vri)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
switch (vri->vri_seg) {
|
||||||
|
case T: c = 'T'; break;
|
||||||
|
case D: c = 'D'; break;
|
||||||
|
default: c = '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" %c %08lx-%08lx %c%c%c %c (%lu kB)\n", c, vri->vri_addr,
|
||||||
|
vri->vri_addr + vri->vri_length,
|
||||||
|
(vri->vri_prot & PROT_READ) ? 'r' : '-',
|
||||||
|
(vri->vri_prot & PROT_WRITE) ? 'w' : '-',
|
||||||
|
(vri->vri_prot & PROT_EXEC) ? 'x' : '-',
|
||||||
|
(vri->vri_flags & MAP_SHARED) ? 's' : 'p',
|
||||||
|
vri->vri_length / 1024L);
|
||||||
|
}
|
||||||
|
|
||||||
|
PUBLIC void vm_dmp()
|
||||||
|
{
|
||||||
|
static struct proc proc[NR_TASKS + NR_PROCS];
|
||||||
|
static struct vm_region_info vri[LINES];
|
||||||
|
struct vm_stats_info vsi;
|
||||||
|
struct vm_usage_info vui;
|
||||||
|
static int prev_i = -1;
|
||||||
|
static vir_bytes prev_base = 0;
|
||||||
|
int r, r2, i, j, first, n = 0;
|
||||||
|
|
||||||
|
if (prev_i == -1) {
|
||||||
|
if ((r = vm_info_stats(&vsi)) != OK) {
|
||||||
|
report("IS", "warning: couldn't talk to VM", r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Total %u kB, free %u kB, largest free area %u kB\n",
|
||||||
|
vsi.vsi_total * (vsi.vsi_pagesize / 1024),
|
||||||
|
vsi.vsi_free * (vsi.vsi_pagesize / 1024),
|
||||||
|
vsi.vsi_largest * (vsi.vsi_pagesize / 1024));
|
||||||
|
n++;
|
||||||
|
printf("\n");
|
||||||
|
n++;
|
||||||
|
|
||||||
|
prev_i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r = sys_getproctab(proc)) != OK) {
|
||||||
|
report("IS", "warning: couldn't get copy of process table", r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = prev_i; i < NR_TASKS + NR_PROCS && n < LINES; i++, prev_base = 0) {
|
||||||
|
if (i < NR_TASKS || isemptyp(&proc[i])) continue;
|
||||||
|
|
||||||
|
/* The first batch dump for each process contains a header line. */
|
||||||
|
first = prev_base == 0;
|
||||||
|
|
||||||
|
r = vm_info_region(proc[i].p_endpoint, vri, LINES - first, &prev_base);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
printf("Process %d (%s): error %d\n",
|
||||||
|
proc[i].p_endpoint, proc[i].p_name, r);
|
||||||
|
n++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
/* The entire batch should fit on the screen. */
|
||||||
|
if (n + 1 + r > LINES) {
|
||||||
|
prev_base = 0; /* restart on next page */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r2 = vm_info_usage(proc[i].p_endpoint, &vui)) != OK) {
|
||||||
|
printf("Process %d (%s): error %d\n",
|
||||||
|
proc[i].p_endpoint, proc[i].p_name, r2);
|
||||||
|
n++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Process %d (%s): total %lu kB, common %lu kB, "
|
||||||
|
"shared %lu kB\n",
|
||||||
|
proc[i].p_endpoint, proc[i].p_name,
|
||||||
|
vui.vui_total / 1024L, vui.vui_common / 1024L,
|
||||||
|
vui.vui_shared / 1024L);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < r; j++) {
|
||||||
|
print_region(&vri[j]);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > LINES) printf("IS: internal error\n");
|
||||||
|
if (n == LINES) break;
|
||||||
|
|
||||||
|
/* This may have to wipe out the "--more--" from below. */
|
||||||
|
printf(" \n");
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= NR_TASKS + NR_PROCS) {
|
||||||
|
i = -1;
|
||||||
|
prev_base = 0;
|
||||||
|
}
|
||||||
|
else printf("--more--\r");
|
||||||
|
prev_i = i;
|
||||||
|
}
|
||||||
|
|
|
@ -803,7 +803,7 @@ struct
|
||||||
{ "GETPHYS", VM_GETPHYS },
|
{ "GETPHYS", VM_GETPHYS },
|
||||||
{ "GETREFCNT", VM_GETREF },
|
{ "GETREFCNT", VM_GETREF },
|
||||||
{ "QUERYEXIT", VM_QUERY_EXIT },
|
{ "QUERYEXIT", VM_QUERY_EXIT },
|
||||||
{ "CTL", VM_CTL },
|
{ "INFO", VM_INFO },
|
||||||
{ NULL, 0 },
|
{ NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -405,6 +405,8 @@ struct memory *chunks; /* list of free memory chunks */
|
||||||
|
|
||||||
addr_init(&addravl);
|
addr_init(&addravl);
|
||||||
|
|
||||||
|
total_pages = 0;
|
||||||
|
|
||||||
/* Use the chunks of physical memory to allocate holes. */
|
/* Use the chunks of physical memory to allocate holes. */
|
||||||
for (i=NR_MEMS-1; i>=0; i--) {
|
for (i=NR_MEMS-1; i>=0; i--) {
|
||||||
if (chunks[i].size > 0) {
|
if (chunks[i].size > 0) {
|
||||||
|
@ -413,6 +415,7 @@ struct memory *chunks; /* list of free memory chunks */
|
||||||
if(first || from < mem_low) mem_low = from;
|
if(first || from < mem_low) mem_low = from;
|
||||||
if(first || to > mem_high) mem_high = to;
|
if(first || to > mem_high) mem_high = to;
|
||||||
FREE_MEM(chunks[i].base, chunks[i].size);
|
FREE_MEM(chunks[i].base, chunks[i].size);
|
||||||
|
total_pages += chunks[i].size;
|
||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ EXTERN int incheck;
|
||||||
EXTERN long vm_sanitychecklevel;
|
EXTERN long vm_sanitychecklevel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* total number of memory pages */
|
||||||
|
EXTERN int total_pages;
|
||||||
|
|
||||||
/* vm operation mode state and values */
|
/* vm operation mode state and values */
|
||||||
EXTERN long vm_paged;
|
EXTERN long vm_paged;
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,36 @@ PUBLIC char *arch_map2str(struct vmproc *vmp, vir_bytes addr)
|
||||||
return bufstr;
|
return bufstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* arch_map2info *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC vir_bytes arch_map2info(struct vmproc *vmp, vir_bytes addr, int *seg,
|
||||||
|
int *prot)
|
||||||
|
{
|
||||||
|
vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
|
||||||
|
vir_bytes textend = textstart +
|
||||||
|
CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_len);
|
||||||
|
vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys);
|
||||||
|
|
||||||
|
/* The protection to be returned here is that of the segment. */
|
||||||
|
if(addr < textstart) {
|
||||||
|
*seg = D;
|
||||||
|
*prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||||
|
return addr;
|
||||||
|
} else if(addr < datastart) {
|
||||||
|
*seg = T;
|
||||||
|
*prot = PROT_READ | PROT_EXEC;
|
||||||
|
return addr - textstart;
|
||||||
|
} else {
|
||||||
|
*seg = D;
|
||||||
|
if (textstart == textend) /* common I&D? */
|
||||||
|
*prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||||
|
else
|
||||||
|
*prot = PROT_READ | PROT_WRITE;
|
||||||
|
return addr - datastart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* arch_addrok *
|
* arch_addrok *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -347,7 +347,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
CALLMAP(VM_GETPHYS, do_get_phys);
|
CALLMAP(VM_GETPHYS, do_get_phys);
|
||||||
CALLMAP(VM_SHM_UNMAP, do_shared_unmap);
|
CALLMAP(VM_SHM_UNMAP, do_shared_unmap);
|
||||||
CALLMAP(VM_GETREF, do_get_refcount);
|
CALLMAP(VM_GETREF, do_get_refcount);
|
||||||
CALLMAP(VM_CTL, do_ctl);
|
CALLMAP(VM_INFO, do_info);
|
||||||
CALLMAP(VM_QUERY_EXIT, do_query_exit);
|
CALLMAP(VM_QUERY_EXIT, do_query_exit);
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct phys_region;
|
||||||
#include <minix/ipc.h>
|
#include <minix/ipc.h>
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
#include <minix/safecopies.h>
|
#include <minix/safecopies.h>
|
||||||
|
#include <minix/vm.h>
|
||||||
#include <timers.h>
|
#include <timers.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <pagetable.h>
|
#include <pagetable.h>
|
||||||
|
@ -42,7 +43,7 @@ _PROTOTYPE( void reserve_proc_mem, (struct memory *mem_chunks,
|
||||||
struct mem_map *map_ptr));
|
struct mem_map *map_ptr));
|
||||||
_PROTOTYPE( int vm_isokendpt, (endpoint_t ep, int *proc) );
|
_PROTOTYPE( int vm_isokendpt, (endpoint_t ep, int *proc) );
|
||||||
_PROTOTYPE( int get_stack_ptr, (int proc_nr, vir_bytes *sp) );
|
_PROTOTYPE( int get_stack_ptr, (int proc_nr, vir_bytes *sp) );
|
||||||
_PROTOTYPE( int do_ctl, (message *) );
|
_PROTOTYPE( int do_info, (message *) );
|
||||||
|
|
||||||
/* exit.c */
|
/* exit.c */
|
||||||
_PROTOTYPE( void clear_proc, (struct vmproc *vmp) );
|
_PROTOTYPE( void clear_proc, (struct vmproc *vmp) );
|
||||||
|
@ -168,16 +169,22 @@ _PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp,
|
||||||
struct vir_region *region, struct phys_region *ph));
|
struct vir_region *region, struct phys_region *ph));
|
||||||
_PROTOTYPE(void pb_unreferenced, (struct vir_region *region,
|
_PROTOTYPE(void pb_unreferenced, (struct vir_region *region,
|
||||||
struct phys_region *pr));
|
struct phys_region *pr));
|
||||||
|
_PROTOTYPE(void get_usage_info, (struct vmproc *vmp,
|
||||||
|
struct vm_usage_info *vui));
|
||||||
|
_PROTOTYPE(int get_region_info, (struct vmproc *vmp,
|
||||||
|
struct vm_region_info *vri, int count, vir_bytes *nextp));
|
||||||
#if SANITYCHECKS
|
#if SANITYCHECKS
|
||||||
_PROTOTYPE(void map_sanitycheck,(char *file, int line));
|
_PROTOTYPE(void map_sanitycheck,(char *file, int line));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* $(ARCH)/vm.c */
|
/* $(ARCH)/vm.c */
|
||||||
_PROTOTYPE( vir_bytes, arch_map2vir(struct vmproc *vmp, vir_bytes addr));
|
_PROTOTYPE( vir_bytes arch_map2vir, (struct vmproc *vmp, vir_bytes addr));
|
||||||
_PROTOTYPE( char *, arch_map2str(struct vmproc *vmp, vir_bytes addr));
|
_PROTOTYPE( char *arch_map2str, (struct vmproc *vmp, vir_bytes addr));
|
||||||
_PROTOTYPE( vir_bytes, arch_vir2map(struct vmproc *vmp, vir_bytes addr));
|
_PROTOTYPE( vir_bytes arch_map2info, (struct vmproc *vmp, vir_bytes addr,
|
||||||
_PROTOTYPE( vir_bytes, arch_vir2map_text(struct vmproc *vmp, vir_bytes addr));
|
int *space, int *prot));
|
||||||
_PROTOTYPE( vir_bytes, arch_addrok(struct vmproc *vmp, vir_bytes addr));
|
_PROTOTYPE( vir_bytes arch_vir2map, (struct vmproc *vmp, vir_bytes addr));
|
||||||
|
_PROTOTYPE( vir_bytes arch_vir2map_text, (struct vmproc *vmp, vir_bytes addr));
|
||||||
|
_PROTOTYPE( vir_bytes arch_addrok, (struct vmproc *vmp, vir_bytes addr));
|
||||||
|
|
||||||
/* rs.c */
|
/* rs.c */
|
||||||
_PROTOTYPE(int do_rs_set_priv, (message *m));
|
_PROTOTYPE(int do_rs_set_priv, (message *m));
|
||||||
|
|
|
@ -1455,6 +1455,76 @@ PUBLIC int map_get_ref(struct vmproc *vmp, vir_bytes addr, u8_t *cnt)
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*========================================================================*
|
||||||
|
* get_usage_info *
|
||||||
|
*========================================================================*/
|
||||||
|
PUBLIC void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui)
|
||||||
|
{
|
||||||
|
struct vir_region *vr;
|
||||||
|
physr_iter iter;
|
||||||
|
struct phys_region *ph;
|
||||||
|
vir_bytes len;
|
||||||
|
|
||||||
|
memset(vui, 0, sizeof(*vui));
|
||||||
|
|
||||||
|
for(vr = vmp->vm_regions; vr; vr = vr->next) {
|
||||||
|
physr_start_iter_least(vr->phys, &iter);
|
||||||
|
while((ph = physr_get_iter(&iter))) {
|
||||||
|
len = ph->ph->length;
|
||||||
|
|
||||||
|
/* All present pages are counted towards the total. */
|
||||||
|
vui->vui_total += len;
|
||||||
|
|
||||||
|
if (ph->ph->refcount > 1) {
|
||||||
|
/* Any page with a refcount > 1 is common. */
|
||||||
|
vui->vui_common += len;
|
||||||
|
|
||||||
|
/* Any common, non-COW page is shared. */
|
||||||
|
if (vr->flags & VR_SHARED ||
|
||||||
|
ph->ph->share_flag == PBSH_SMAP)
|
||||||
|
vui->vui_shared += len;
|
||||||
|
}
|
||||||
|
physr_incr_iter(&iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* get_region_info *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int get_region_info(struct vmproc *vmp, struct vm_region_info *vri,
|
||||||
|
int max, vir_bytes *nextp)
|
||||||
|
{
|
||||||
|
struct vir_region *vr;
|
||||||
|
vir_bytes next;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
next = *nextp;
|
||||||
|
|
||||||
|
if (!max) return 0;
|
||||||
|
|
||||||
|
for(vr = vmp->vm_regions; vr; vr = vr->next)
|
||||||
|
if (vr->vaddr >= next) break;
|
||||||
|
|
||||||
|
if (!vr) return 0;
|
||||||
|
|
||||||
|
for(count = 0; vr && count < max; vr = vr->next, count++, vri++) {
|
||||||
|
vri->vri_addr = arch_map2info(vmp, vr->vaddr, &vri->vri_seg,
|
||||||
|
&vri->vri_prot);
|
||||||
|
vri->vri_length = vr->length;
|
||||||
|
|
||||||
|
/* "AND" the provided protection with per-page protection. */
|
||||||
|
if (!(vr->flags & VR_WRITABLE))
|
||||||
|
vri->vri_prot &= ~PROT_WRITE;
|
||||||
|
|
||||||
|
vri->vri_flags = (vr->flags & VR_SHARED) ? MAP_SHARED : 0;
|
||||||
|
|
||||||
|
next = vr->vaddr + vr->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nextp = next;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/*========================================================================*
|
/*========================================================================*
|
||||||
* regionprintstats *
|
* regionprintstats *
|
||||||
|
|
|
@ -122,7 +122,7 @@ PUBLIC int vm_isokendpt(endpoint_t endpoint, int *proc)
|
||||||
{
|
{
|
||||||
*proc = _ENDPOINT_P(endpoint);
|
*proc = _ENDPOINT_P(endpoint);
|
||||||
if(*proc < 0 || *proc >= NR_PROCS)
|
if(*proc < 0 || *proc >= NR_PROCS)
|
||||||
vm_panic("crazy slot number", *proc);
|
return EINVAL;
|
||||||
if(*proc >= 0 && endpoint != vmproc[*proc].vm_endpoint)
|
if(*proc >= 0 && endpoint != vmproc[*proc].vm_endpoint)
|
||||||
return EDEADSRCDST;
|
return EDEADSRCDST;
|
||||||
if(*proc >= 0 && !(vmproc[*proc].vm_flags & VMF_INUSE))
|
if(*proc >= 0 && !(vmproc[*proc].vm_flags & VMF_INUSE))
|
||||||
|
@ -166,27 +166,82 @@ char *brk_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_ctl *
|
* do_info *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int do_ctl(message *m)
|
PUBLIC int do_info(message *m)
|
||||||
{
|
{
|
||||||
int pages, nodes;
|
struct vm_stats_info vsi;
|
||||||
int pr;
|
struct vm_usage_info vui;
|
||||||
|
static struct vm_region_info vri[MAX_VRI_COUNT];
|
||||||
struct vmproc *vmp;
|
struct vmproc *vmp;
|
||||||
|
vir_bytes addr, size, next, ptr;
|
||||||
|
int r, pr, dummy, count;
|
||||||
|
|
||||||
switch(m->VCTL_WHAT) {
|
if (vm_isokendpt(m->m_source, &pr) != OK)
|
||||||
case VCTLP_STATS_MEM:
|
return EINVAL;
|
||||||
printmemstats();
|
vmp = &vmproc[pr];
|
||||||
break;
|
|
||||||
case VCTLP_STATS_EP:
|
ptr = (vir_bytes) m->VMI_PTR;
|
||||||
if(vm_isokendpt(m->VCTL_PARAM, &pr) != OK)
|
|
||||||
return EINVAL;
|
switch(m->VMI_WHAT) {
|
||||||
printregionstats(&vmproc[pr]);
|
case VMIW_STATS:
|
||||||
break;
|
vsi.vsi_pagesize = VM_PAGE_SIZE;
|
||||||
default:
|
vsi.vsi_total = total_pages;
|
||||||
|
memstats(&dummy, &vsi.vsi_free, &vsi.vsi_largest);
|
||||||
|
|
||||||
|
addr = (vir_bytes) &vsi;
|
||||||
|
size = sizeof(vsi);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VMIW_USAGE:
|
||||||
|
if (vm_isokendpt(m->VMI_EP, &pr) != OK)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
get_usage_info(&vmproc[pr], &vui);
|
||||||
|
|
||||||
|
addr = (vir_bytes) &vui;
|
||||||
|
size = sizeof(vui);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VMIW_REGION:
|
||||||
|
if (vm_isokendpt(m->VMI_EP, &pr) != OK)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
count = MIN(m->VMI_COUNT, MAX_VRI_COUNT);
|
||||||
|
next = m->VMI_NEXT;
|
||||||
|
|
||||||
|
count = get_region_info(&vmproc[pr], vri, count, &next);
|
||||||
|
|
||||||
|
m->VMI_COUNT = count;
|
||||||
|
m->VMI_NEXT = next;
|
||||||
|
|
||||||
|
addr = (vir_bytes) vri;
|
||||||
|
size = sizeof(vri[0]) * count;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
if (size == 0)
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
/* Make sure that no page faults can occur while copying out. A page
|
||||||
|
* fault would cause the kernel to send a notify to us, while we would
|
||||||
|
* be waiting for the result of the copy system call, resulting in a
|
||||||
|
* deadlock. Note that no memory mapping can be undone without the
|
||||||
|
* involvement of VM, so we are safe until we're done.
|
||||||
|
*/
|
||||||
|
r = handle_memory(vmp, arch_vir2map(vmp, ptr), size, 1 /*wrflag*/);
|
||||||
|
if (r != OK) return r;
|
||||||
|
|
||||||
|
/* Now that we know the copy out will succeed, perform the actual copy
|
||||||
|
* operation.
|
||||||
|
*/
|
||||||
|
return sys_datacopy(SELF, addr,
|
||||||
|
(vir_bytes) vmp->vm_endpoint, ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue