⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lapic.c

📁 类unix x86平台的简单操作系统
💻 C
字号:
#include "types.h"#include "mp.h"#include "defs.h"#include "param.h"#include "x86.h"#include "traps.h"#include "mmu.h"#include "proc.h"enum {  // Local APIC registers  LAPIC_ID  = 0x0020,   // ID  LAPIC_VER = 0x0030,   // Version  LAPIC_TPR = 0x0080,   // Task Priority  LAPIC_APR = 0x0090,   // Arbitration Priority  LAPIC_PPR = 0x00A0,   // Processor Priority  LAPIC_EOI = 0x00B0,   // EOI  LAPIC_LDR = 0x00D0,   // Logical Destination  LAPIC_DFR = 0x00E0,   // Destination Format  LAPIC_SVR = 0x00F0,   // Spurious Interrupt Vector  LAPIC_ISR = 0x0100,   // Interrupt Status (8 registers)  LAPIC_TMR = 0x0180,   // Trigger Mode (8 registers)  LAPIC_IRR = 0x0200,   // Interrupt Request (8 registers)  LAPIC_ESR = 0x0280,   // Error Status  LAPIC_ICRLO = 0x0300, // Interrupt Command  LAPIC_ICRHI = 0x0310, // Interrupt Command [63:32]  LAPIC_TIMER = 0x0320, // Local Vector Table 0 (TIMER)  LAPIC_PCINT = 0x0340, // Performance Counter LVT  LAPIC_LINT0 = 0x0350, // Local Vector Table 1 (LINT0)  LAPIC_LINT1 = 0x0360, // Local Vector Table 2 (LINT1)  LAPIC_ERROR = 0x0370, // Local Vector Table 3 (ERROR)  LAPIC_TICR = 0x0380,  // Timer Initial Count  LAPIC_TCCR = 0x0390,  // Timer Current Count  LAPIC_TDCR = 0x03E0,  // Timer Divide Configuration};enum {  // LAPIC_SVR  LAPIC_ENABLE  = 0x00000100,   // Unit Enable  LAPIC_FOCUS   = 0x00000200,   // Focus Processor Checking Disable};enum {  // LAPIC_ICRLO  // [14] IPI Trigger Mode Level (RW)  LAPIC_DEASSERT = 0x00000000,  // Deassert level-sensitive interrupt  LAPIC_ASSERT  = 0x00004000,   // Assert level-sensitive interrupt  // [17:16] Remote Read Status  LAPIC_INVALID = 0x00000000,   // Invalid  LAPIC_WAIT    = 0x00010000,   // In-Progress  LAPIC_VALID   = 0x00020000,   // Valid  // [19:18] Destination Shorthand  LAPIC_FIELD   = 0x00000000,   // No shorthand  LAPIC_SELF    = 0x00040000,   // Self is single destination  LAPIC_ALLINC  = 0x00080000,   // All including self  LAPIC_ALLEXC  = 0x000C0000,   // All Excluding self};enum {  // LAPIC_ESR  LAPIC_SENDCS  = 0x00000001,     // Send CS Error  LAPIC_RCVCS   = 0x00000002,     // Receive CS Error  LAPIC_SENDACCEPT = 0x00000004,  // Send Accept Error  LAPIC_RCVACCEPT = 0x00000008,   // Receive Accept Error  LAPIC_SENDVECTOR = 0x00000020,  // Send Illegal Vector  LAPIC_RCVVECTOR = 0x00000040,   // Receive Illegal Vector  LAPIC_REGISTER = 0x00000080,    // Illegal Register Address};enum {  // LAPIC_TIMER  // [17] Timer Mode (RW)  LAPIC_ONESHOT = 0x00000000,   // One-shot  LAPIC_PERIODIC = 0x00020000,  // Periodic  // [19:18] Timer Base (RW)  LAPIC_CLKIN   = 0x00000000,   // use CLKIN as input  LAPIC_TMBASE  = 0x00040000,   // use TMBASE  LAPIC_DIVIDER = 0x00080000,   // use output of the divider};enum {  // LAPIC_TDCR  LAPIC_X2 = 0x00000000,        // divide by 2  LAPIC_X4 = 0x00000001,        // divide by 4  LAPIC_X8 = 0x00000002,        // divide by 8  LAPIC_X16 = 0x00000003,       // divide by 16  LAPIC_X32 = 0x00000008,       // divide by 32  LAPIC_X64 = 0x00000009,       // divide by 64  LAPIC_X128 = 0x0000000A,      // divide by 128  LAPIC_X1 = 0x0000000B,        // divide by 1};uint *lapicaddr;static intlapic_read(int r){  return *(lapicaddr+(r/sizeof(*lapicaddr)));}static voidlapic_write(int r, int data){  *(lapicaddr+(r/sizeof(*lapicaddr))) = data;}voidlapic_timerinit(void){  if(!lapicaddr)     return;  lapic_write(LAPIC_TDCR, LAPIC_X1);  lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |	      (IRQ_OFFSET + IRQ_TIMER));  lapic_write(LAPIC_TCCR, 10000000);  lapic_write(LAPIC_TICR, 10000000);}voidlapic_timerintr(void){  if(lapicaddr)     lapic_write(LAPIC_EOI, 0);}voidlapic_init(int c){  uint r, lvt;  if(!lapicaddr)     return;  lapic_write(LAPIC_DFR, 0xFFFFFFFF);    // Set dst format register  r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID  lapic_write(LAPIC_LDR, (1<<r)<<24);    // Set logical dst register to r  lapic_write(LAPIC_TPR, 0xFF);          // No interrupts for now  // Enable APIC  lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS));  // In virtual wire mode, set up the LINT0 and LINT1 as follows:  lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT);  lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI);  lapic_write(LAPIC_EOI, 0); // Ack any outstanding interrupts.  lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF;  if(lvt >= 4)    lapic_write(LAPIC_PCINT, APIC_IMASK);  lapic_write(LAPIC_ERROR, IRQ_OFFSET+IRQ_ERROR);  lapic_write(LAPIC_ESR, 0);  lapic_read(LAPIC_ESR);  // Issue an INIT Level De-Assert to synchronise arbitration ID's.  lapic_write(LAPIC_ICRHI, 0);  lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL|                           LAPIC_DEASSERT|APIC_INIT);  while(lapic_read(LAPIC_ICRLO) & APIC_DELIVS)    ;}voidlapic_enableintr(void){  if(lapicaddr)    lapic_write(LAPIC_TPR, 0);}voidlapic_disableintr(void){  if(lapicaddr)    lapic_write(LAPIC_TPR, 0xFF);}voidlapic_eoi(void){  if(lapicaddr)    lapic_write(LAPIC_EOI, 0);}intcpu(void){  int x;  if(lapicaddr)     x = (lapic_read(LAPIC_ID)>>24) & 0xFF;  else     x = 0;  return x;}voidlapic_startap(uchar apicid, int v){  int crhi, i;  volatile int j = 0;  crhi = apicid<<24;  lapic_write(LAPIC_ICRHI, crhi);  lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|                           LAPIC_ASSERT|APIC_INIT);  while(j++ < 10000) {;}  lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|                           LAPIC_DEASSERT|APIC_INIT);  while(j++ < 1000000) {;}  // in p9 code, this was i < 2, which is what the spec says on page B-3  for(i = 0; i < 1; i++){    lapic_write(LAPIC_ICRHI, crhi);    lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_EDGE|APIC_STARTUP|(v/4096));    while(j++ < 100000) {;}  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -