add_process_large_range and (towards) atomic context switch

This commit is contained in:
Balazs Gerofi
2012-05-19 16:11:38 +09:00
parent 7c85ac93e8
commit 38a0bde75e
2 changed files with 77 additions and 9 deletions

View File

@@ -81,6 +81,9 @@ void free_process_memory(struct process *proc);
int add_process_memory_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long phys, unsigned long flag);
int add_process_large_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long flag, unsigned long *phys);
int remove_process_region(struct process *proc,
unsigned long start, unsigned long end);
void init_process_stack(struct process *process, int argc, char **argv,

View File

@@ -16,8 +16,8 @@
#endif
#define USER_STACK_NR_PAGES 4
#define KERNEL_STACK_NR_PAGES 8
#define USER_STACK_NR_PAGES 512
#define KERNEL_STACK_NR_PAGES 16
extern long do_arch_prctl(unsigned long code, unsigned long address);
@@ -95,9 +95,67 @@ void update_process_page_table(struct process *process, struct vm_range *range,
pa += PAGE_SIZE;
p += PAGE_SIZE;
}
}
int add_process_large_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long flag, unsigned long *phys)
{
struct vm_range *range;
int npages = (end - start) >> PAGE_SHIFT;
int npages_allocated = 0;
void *virt;
range = kmalloc(sizeof(struct vm_range), 0);
if (!range) {
return -ENOMEM;
}
INIT_LIST_HEAD(&range->list);
range->start = start;
range->end = end;
range->flag = flag;
range->phys = 0;
/* Loop through the range, allocate and map blocks of 64 pages */
for (npages_allocated = 0; npages_allocated < npages;
npages_allocated += 64) {
struct vm_range sub_range;
virt = aal_mc_alloc_pages(64, 0);
if (!virt) {
return -ENOMEM;
}
/* Save the first sub region's physical address */
if (!(*phys)) {
*phys = virt_to_phys(virt);
}
sub_range.phys = virt_to_phys(virt);
sub_range.start = start + npages_allocated * PAGE_SIZE;
sub_range.end = sub_range.start + 64 * PAGE_SIZE;
update_process_page_table(process, &sub_range, flag);
dkprintf("subrange 0x%lX - 0x%lX -> 0x%lx - 0x%lX mapped\n",
sub_range.start, sub_range.end,
sub_range.phys, sub_range.phys + 64 * PAGE_SIZE);
memset(virt, 0, 64 * PAGE_SIZE);
}
dkprintf("range: 0x%lX - 0x%lX (%ld)\n",
range->start, range->end, range->end - range->start);
list_add_tail(&range->list, &process->vm->vm_range_list);
return 0;
}
int add_process_memory_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long phys, unsigned long flag)
@@ -129,8 +187,12 @@ int add_process_memory_range(struct process *process,
if (!(flag & VR_REMOTE)) {
__host_update_process_range(process, range);
}
list_add_tail(&range->list, &process->vm->vm_range_list);
/* Clear content! */
if (!(flag & VR_REMOTE))
memset((void*)phys_to_virt(range->phys), 0, end - start);
return 0;
}
@@ -158,11 +220,13 @@ void init_process_stack(struct process *process, int argc, char **argv,
p[-3] = USER_END - sizeof(unsigned long) * 2;
p[-4] = 0; /* envp terminating NULL */
s_ind = -5;
/* envp */
for (arg_ind = envc - 1; arg_ind > -1; --arg_ind) {
p[s_ind--] = (unsigned long)env[arg_ind];
}
p[s_ind--] = 0; /* argv terminating NULL */
/* argv */
for (arg_ind = argc - 1; arg_ind > -1; --arg_ind) {
p[s_ind--] = (unsigned long)argv[arg_ind];
}
@@ -202,9 +266,6 @@ unsigned long extend_process_region(struct process *proc,
return end;
}
/* Clear content! */
memset(p, 0, aligned_new_end - aligned_end);
add_process_memory_range(proc, aligned_end, aligned_new_end,
virt_to_phys(p), 0);
@@ -331,7 +392,6 @@ void schedule(void)
v->current = next;
}
aal_mc_spinlock_unlock(&(v->runq_lock), irqstate);
if (switch_ctx) {
dkprintf("[%d] schedule: %d => %d \n",
@@ -340,12 +400,14 @@ void schedule(void)
aal_mc_load_page_table(next->vm->page_table);
kprintf("[%d] schedule: tlsblock_base: 0x%lX\n",
aal_mc_get_processor_id(), next->thread.tlsblock_base);
dkprintf("[%d] schedule: tlsblock_base: 0x%lX\n",
aal_mc_get_processor_id(), next->thread.tlsblock_base);
/* Set up new TLS.. */
do_arch_prctl(ARCH_SET_FS, next->thread.tlsblock_base);
aal_mc_spinlock_unlock(&(v->runq_lock), irqstate);
if (prev) {
aal_mc_switch_context(&prev->ctx, &next->ctx);
}
@@ -353,6 +415,9 @@ void schedule(void)
aal_mc_switch_context(NULL, &next->ctx);
}
}
else {
aal_mc_spinlock_unlock(&(v->runq_lock), irqstate);
}
}