static void __local_apic_clear(void) { uint32_t max_lvt; uint32_t v; apic_lvt_error_t lvt_error=local_apic->lvt_error; apic_lvt_timer_t lvt_timer=local_apic->lvt_timer; apic_lvt_lint_t lvt_lint=local_apic->lvt_lint0; apic_lvt_pc_t lvt_pc=local_apic->lvt_pc; max_lvt=__get_maxlvt(); if(max_lvt>=3) { v=0xfe; lvt_error.vector=v; lvt_error.mask |= (1 << 0); local_apic->lvt_error.reg=lvt_error.reg; } /* mask timer and LVTs*/ lvt_timer.mask = 0x1; local_apic->lvt_timer.reg=lvt_timer.reg; lvt_lint.mask=0x1; local_apic->lvt_lint0.reg = lvt_lint.reg; lvt_lint=local_apic->lvt_lint1; lvt_lint.mask=0x1; local_apic->lvt_lint1.reg = lvt_lint.reg; if(max_lvt>=4) { lvt_pc.mask = 0x1; local_apic->lvt_pc.reg=lvt_pc.reg; } }
static int __local_apic_check(void) { uint32_t v0; /* version check */ v0=get_apic_version(); v0=(v0)&0xffu; if(v0==0x0 || v0==0xff) return -1; /*check for lvt*/ v0=__get_maxlvt(); if(v0<0x02 || v0==0xff) return -1; return 0; }
void __local_apic_clear(void) { uint32_t max_lvt; uint32_t v; max_lvt=__get_maxlvt(); if(max_lvt>=3) { v=0xfe; local_apic->lvt_error.vector=v; local_apic->lvt_error.mask |= (1 << 0); } /* mask timer and LVTs*/ local_apic->lvt_timer.mask |= (1 << 0); local_apic->lvt_lint0.mask |= (1 << 0); local_apic->lvt_lint1.mask |= (1 << 0); if(max_lvt>=4) local_apic->lvt_pc.mask |= (1 << 0); }
static int __local_apic_check(void) { uint32_t v0,v1; struct __local_apic_version_t *ver=(struct __local_apic_version_t *)&(local_apic->version); v0=local_apic->version.version; ver->version=0x0; v1=local_apic->version.version; if(v0!=v1) return -1; /* version check */ v0=(v1)&0xffu; if(v0==0x0 || v0==0xff) return -1; /*check for lvt*/ v1=__get_maxlvt(); if(v1<0x02 || v1==0xff) return -1; return 0; }
static int __local_apic_init(bool msgout) { uint32_t v; int i=0,l; apic_lvt_lint_t lvt_lint; apic_icr1_t icr1; if (msgout) { kprintf("APIC: Checking APIC is present ... "); if(__local_apic_check()<0) { kprintf("FAIL\n"); return -1; } else{ kprintf("OK\n"); } } enable_l_apic_in_msr(); v=get_apic_version(); if (msgout) kprintf("APIC: APIC version: %d apic id:%x\n",v,get_local_apic_id()); /* first we're need to clear APIC to avoid magical results */ __local_apic_clear(); __disable_apic(); set_apic_dfr_mode(0xf); kprintf(" APIC id:%d destination id :%d \n",get_local_apic_id(),(1 << (__apics_number & 7))); set_apic_ldr_logdest(1 << (__apics_number & 7)); __apics_number++; apic_set_task_priority(0); /* clear bits for interrupts - can be filled up to other os */ for(i=7;i>=0;i--){ v=local_apic->isr[i].bits; for(l=31;l>=0;l--) if(v & (1 << l)) local_apic_send_eoi(); } set_apic_spurious_vector(0xff); __enable_apic(); /* set nil vectors */ __set_lvt_lint_vector(0,0x34); __set_lvt_lint_vector(1,0x35); /*set mode#7 extINT for lint0*/ lvt_lint=local_apic->lvt_lint0; lvt_lint.tx_mode=0x7; lvt_lint.mask=1; lvt_lint.tx_status = 0x0; lvt_lint.polarity = LEVEL_DEASSERT; lvt_lint.trigger = TRIG_EDGE; local_apic->lvt_lint0.reg=lvt_lint.reg; /*set mode#4 NMI for lint1*/ lvt_lint=local_apic->lvt_lint1; lvt_lint.tx_mode=0x4; lvt_lint.mask=1; lvt_lint.tx_status = 0x0; lvt_lint.polarity = LEVEL_DEASSERT; lvt_lint.trigger = TRIG_EDGE; local_apic->lvt_lint1.reg=lvt_lint.reg; /* ok, now we're need to set esr vector to 0xfe */ local_apic->lvt_error.vector = 0xfe; /*enable to receive errors*/ if(__get_maxlvt()>3) local_apic->esr.tx_cs_err = 0x0; /* set icr1 registers*/ icr1=local_apic->icr1; icr1.tx_mode=TXMODE_INIT; icr1.rx_mode=DMODE_PHY; icr1.level=0x0; icr1.shorthand=0x2; icr1.trigger=0x1; local_apic->icr1.reg=icr1.reg; // set internal apic error interrupt vector *(uint32_t*)((uint64_t)local_apic + 0x370) = 200; return 0; }