JOS——lab 4

  1. Compare kern/mpentry.S side by side with boot/boot.S. Bearing in mind thatkern/mpentry.S is compiled and linked to run aboveKERNBASE just like everything else in the kernel, what is the purpose of macroMPBOOTPHYS? Why is it necessary inkern/mpentry.S but not inboot/boot.S? In other words, what could go wrong if it were omitted inkern/mpentry.S?
    Hint: recall the differences between the link address and the load address that we have discussed in Lab 1.


问题一:

static void
boot_aps(void)
{
        extern unsigned char mpentry_start[], mpentry_end[]; //分别为mpentry的起始地址和mpentry的终止地址
        void *code;
        struct Cpu *c;

        // Write entry code to unused memory at MPENTRY_PADDR
        code = KADDR(MPENTRY_PADDR);    
        memmove(code, mpentry_start, mpentry_end - mpentry_start);  //将mpentry移动到MPENTRY_PADDR页面中

        // Boot each AP one at a time
        for (c = cpus; c < cpus + ncpu; c++) {
                if (c == cpus + cpunum())  // We've started already.
                        continue;

                // Tell mpentry.S what stack to use 
                mpentry_kstack = percpu_kstacks[c - cpus] + KSTKSIZE;
                // Start the CPU at mpentry_start
                lapic_startap(c->cpu_id, PADDR(code));
                // Wait for the CPU to finish some basic setup in mp_main()
                while(c->cpu_status != CPU_STARTED)
                        ;
        }
}   


#define MPBOOTPHYS(s) ((s) - mpentry_start + MPENTRY_PADDR)

但是在AP的保护模式打开之前,是没有办法寻址到3G以上的空间的,因此用MPBOOTPHYS是用来计算相应的物理地址的。

但是在boot.S中,由于尚没有启用分页机制,所以我们能够指定程序开始执行的地方以及程序加载的地址;但是,在mpentry.S的时候,由于主CPU已经处于保护模式下了,因此是不能直接指定物理地址的,给定线性地址,映射到相应的物理地址是允许的。


Question

  1. It seems that using the big kernel lock guarantees that only one CPU can run the kernel code at a time. Why do we still need separate kernel stacks for each CPU? Describe a scenario in which using a shared kernel stack will go wrong, even with the protection of the big kernel lock.

问题二:

我们描述这样一种情况,考虑CPU0和CPU1

(1)CPU0运行中,遇到持续等待某个中断发生

(2)CPU1开始运行,CPU1将保存在task state中的寄存器的值恢复

(3)CPU1持续等待某个中断发生

(4)CPU0等待的中断发生,切换到CPU0

问题出现,因为CPU1保存在堆栈中的内容并没有弹出,因此此时转向CPU0时,共享栈的内容会出错。

Question

  1. In your implementation of env_run() you should havecalled lcr3(). Before and after the call tolcr3(), your code makes references (at least it should)to the variable e, the argument to env_run.Upon loading the %cr3 register, the addressing contextused by the MMU is instantly changed. But a virtualaddress (namely e) has meaning relative to a givenaddress context--the address context specifies the physical address towhich the virtual address maps. Why can the pointer e bedereferenced both before and after the addressing switch?
问题三:

因为进程的切换是在内核中的,而内核的地址是固定的,也就是无论是哪个进程的页目录,内核都映射到相同的地址,因此,不会出现问题。

你可能感兴趣的:(c,struct,basic,each,Go)