Krafton Jungle/5. PintOS

[PintOS 4주차] Day 6

munsik22 2025. 6. 3. 14:33

개피곤...

Memory Management 구현

⚠ 아직 작성중인 코드입니다.

 

🔹 해시 관련 함수

struct hash pages;

unsigned page_hash (const struct hash_elem *p_, void *aux UNUSED);
bool page_less (const struct hash_elem *a_, const struct hash_elem *b_, void *aux UNUSED);
struct page *page_lookup (const void *address);

/* Returns a hash value for page p. */
unsigned
page_hash (const struct hash_elem *p_, void *aux UNUSED) {
	const struct page *p = hash_entry (p_, struct page, hash_elem);
	return hash_bytes (&p->va, sizeof p->va);
}

bool
page_less (const struct hash_elem *a_, const struct hash_elem *b_, void *aux UNUSED) {
	const struct page *a = hash_entry (a_, struct page, hash_elem);
	const struct page *b = hash_entry (b_, struct page, hash_elem);
	return a->va < b->va;
}

/* Returns the page containing the given virtual address, or a null pointer if no such page exists. */
struct page *
page_lookup (const void *address) {
	struct page p;
	struct hash_elem *e;

	p.va = address;
	e = hash_find (&pages, &p.hash_elem);
	return e != NULL ? hash_entry (e, struct page, hash_elem) : NULL;
}
struct hash_elem *
hash_insert_with_va (struct hash *h, struct hash_elem *new, void *va) {
	// struct list *bucket = find_bucket (h, new);
	int key = hash_bytes(&va, sizeof(va)) % h->bucket_cnt;
	struct list *bucket = &h->buckets[key];
	struct hash_elem *old = find_va (h, bucket, va);

	if (old == NULL)
		insert_elem (h, bucket, new);

	rehash (h);

	return old;
}

static struct hash_elem *
find_va (struct hash *h, struct list *bucket, void *va) {
	struct list_elem *i;

	for (i = list_begin (bucket); i != list_end (bucket); i = list_next (i)) {
		struct hash_elem *hi = list_elem_to_hash_elem (i);
		// if (!h->less (hi, e, h->aux) && !h->less (e, hi, h->aux))
		// 	return hi;
		struct page *p = hash_entry(hi, struct page, hash_elem);
		if (p->va == va)
			return hi;
	}
	return NULL;
}

🔹 SPT 관련 함수

struct supplemental_page_table {
	struct hash spt_hash;
};
struct page {
	…
	struct hash_elem hash_elem; /* Hash table element. */
	…
}
struct page *
spt_find_page (struct supplemental_page_table *spt UNUSED, void *va UNUSED) {
	struct page *page = NULL;
	/* TODO: Fill this function. */
	int key = hash_bytes(&va, sizeof(va)) % spt->spt_hash.bucket_cnt;
	struct list *bucket = &spt->spt_hash.buckets[key];
	for (struct list_elem *e = list_begin(bucket); e != list_end(bucket); e = list_next(e)) {
		struct hash_elem *he = list_elem_to_hash_elem(e);
		struct page *p = hash_entry(he, struct page, hash_elem);
		if (p->va == va)
			return p;
	}
	return page;
}

/* Insert PAGE into spt with validation. */
bool
spt_insert_page (struct supplemental_page_table *spt UNUSED, struct page *page UNUSED) {
	bool succ = false;
	/* TODO: Fill this function. */
	if (spt_find_page(spt, page->va) == NULL) {
		hash_insert_with_va(&spt->spt_hash, &page->hash_elem, &page->va);
		succ = true;
	}
	return succ;
}
/* Initialize new supplemental page table */
void
supplemental_page_table_init (struct supplemental_page_table *spt UNUSED) {
	hash_init (&spt->spt_hash, page_hash, page_less, NULL);
}

/* Copy supplemental page table from src to dst */
bool
supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED,
		struct supplemental_page_table *src UNUSED) {
	memcpy(&dst->spt_hash, &src->spt_hash, sizeof(struct supplemental_page_table));
}

/* Free the resource hold by the supplemental page table */
void
supplemental_page_table_kill (struct supplemental_page_table *spt UNUSED) {
	/* TODO: Destroy all the supplemental_page_table hold by thread and
	 * TODO: writeback all the modified contents to the storage. */
	hash_destroy(&spt->spt_hash, &spt->spt_hash.hash);
}

🔹 Frame 관련 함수

static struct frame *
vm_get_frame (void) {
	/* TODO: Fill this function. */
	struct frame *frame = palloc_get_page(PAL_USER);
	frame->kva = NULL;
	frame->page = NULL;

	ASSERT (frame != NULL);
	ASSERT (frame->page == NULL);
	return frame;
}
/* Claim the page that allocate on VA. */
bool
vm_claim_page (void *va UNUSED) {
	struct page *page = NULL;
	/* TODO: Fill this function */
	/* 1. 특정 가상 주소에 대해 페이지를 할당하고, 해당 페이지에 프레임을 매핑함
	 * 2. spt_find_page(spt, va)로 해당 주소에 이미 page가 있는지 확인
	 * 3. 있으면 그 page를 대상으로 vm_do_claim_page() 호출
	 * 4. 없으면 새로운 page를 만들어 spt_insert_page() 후 vm_do_claim_page() 호출 */
	if (va == NULL) return false;
	if (page = spt_find_page(&thread_current()->spt, va) == NULL) {
		page = palloc_get_page(PAL_USER);
		page->va = va;
	}
	return vm_do_claim_page (page);
}

/* Claim the PAGE and set up the mmu. */
static bool
vm_do_claim_page (struct page *page) {
	struct frame *frame = vm_get_frame ();
	if (frame == NULL)
		return false;

	/* Set links */
	frame->page = page;
	page->frame = frame;

	/* TODO: Insert page table entry to map page's VA to frame's PA. */
	// Add the mapping from the VA to the PA in the page table.
	pml4_set_page(curr->pml4, page->va, frame->kva, pml4_is_writable(curr->pml4, page->va));
	if (!spt_insert_page(&thread_current()->spt, page))
		return false;

	return swap_in (page, frame->kva);
}

make check 결과 이전 프로젝트의 테스트부터 전부 실패했다.

Kernel panic in run: PANIC at ../../threads/thread.c:285 in thread_current(): assertion `is_thread (t)' failed.
$ ../../utils/backtrace 0x8004218736 0x80042070a0 0x8004221c95 0x800421d60c 0x80042095c7 0x80042099e5 0x8004221cba 0x800421d60c 0x80042095c7 0x80042099e5 0x8004221cba 0x800421d60c 0x80042095c7 0x80042099e5 0x8004221cba 0x800421d60c 0x80042095c7 0x80042099e5 0x80042218eb 0x800421ce97 0x800421cad0 0x800421c3a4 0x800421bdbf 0x80042074b1
0x0000008004218736: debug_panic (lib/kernel/debug.c:32)
0x00000080042070a0: thread_current (threads/thread.c:286)
0x0000008004221c95: vm_try_handle_fault (vm/vm.c:238)
0x000000800421d60c: page_fault (userprog/exception.c:147)
0x00000080042095c7: intr_handler (threads/interrupt.c:352)
0x00000080042099e5: intr_entry (threads/intr-stubs.o:?)
0x0000008004221cba: vm_try_handle_fault (vm/vm.c:244)
0x000000800421d60c: page_fault (userprog/exception.c:147)
0x00000080042095c7: intr_handler (threads/interrupt.c:352)
0x00000080042099e5: intr_entry (threads/intr-stubs.o:?)
0x0000008004221cba: vm_try_handle_fault (vm/vm.c:244)
0x000000800421d60c: page_fault (userprog/exception.c:147)
0x00000080042095c7: intr_handler (threads/interrupt.c:352)
0x00000080042099e5: intr_entry (threads/intr-stubs.o:?)
0x0000008004221cba: vm_try_handle_fault (vm/vm.c:244)
0x000000800421d60c: page_fault (userprog/exception.c:147)
0x00000080042095c7: intr_handler (threads/interrupt.c:352)
0x00000080042099e5: intr_entry (threads/intr-stubs.o:?)
0x00000080042218eb: vm_alloc_page_with_initializer (vm/vm.c:119)
0x000000800421ce97: load_segment (userprog/process.c:817)
0x000000800421cad0: load (userprog/process.c:589)
0x000000800421c3a4: process_exec (userprog/process.c:306)
0x000000800421bdbf: initd (userprog/process.c:81)
0x00000080042074b1: kernel_thread (threads/thread.c:429)
더보기
Executing 'args-single onearg':
Kernel PANIC at ../../threads/thread.c:285 in thread_current(): assertion `is_thread (t)' failed.
Call stack: 0x8004218736 0x80042070a0 0x8004221d04 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x8004221d30 0x800421d66b 0x80042095c7 0x80042099e5 0x800422194a 0x800421ce9f 0x800421cad0 0x800421c3a4 0x800421bdbf 0x80042074b1.
The `backtrace' program can make call stacks useful.
Read "Backtraces" in the "Debugging Tools" chapter
of the Pintos documentation for more information.
Kernel PANIC recursion at ../../threads/thread.c:285 in thread_current().
Interrupt 0x0d (#GP General Protection Exception) at rip=8004220bd3
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 00000080042228d6 rdx 0000000000000016
rsp 0000008004241a20 rbp 0000008004241a30 rsi 000000000000011d rdi cccccccccccccccc
rip 0000008004220bd3 r8 000000800422296f  r9 000000800421865b r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000002
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000001f
rsp 0000008004241810 rbp 0000008004241820 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000028
rsp 0000008004241600 rbp 0000008004241610 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000031
rsp 00000080042413f0 rbp 0000008004241400 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000003a
rsp 00000080042411e0 rbp 00000080042411f0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000003
rsp 0000008004240fd0 rbp 0000008004240fe0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000000c
rsp 0000008004240dc0 rbp 0000008004240dd0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000015
rsp 0000008004240bb0 rbp 0000008004240bc0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000001e
rsp 00000080042409a0 rbp 00000080042409b0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000027
rsp 0000008004240790 rbp 00000080042407a0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000030
rsp 0000008004240580 rbp 0000008004240590 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000039
rsp 0000008004240370 rbp 0000008004240380 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000002
rsp 0000008004240160 rbp 0000008004240170 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000000b
rsp 000000800423ff50 rbp 000000800423ff60 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000014
rsp 000000800423fd40 rbp 000000800423fd50 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000001d
rsp 000000800423fb30 rbp 000000800423fb40 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000026
rsp 000000800423f920 rbp 000000800423f930 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000002f
rsp 000000800423f710 rbp 000000800423f720 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000038
rsp 000000800423f500 rbp 000000800423f510 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000001
rsp 000000800423f2f0 rbp 000000800423f300 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000000a
rsp 000000800423f0e0 rbp 000000800423f0f0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000013
rsp 000000800423eed0 rbp 000000800423eee0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000001c
rsp 000000800423ecc0 rbp 000000800423ecd0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000025
rsp 000000800423eab0 rbp 000000800423eac0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 000000000000002e
rsp 000000800423e8a0 rbp 000000800423e8b0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000037
rsp 000000800423e690 rbp 000000800423e6a0 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010
Interrupt 0x0d (#GP General Protection Exception) at rip=80042206b9
 cr2=0000000000000008 error=               0
rax cccccccccccccccc rbx 0000000000000000 rcx 0000008004227168 rdx 0000000000000000
rsp 000000800423e480 rbp 000000800423e490 rsi 000000000000000a rdi cccccccccccccccc
rip 00000080042206b9 r8 000000800421865b  r9 000000800421bbaf r10 0000000000000000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000086
es: 0010 ds: 0010 cs: 0008 ss: 0010

그런데 레지스터 값이 cccccccccccccccc인 상황, 어디서 많이 본 것 같은데? 해서 이전 주차에 작성했던 글을 보니, free된 페이지를 접근할 때 발생하는 오류라고 한다.


기존에 작성했던 vm_do_claim_page() 함수를 보면 다음처럼 writable 여부를 확인하고 있다.

pml4_is_writable(curr->pml4, page->va)

이렇게 코드를 작성한 근거는 pte.h에 있다.

#define PTE_FLAGS 0x00000000000000fffUL    /* Flag bits. */
#define PTE_ADDR_MASK  0xffffffffffffff000UL /* Address bits. */
#define PTE_AVL   0x00000e00             /* Bits available for OS use. */
#define PTE_P 0x1                        /* 1=present, 0=not present. */
#define PTE_W 0x2                        /* 1=read/write, 0=read-only. */
#define PTE_U 0x4                        /* 1=user/kernel, 0=kernel only. */
#define PTE_A 0x20                       /* 1=accessed, 0=not acccessed. */
#define PTE_D 0x40                       /* 1=dirty, 0=not dirty (PTEs only). */

PTE의 각 비트는 present 여부, writable 여부, user mode 여부 등을 나타내고 있다. 이를 그림으로 나타내면 다음과 같다.

굳이 struct pagewritable 필드를 추가하지 않아도, pml4의 2번째 비트를 확인하면 페이지의 writable 여부를 확인할 수 있다고 판단했다. 하지만 이는 잘못된 생각이었는데, pml4_is_writable()은 페이지가 이미 매핑된 후에만 의미가 있기 때문이다.

uint64_t *pte = pml4e_walk (pml4, vaddr, false);
return pte != NULL && (*pte & PTE_W) != 0;
  • pml4_is_writable()은 매핑된 페이지의 PTE를 읽어 확인하는 함수다.
    • 즉 가상 주소 vaddr에 대한 PTE를 찾고, 그 PTE의 PTE_W (writable) 비트를 확인하는 구조다.
pml4_set_page(pml4, page->va, frame->kva, ???);
  • 그러나 vm_do_claim_page() 호출 시점에는 VA가 아직 매핑되지 않았다.
    • pml4_set_page()를 호출하기 직전임
    • 아직 PTE 자체가 존재하지 않거나 초기화되지 않은 상태일 수 있음
    • 따라서 pml4_is_writable()을 호출하면 pte == NULL로 예외 발생 OR 잘못된 값을 읽어서 false가 나올 수 있음
pml4_set_page(curr->pml4, page->va, frame->kva, page->writable)
  • 반면에 struct page 구조체에 bool writable 필드를 추가하면, VA가 매핑되기 전에도 writable 여부를 사용할 수 있어 안전하다.

'Krafton Jungle > 5. PintOS' 카테고리의 다른 글

[PintOS 5주차] Day 1  (0) 2025.06.05
[PintOS 4주차] Day 7  (0) 2025.06.04
[PintOS 4주차] Day 4-5  (0) 2025.06.02
[PintOS 4주차] Day 3  (0) 2025.05.31
[PintOS 4주차] Day 2  (4) 2025.05.30