テスト支援コード
- vm_range_list のテスト支援コード - vm_range 一致確認用関数追加 できれば、指定範囲内の変更を無視させたいのだが、 指定範囲内の変更のために split されたエントリを無害と判断できない - page table のテスト支援コード
This commit is contained in:
287
arch/x86/kernel/include/owano-process.h
Normal file
287
arch/x86/kernel/include/owano-process.h
Normal file
@@ -0,0 +1,287 @@
|
||||
#ifndef OWANO_PROCESS_H
|
||||
#define OWANO_PROCESS_H
|
||||
|
||||
extern void check_vm_range_list(char *msg, struct process_vm *vm);
|
||||
extern struct process_vm *snap_vm_range_list(struct process_vm *vm);
|
||||
extern void destroy_vm_range_list_snap(struct process_vm *snap);
|
||||
extern void show_vm_range_list(struct process_vm *vm, struct vm_range *stop);
|
||||
extern void diff_vm_range_list(struct process_vm *oldvm, struct process_vm *newvm);
|
||||
extern void cmp_vm_range_list(struct process_vm *oldvm, struct process_vm *newvm, struct vm_range *except);
|
||||
|
||||
#ifdef OWANO_IMPLEMENTATION
|
||||
|
||||
void check_vm_range_list(char *msg, struct process_vm *vm) {
|
||||
struct vm_regions *region = &vm->region;
|
||||
struct vm_range *range;
|
||||
struct vm_range *next;
|
||||
const int max = 1000000;
|
||||
int n;
|
||||
struct vm_range *p;
|
||||
struct vm_range *q;
|
||||
|
||||
kprintf("check_vm_range_list(%p,%p): %s\n", msg, vm, msg);
|
||||
n = 0;
|
||||
list_for_each_entry_safe(range, next, &vm->vm_range_list, list) {
|
||||
/* 範囲確認 */
|
||||
if ((range->start < region->user_start) || (region->user_end < range->end)) {
|
||||
kprintf("out of range:%s\n", msg);
|
||||
kprintf("%p: %lx-%lx %lx\n", range, range->start, range->end, range->flag);
|
||||
panic("out of range\n");
|
||||
/* no return */
|
||||
}
|
||||
|
||||
/* リンク整合 */
|
||||
if (range->list.next->prev != &range->list) {
|
||||
kprintf("vm_range_list corrupt:next:%s\n", msg);
|
||||
show_vm_range_list(vm, next);
|
||||
panic("check_vm_range_list");
|
||||
/* no return */
|
||||
}
|
||||
if (range->list.prev->next != &range->list) {
|
||||
kprintf("vm_range_list corrupt:prev:%s\n", msg);
|
||||
show_vm_range_list(vm, range);
|
||||
panic("check_vm_range_list");
|
||||
/* no return */
|
||||
}
|
||||
|
||||
/* ループ確認 */
|
||||
++n;
|
||||
if (n > max) {
|
||||
kprintf("vm_range_list corrupt:too many:%s\n", msg);
|
||||
show_vm_range_list(vm, range);
|
||||
panic("check_vm_range_list");
|
||||
/* no return */
|
||||
}
|
||||
}
|
||||
|
||||
/* レンジ重なり */
|
||||
list_for_each_entry(p, &vm->vm_range_list, list) {
|
||||
list_for_each_entry(q, &vm->vm_range_list, list) {
|
||||
if (p == q) {
|
||||
continue;
|
||||
}
|
||||
if ((p->start < q->end) && (q->start < p->end)) {
|
||||
kprintf("overlapped vm_range:%s\n", msg);
|
||||
kprintf("%p: %lx-%lx %lx\n", p, p->start, p->end, p->flag);
|
||||
kprintf("%p: %lx-%lx %lx\n", q, q->start, q->end, q->flag);
|
||||
panic("overlapped vm_range\n");
|
||||
/* no return */
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct process_vm *snap_vm_range_list(struct process_vm *vm) {
|
||||
struct process_vm *snap = NULL;
|
||||
struct vm_range *orig;
|
||||
struct vm_range *range;
|
||||
|
||||
kprintf("snap_vm_range_list(%p)\n", vm);
|
||||
snap = kmalloc(sizeof(*snap), IHK_MC_AP_NOWAIT);
|
||||
if (snap == NULL) {
|
||||
kprintf("snap_vm_range_list:kmalloc failed\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(snap, 0, sizeof(*snap));
|
||||
INIT_LIST_HEAD(&snap->vm_range_list);
|
||||
snap->region = vm->region;
|
||||
|
||||
list_for_each_entry(orig, &vm->vm_range_list, list) {
|
||||
range = kmalloc(sizeof(*range), IHK_MC_AP_NOWAIT);
|
||||
if (range == NULL) {
|
||||
kprintf("snap_vm_range_list:kmalloc(range) failed\n");
|
||||
destroy_vm_range_list_snap(snap);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(range, orig, sizeof(*range));
|
||||
list_add_tail(&range->list, &snap->vm_range_list);
|
||||
}
|
||||
|
||||
check_vm_range_list("snap_vm_range_list", snap);
|
||||
return snap;
|
||||
}
|
||||
|
||||
void destroy_vm_range_list_snap(struct process_vm *snap) {
|
||||
struct vm_range *range;
|
||||
struct vm_range *next;
|
||||
|
||||
check_vm_range_list("destroy_vm_range_list_snap", snap);
|
||||
list_for_each_entry_safe(range, next, &snap->vm_range_list, list) {
|
||||
list_del(&range->list);
|
||||
kfree(range);
|
||||
}
|
||||
|
||||
kfree(snap);
|
||||
return;
|
||||
}
|
||||
|
||||
void show_vm_range_list(struct process_vm *vm, struct vm_range *stop) {
|
||||
struct vm_range *range;
|
||||
struct vm_range *next;
|
||||
|
||||
kprintf("vm_range_list: %p\n", &vm->vm_range_list);
|
||||
list_for_each_entry_safe(range, next, &vm->vm_range_list, list) {
|
||||
kprintf("%p: n %p p %p %lx-%lx %lx\n",
|
||||
range,
|
||||
range->list.next,
|
||||
range->list.prev,
|
||||
range->start,
|
||||
range->end,
|
||||
range->flag);
|
||||
if ((stop != NULL) && (range == stop)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int is_same_vm_range(struct vm_range *lhs, struct vm_range *rhs) {
|
||||
return (1
|
||||
&& (lhs->start == rhs->start)
|
||||
&& (lhs->end == rhs->end)
|
||||
&& (lhs->flag == rhs->flag)
|
||||
);
|
||||
}
|
||||
|
||||
void diff_vm_range_list(struct process_vm *oldvm, struct process_vm *newvm) {
|
||||
struct vm_range *oldrange;
|
||||
struct vm_range *newrange;
|
||||
int tail = 0;
|
||||
int pending = 0;
|
||||
struct vm_range *pending_range = NULL;
|
||||
|
||||
kprintf("vm_range_list: %p %p\n", oldvm, newvm);
|
||||
|
||||
oldrange = list_first_entry(&oldvm->vm_range_list, struct vm_range, list);
|
||||
newrange = list_first_entry(&newvm->vm_range_list, struct vm_range, list);
|
||||
for (;;) {
|
||||
if ((&oldrange->list == &oldvm->vm_range_list)
|
||||
&& (&newrange->list == &newvm->vm_range_list)) {
|
||||
break;
|
||||
}
|
||||
|
||||
#define is_list_end(e,h,m) (&(e)->m == (h))
|
||||
if (!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& !is_list_end(newrange, &newvm->vm_range_list, list)
|
||||
&& is_same_vm_range(oldrange, newrange)) {
|
||||
/* same */
|
||||
if (tail > 0) {
|
||||
--tail;
|
||||
kprintf(" %012lx-%012lx %lx\n",
|
||||
oldrange->start,
|
||||
oldrange->end,
|
||||
oldrange->flag);
|
||||
}
|
||||
else if (pending <= 0) {
|
||||
pending_range = oldrange;
|
||||
pending = 1;
|
||||
}
|
||||
else if (pending <= 2) {
|
||||
++pending;
|
||||
}
|
||||
else {
|
||||
pending_range = list_entry(pending_range->list.next, struct vm_range, list);
|
||||
}
|
||||
oldrange = list_entry(oldrange->list.next, struct vm_range, list);
|
||||
newrange = list_entry(newrange->list.next, struct vm_range, list);
|
||||
}
|
||||
else {
|
||||
while (pending > 0) {
|
||||
kprintf(" %012lx-%012lx %lx\n",
|
||||
pending_range->start,
|
||||
pending_range->end,
|
||||
pending_range->flag);
|
||||
pending_range = list_entry(pending_range->list.next, struct vm_range, list);
|
||||
--pending;
|
||||
}
|
||||
|
||||
if ((!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& is_list_end(newrange, &newvm->vm_range_list, list))
|
||||
|| (!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& !is_list_end(newrange, &newvm->vm_range_list, list)
|
||||
&& (oldrange->start <= newrange->start))) {
|
||||
/* delete */
|
||||
kprintf("- %012lx-%012lx %lx\n",
|
||||
oldrange->start,
|
||||
oldrange->end,
|
||||
oldrange->flag);
|
||||
oldrange = list_entry(oldrange->list.next, struct vm_range, list);
|
||||
}
|
||||
else {
|
||||
/* add */
|
||||
kprintf("+ %012lx-%012lx %lx\n",
|
||||
newrange->start,
|
||||
newrange->end,
|
||||
newrange->flag);
|
||||
newrange = list_entry(newrange->list.next, struct vm_range, list);
|
||||
}
|
||||
tail = 3;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cmp_vm_range_list(struct process_vm *oldvm, struct process_vm *newvm, struct vm_range *except) {
|
||||
struct vm_range *oldrange;
|
||||
struct vm_range *newrange;
|
||||
|
||||
oldrange = list_first_entry(&oldvm->vm_range_list, struct vm_range, list);
|
||||
newrange = list_first_entry(&newvm->vm_range_list, struct vm_range, list);
|
||||
for (;;) {
|
||||
if ((&oldrange->list == &oldvm->vm_range_list)
|
||||
&& (&newrange->list == &newvm->vm_range_list)) {
|
||||
break;
|
||||
}
|
||||
|
||||
#define is_list_end(e,h,m) (&(e)->m == (h))
|
||||
if (!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& !is_list_end(newrange, &newvm->vm_range_list, list)
|
||||
&& is_same_vm_range(oldrange, newrange)) {
|
||||
/* same */
|
||||
oldrange = list_entry(oldrange->list.next, struct vm_range, list);
|
||||
newrange = list_entry(newrange->list.next, struct vm_range, list);
|
||||
}
|
||||
else if ((!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& is_list_end(newrange, &newvm->vm_range_list, list))
|
||||
|| (!is_list_end(oldrange, &oldvm->vm_range_list, list)
|
||||
&& !is_list_end(newrange, &newvm->vm_range_list, list)
|
||||
&& (oldrange->start <= newrange->start))) {
|
||||
/* delete */
|
||||
if ((except == NULL)
|
||||
|| (oldrange->start < except->start)
|
||||
|| (except->end < oldrange->end))
|
||||
{
|
||||
kprintf("vm_range_list: %p %p\n", oldvm, newvm);
|
||||
kprintf("- %012lx-%012lx %lx\n",
|
||||
oldrange->start,
|
||||
oldrange->end,
|
||||
oldrange->flag);
|
||||
panic("cmp_vm_range_list:deleted\n");
|
||||
}
|
||||
oldrange = list_entry(oldrange->list.next, struct vm_range, list);
|
||||
}
|
||||
else {
|
||||
/* add */
|
||||
if ((except == NULL)
|
||||
|| (newrange->start < except->start)
|
||||
|| (except->end < newrange->end))
|
||||
{
|
||||
kprintf("vm_range_list: %p %p\n", oldvm, newvm);
|
||||
kprintf("+ %012lx-%012lx %lx\n",
|
||||
newrange->start,
|
||||
newrange->end,
|
||||
newrange->flag);
|
||||
panic("cmp_vm_range_list:added\n");
|
||||
}
|
||||
newrange = list_entry(newrange->list.next, struct vm_range, list);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* OWANO_IMPLEMENTATION */
|
||||
#endif /* OWANO_PROCESS_H */
|
||||
Reference in New Issue
Block a user