further libexec generalization
. new mode for sys_memset: include process so memset can be done in physical or virtual address space. . add a mode to mmap() that lets a process allocate uninitialized memory. . this allows an exec()er (RS, VFS, etc.) to request uninitialized memory from VM and selectively clear the ranges that don't come from a file, leaving no uninitialized memory left for the process to see. . use callbacks for clearing the process, clearing memory in the process, and copying into the process; so that the libexec code can be used from rs, vfs, and in the future, kernel (to load vm) and vm (to load boot-time processes)
This commit is contained in:
@@ -52,7 +52,7 @@ static void pagefault( struct proc *pr,
|
||||
struct exception_frame * frame,
|
||||
int is_nested)
|
||||
{
|
||||
int in_physcopy = 0;
|
||||
int in_physcopy = 0, in_memset = 0;
|
||||
|
||||
reg_t pagefaultcr2;
|
||||
message m_pagefault;
|
||||
@@ -68,13 +68,21 @@ static void pagefault( struct proc *pr,
|
||||
in_physcopy = (frame->eip > (vir_bytes) phys_copy) &&
|
||||
(frame->eip < (vir_bytes) phys_copy_fault);
|
||||
|
||||
in_memset = (frame->eip > (vir_bytes) phys_memset) &&
|
||||
(frame->eip < (vir_bytes) memset_fault);
|
||||
|
||||
if((is_nested || iskernelp(pr)) &&
|
||||
catch_pagefaults && in_physcopy) {
|
||||
catch_pagefaults && (in_physcopy || in_memset)) {
|
||||
#if 0
|
||||
printf("pf caught! addr 0x%lx\n", pagefaultcr2);
|
||||
#endif
|
||||
if (is_nested) {
|
||||
frame->eip = (reg_t) phys_copy_fault_in_kernel;
|
||||
if(in_physcopy) {
|
||||
assert(!in_memset);
|
||||
frame->eip = (reg_t) phys_copy_fault_in_kernel;
|
||||
} else {
|
||||
frame->eip = (reg_t) memset_fault_in_kernel;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pr->p_reg.pc = (reg_t) phys_copy_fault;
|
||||
|
||||
@@ -90,7 +90,7 @@ void phys_outsw(u16_t port, phys_bytes buf, size_t count);
|
||||
u32_t read_cr3(void);
|
||||
void reload_cr3(void);
|
||||
void i386_invlpg(phys_bytes linaddr);
|
||||
void phys_memset(phys_bytes ph, u32_t c, phys_bytes bytes);
|
||||
vir_bytes phys_memset(phys_bytes ph, u32_t c, phys_bytes bytes);
|
||||
void reload_ds(void);
|
||||
void ia32_msr_read(u32_t reg, u32_t * hi, u32_t * lo);
|
||||
void ia32_msr_write(u32_t reg, u32_t hi, u32_t lo);
|
||||
|
||||
@@ -391,13 +391,24 @@ remain_fill:
|
||||
inc %ebp
|
||||
dec %eax
|
||||
jmp remain_fill
|
||||
|
||||
fill_done:
|
||||
LABEL(memset_fault) /* kernel can send us here */
|
||||
mov $0, %eax /* 0 means: no fault */
|
||||
pop %ds
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %ebp
|
||||
ret
|
||||
|
||||
LABEL(memset_fault_in_kernel) /* kernel can send us here */
|
||||
pop %ds
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %ebp
|
||||
mov %cr2, %eax
|
||||
ret
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* mem_rdw */
|
||||
|
||||
@@ -662,16 +662,27 @@ static void vm_print(u32_t *root)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*
|
||||
* lin_memset *
|
||||
*===========================================================================*/
|
||||
int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
|
||||
int vm_memset(endpoint_t who, phys_bytes ph, const u8_t c, phys_bytes bytes)
|
||||
{
|
||||
u32_t p;
|
||||
|
||||
int r = OK;
|
||||
struct proc *whoptr = NULL;
|
||||
|
||||
/* NONE for physical, otherwise virtual */
|
||||
if(who != NONE) {
|
||||
int n;
|
||||
vir_bytes lin;
|
||||
assert(vm_running);
|
||||
if(!isokendpt(who, &n)) return ESRCH;
|
||||
whoptr = proc_addr(n);
|
||||
if(!(lin = umap_local(whoptr, D, ph, bytes))) return EFAULT;
|
||||
ph = lin;
|
||||
}
|
||||
|
||||
p = c | (c << 8) | (c << 16) | (c << 24);
|
||||
|
||||
if(!vm_running) {
|
||||
if(who != NONE) panic("can't vm_memset without vm running");
|
||||
phys_memset(ph, p, bytes);
|
||||
return OK;
|
||||
}
|
||||
@@ -680,24 +691,34 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
|
||||
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
/* With VM, we have to map in the physical memory.
|
||||
assert(!catch_pagefaults);
|
||||
catch_pagefaults=1;
|
||||
|
||||
/* With VM, we have to map in the memory (virtual or physical).
|
||||
* We can do this 4MB at a time.
|
||||
*/
|
||||
while(bytes > 0) {
|
||||
int changed = 0;
|
||||
phys_bytes chunk = bytes, ptr;
|
||||
ptr = createpde(NULL, ph, &chunk, 0, &changed);
|
||||
phys_bytes chunk = bytes, ptr, pfa;
|
||||
ptr = createpde(whoptr, ph, &chunk, 0, &changed);
|
||||
if(changed)
|
||||
reload_cr3();
|
||||
|
||||
/* We can memset as many bytes as we have remaining,
|
||||
* or as many as remain in the 4MB chunk we mapped in.
|
||||
*/
|
||||
phys_memset(ptr, p, chunk);
|
||||
if((pfa=phys_memset(ptr, p, chunk))) {
|
||||
printf("kernel memset pagefault\n");
|
||||
r = EFAULT;
|
||||
break;
|
||||
}
|
||||
bytes -= chunk;
|
||||
ph += chunk;
|
||||
}
|
||||
|
||||
assert(catch_pagefaults);
|
||||
catch_pagefaults=0;
|
||||
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
return OK;
|
||||
|
||||
Reference in New Issue
Block a user