[Pintos-KAIST] Project 3 : Stack Growth

์œ ์„ ยท2024๋…„ 5์›” 20์ผ
0

Pintos - KAIST

๋ชฉ๋ก ๋ณด๊ธฐ
13/16
post-thumbnail

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB ๋ ˆํฌ์ง€ํ† ๋ฆฌ
๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB Stack Growth ์ด์Šˆ

๊ณผ์ œ ์„ค๋ช…

ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค 1 ํŽ˜์ด์ง€์”ฉ ์ž๋ผ๋‚˜๋Š” ์Šคํƒ์„ ๋งŒ๋“ค์–ด์ค„ ๊ฒƒ์ด๋‹ค. ์ฆ‰,

๐Ÿ’ก Page Fault์— ์˜ํ•ด ๋™์ ์œผ๋กœ ์ž๋ผ๋‚˜๋Š” ์Šคํƒ์„ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.

์–ด๋Š ํƒ€์ด๋ฐ์— STACK GROW ํ•  ๊ฒƒ์ธ๊ฐ€?

ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์„ ๋•Œ, ์ด ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ stack growth์— ๋Œ€ํ•œ ํŽ˜์ด์ง€ ํดํŠธ์ผ ๋•Œ ์Šคํƒ์„ ํ‚ค์šด๋‹ค.


์šฐ์„  ์Šคํƒ์˜์—ญ์„ ํ™•์žฅ ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ˜„์žฌ ์Šคํƒ ํฌ์ธํ„ฐ ์œ„์น˜๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ์Šค๋ ˆ๋“œ ๊ตฌ์กฐ์ฒด ์•ˆ์— ์Šคํƒ ํฌ์ธํ„ฐ์™€ ์Šคํƒ ๋ฐ”ํ…€์„ ์ €์žฅํ•ด ๋‘”๋‹ค.
์Šคํƒ์„ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์€ ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ด๋ฏ€๋กœ ํŽ˜์ด์ง€ ํดํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์Šคํƒ ํ™•์žฅ์„ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ๋œ๋‹ค.


๊ตฌํ˜„

ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ

1๏ธโƒฃ ์œ ํšจํ•œ ์ฃผ์†Œ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ
2๏ธโƒฃ ์‹ค์ œ ํ• ๋‹นํ•˜๋ ค๋Š” ํŽ˜์ด์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
3๏ธโƒฃ ์Šคํƒ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ โ†’ ํ˜„์žฌ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ์ƒํ™ฉ โœ…

1. vm_try_handle_fault()

1-1. define STACK_LIMIT

  • include/vm/vm.h
  • Pintos์—์„œ๋Š” ์ตœ๋Œ€ ์Šคํƒ ํฌ๊ธฐ๋ฅผ 1MB(1,048,576 bytes)๋กœ ์ œํ•œํ•œ๋‹ค.
  • USER_STACK - 1MB๋ณด๋‹ค ๋‚ฎ์€ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด ์ž˜๋ชป๋œ ์ ‘๊ทผ์œผ๋กœ ํŒ๋ณ„ํ•œ๋‹ค.
/** Project 3-Stack Growth*/
#define STACK_LIMIT (USER_STACK - (1 << 20))  

1-2. vm_try_handle_fault() ์ˆ˜์ •

  • vm/vm.c
  • page fault ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ userprog/exception.c์—์„œ page_fault() ๋กœ ํ˜ธ์ถœ๋œ๋‹ค.
  • ์ด ํ•จ์ˆ˜์—์„œ๋Š” page fault๊ฐ€ ์Šคํƒ์„ ์ฆ๊ฐ€์‹œ์ผœ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.
  • ์Šคํƒ ์ฆ๊ฐ€๋กœ page fault๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, page fault๊ฐ€ ๋ฐœ์ƒํ•œ ์ฃผ์†Œ๋กœ vm_stack_growth ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  • !vm_claim_page(addr) โ†’ ๊ฐ€์ƒ ์ฃผ์†Œ addr์— ๋Œ€ํ•ด์„œ ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
bool
vm_try_handle_fault (struct intr_frame *f UNUSED, void *addr UNUSED,
		bool user UNUSED, bool write UNUSED, bool not_present UNUSED) {
	struct supplemental_page_table *spt UNUSED = &thread_current ()->spt;

	/** Project 3-Anonymous Page */
	struct page *page = NULL;

    if (addr == NULL || is_kernel_vaddr(addr))
        return false;

    if (not_present)
    {
		/** Project 3-Stack Growth*/
		void *rsp = user ?  f->rsp : thread_current()->stack_pointer;
		if (STACK_LIMIT <= rsp - 8 && rsp - 8 == addr && addr <= USER_STACK){
			vm_stack_growth(addr);
			return true;
		}
		else if (STACK_LIMIT <= rsp && rsp <= addr && addr <= USER_STACK){
			vm_stack_growth(addr);
			return true;
		}
		page = spt_find_page(spt, addr);

		if (!page || (write && !page->writable))
			return false;
		
		return vm_do_claim_page(page);
    }
    return false;
}
  • f : ํŽ˜์ด์ง€ ํดํŠธ ๋ฐœ์ƒ ์ˆœ๊ฐ„์˜ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ตฌ์กฐ์ฒด
  • addr : ํŽ˜์ด์ง€ ํดํŠธ๋ฅผ ์ผ์œผํ‚จ ๊ฐ€์ƒ์ฃผ์†Œ
  • not_present : ํŽ˜์ด์ง€ ์กด์žฌ x (bogus fault), false์ธ ๊ฒฝ์šฐ read-onlyํŽ˜์ด์ง€์— writeํ•˜๋ ค๋Š” ์ƒํ™ฉ
  • user : ์œ ์ €์— ์˜ํ•œ ์ ‘๊ทผ(true), ์ปค๋„์— ์˜ํ•œ ์ ‘๊ทผ(false) - rsp ๊ฐ’์ด ์œ ์ € ์˜์—ญ์ธ์ง€ ์ปค๋„์˜์—ญ์ธ์ง€
  • write : ์“ฐ๊ธฐ ๋ชฉ์  ์ ‘๊ทผ(true), ์ฝ๊ธฐ ๋ชฉ์  ์ ‘๊ทผ(false)

2. vm_stack_growth() ๊ตฌํ˜„

  • vm/vm.c
  • addr ์ด ๋”์ด์ƒ page fault๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ฃผ์†Œ๊ฐ€ ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋‚˜ ์ด์ƒ์˜ ์ต๋ช… ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ•˜์—ฌ ์Šคํƒ์˜ ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
static void
vm_stack_growth (void *addr UNUSED) {
	/** Project 3-Stack Growth*/
    bool success = false;
	addr = pg_round_down(addr);
    if (vm_alloc_page(VM_ANON | VM_MARKER_0, addr, true)) {
        success = vm_claim_page(addr);

        if (success) {
            thread_current()->stack_bottom -= PGSIZE;
        }
    }
}

3. page_fault ์ˆ˜์ •

  • userprog/exception.c
/** #project3-Stack Growth */
#ifdef VM
	if (vm_try_handle_fault(f, fault_addr, user, write, not_present))
	{
		return;
	}
	else
	{
		page_fault_cnt++;
		exit(-1);
	}
#endif

4. read() ์กฐ๊ฑด ์ถ”๊ฐ€

  • userprog/syscall.c
/** #project3-Stack Growth */
#ifdef VM
    struct page *page = spt_find_page(&thread_current()->spt, buffer);
    if (page && !page->writable)
        exit(-1);
#endif

์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

  • ์ „์ฒด์ฝ”๋“œ
/** Project 2-Extend File Descriptor */
int 
read(int fd, void *buffer, unsigned length) 
{
    struct thread *curr = thread_current();
    check_address(buffer);
/** #project3-Stack Growth */
#ifdef VM
    struct page *page = spt_find_page(&thread_current()->spt, buffer);
    if (page && !page->writable)
        exit(-1);
#endif
    struct file *file = process_get_file(fd);

    if (file == STDIN) { 
        int i = 0; 
        char c;
        unsigned char *buf = buffer;

        for (; i < length; i++) {
            c = input_getc();
            *buf++ = c;
            if (c == '\0')
                break;
        }
        return i;
    }

    if (file == NULL || file == STDOUT || file == STDERR)  // ๋นˆ ํŒŒ์ผ, stdout, stderr๋ฅผ ์ฝ์œผ๋ ค๊ณ  ํ•  ๊ฒฝ์šฐ
        return -1;

    off_t bytes = -1;

    lock_acquire(&filesys_lock);
    bytes = file_read(file, buffer, length);
    lock_release(&filesys_lock);

    return bytes;
}

5. syscall_handler() ์ˆ˜์ •

  • userprog/syscall.c
  • ์œ ์ € ๋ชจ๋“œ์—์„œ ์ปค๋„ ๋ชจ๋“œ๋กœ ๋ฐ”๋€Œ๋ฉด์„œ ์‹œ์Šคํ…œ ์ฝœ์ด ํ˜ธ์ถœ๋  ๋•Œ, ๋ฏธ๋ฆฌ ์œ ์ € ์Šคํƒ ํฌ์ธํ„ฐ๋ฅผ ์Šค๋ ˆ๋“œ ๊ตฌ์กฐ์ฒด ๋‚ด์— ์ €์žฅํ•ด ๋†“๋Š”๋‹ค.
  • ์‹œ์Šคํ…œ ์ฝœ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐ›์€ ์ธํ„ฐ๋ŸฝํŠธ ํ”„๋ ˆ์ž„์˜ RSP ๊ฐ’์€ ์œ ์ € ํ”„๋กœ์„ธ์Šค์˜ ์œ ์ € ์Šคํƒ ํฌ์ธํ„ฐ ๊ฐ’์ด๋‹ค.
#ifdef VM
    thread_current()->stack_pointer = f->rsp;
#endif
profile
Sunny Day!

0๊ฐœ์˜ ๋Œ“๊ธ€