码迷,mamicode.com
首页 > 其他好文 > 详细

MIT_xv6_Lab4_PartA

时间:2020-07-11 23:16:57      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:++   int   halt   sch   flow   another   append   uri   clear   

Introduction

In part A we should add multiprocessor support to JOS, implement round-robin scheduling, and add basic environment management system calls (calls that create and destroy environments, and allocate/map memory).

In the first part of this lab, we will first extend JOS to run on a multiprocessor system, and then implement some new JOS kernel system calls to allow user-level environments to create additional new environments. we will also implement cooperative round-robin scheduling, allowing the kernel to switch from one environment to another when the current environment voluntarily relinquishes the CPU (or exits). Later in part C we will implement preemptive scheduling, which allows the kernel to re-take control of the CPU from an environment after a certain time has passed even if the environment does not cooperate.

Multiprocessor Support

We are going to make JOS support "symmetric multiprocessing" (SMP), all CPUs are functionally identical in SMP, during the boot process they can be classified into two types:

  1. the bootstrap processor (BSP) is responsible for initializing the system and for booting the operating system;
  2. application processors (APs) are activated by the BSP only after the operating system is up and running

Which processor is the BSP is determined by the hardware and the BIOS. Up to this point, all existing JOS code that we write and implement has been running on the BSP

APIC (LAPIC) unit

In an SMP system, each CPU has an accompanying local APIC (LAPIC) unit.

function: The LAPIC units are responsible for delivering interrupts throughout the system. The LAPIC also provides its connected CPU with a unique identifier.

  1. Reading the LAPIC identifier (APIC ID) to tell which CPU our code is currently running on (see cpunum()).

    int cpunum(void)
    {
    	if (lapic)
    		return lapic[ID] >> 24;
    	return 0;
    }
    
  2. Sending the STARTUP interprocessor interrupt (IPI) from the BSP to the APs to bring up other CPUs (see lapic_startap()).

    // Start additional processor running entry code at addr.
    // See Appendix B of MultiProcessor Specification.
    void lapic_startap(uint8_t apicid, uint32_t addr)
    {
    	int i;
    	uint16_t *wrv;
    
    	// "The BSP must initialize CMOS shutdown code to 0AH
    	// and the warm reset vector (DWORD based at 40:67) to point at
    	// the AP startup code prior to the [universal startup algorithm]."
    	outb(IO_RTC, 0xF);  // offset 0xF is shutdown code
    	outb(IO_RTC+1, 0x0A);
    	wrv = (uint16_t *)KADDR((0x40 << 4 | 0x67));  // Warm reset vector
    	wrv[0] = 0;
    	wrv[1] = addr >> 4;
    
    	// "Universal startup algorithm."
    	// Send INIT (level-triggered) interrupt to reset other CPU.
    	lapicw(ICRHI, apicid << 24);
    	lapicw(ICRLO, INIT | LEVEL | ASSERT);
    	microdelay(200);
    	lapicw(ICRLO, INIT | LEVEL);
    	microdelay(100);    // should be 10ms, but too slow in Bochs!
    
    	// Send startup IPI (twice!) to enter code.
    	// Regular hardware is supposed to only accept a STARTUP
    	// when it is in the halted state due to an INIT.  So the second
    	// should be ignored, but it is part of the official Intel algorithm.
    	// Bochs complains about the second one.  Too bad for Bochs.
    	for (i = 0; i < 2; i++) {
    		lapicw(ICRHI, apicid << 24);
    		lapicw(ICRLO, STARTUP | (addr >> 12));
    		microdelay(200);
    	}
    }
    
  3. In part C, we program LAPIC‘s built-in timer to trigger clock interrupts to support preemptive multitasking (see apic_init())

    void lapic_init(void)
    {
        if (!lapicaddr)
            return;
    
    // lapicaddr is the physical address of the LAPIC‘s 4KB MMIO
        // region. we get it by kern/pmap.c Map it in to virtual memory so we can access it.
        lapic = mmio_map_region(lapicaddr, 4096);
    
    // Enable local APIC; set spurious interrupt vector.
        lapicw(SVR, ENABLE | (IRQ_OFFSET + IRQ_SPURIOUS));
    
    // The timer repeatedly counts down at bus frequency
        // from lapic[TICR] and then issues an interrupt.  
        // If we cared more about precise timekeeping,
        // TICR would be calibrated using an external time source.
        lapicw(TDCR, X1);
        lapicw(TIMER, PERIODIC | (IRQ_OFFSET + IRQ_TIMER));
        lapicw(TICR, 10000000); 
    
    // Leave LINT0 of the BSP enabled so that it can get
        // interrupts from the 8259A chip.
        //
        // According to Intel MP Specification, the BIOS should initialize
        // BSP‘s local APIC in Virtual Wire Mode, in which 8259A‘s
        // INTR is virtually connected to BSP‘s LINTIN0. In this mode,
        // we do not need to program the IOAPIC.
        if (thiscpu != bootcpu)
            lapicw(LINT0, MASKED);
    
    // Disable NMI (LINT1) on all CPUs
        lapicw(LINT1, MASKED);
    
    // Disable performance counter overflow interrupts
        // on machines that provide that interrupt entry.
        if (((lapic[VER]>>16) & 0xFF) >= 4)
            lapicw(PCINT, MASKED);
    
    // Map error interrupt to IRQ_ERROR.
        lapicw(ERROR, IRQ_OFFSET + IRQ_ERROR);
    
    // Clear error status register (requires back-to-back writes).
        lapicw(ESR, 0);
        lapicw(ESR, 0);
    
    // Ack any outstanding interrupts.
        lapicw(EOI, 0);
    
    // Send an Init Level De-Assert to synchronize arbitration ID‘s.
        lapicw(ICRHI, 0);
        lapicw(ICRLO, BCAST | INIT | LEVEL);
        while(lapic[ICRLO] & DELIVS)
            ;
    
    // Enable interrupts on the APIC (but not on the processor).
        lapicw(TPR, 0);
    }
    

these three functions are important functions of LAPIC(APIC), but we don‘t use all now, we

MIT_xv6_Lab4_PartA

标签:++   int   halt   sch   flow   another   append   uri   clear   

原文地址:https://www.cnblogs.com/wevolf/p/13285682.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!