void intr_enable() { uint8_t id = apic_get_id(); if (intr_sema[id] == 0) { kprintf("Bug: intr_enable!\n"); BREAK(); asm("hlt"); } if (--intr_sema[id] == 0) asm("sti"); }
ac_bool test_apic() { ac_bool error = AC_FALSE; initialize_apic(); ac_u64 msr_apic_base = get_msr(MSR_IA32_APIC_BASE); error |= AC_TEST(msr_apic_base != 0); ac_printf("msr_apic_base=0x%llx\n",msr_apic_base); ac_printf(" bsp=%d\n", AC_GET_BITS(ac_u32, msr_apic_base, 8, 1)); ac_printf(" extd=%d\n", AC_GET_BITS(ac_u32, msr_apic_base, 10, 1)); ac_printf(" e=%d\n", AC_GET_BITS(ac_u32, msr_apic_base, 11, 1)); ac_u64 phy_addr = apic_get_physical_addr(); ac_printf(" phy_addr=0x%llx\n", phy_addr); error |= AC_TEST(phy_addr != 0); ac_u32 local_id = apic_get_id(); ac_printf(" local_id=0x%x\n", local_id); return error; }
uint64_t task_switch(all_regs *r) { uint8_t id = apic_get_id(); if (curr[id] != 0) { // Если задача запускается, для нее подготовлены регистры if (curr[id]->state == TASK_STARTING) { curr[id]->state = TASK_RUNNING; curr[id]->r.reg1 = r->reg1; } else { memcpy(&(curr[id]->r), r, sizeof(all_regs)); curr[id]->state = TASK_ACTIVE; do { curr[id] = curr[id]->next; } while(curr[id]->state != TASK_ACTIVE); } // Стек, с которого будем восстанавливать регистры return &(curr[id]->r); } return r; }
void apic_init (struct cpu * core) { struct apic_dev * apic = NULL; ulong_t base_addr; uint32_t val; apic = (struct apic_dev*)malloc(sizeof(struct apic_dev)); if (!apic) { panic("Could not allocate apic struct\n"); } memset(apic, 0, sizeof(struct apic_dev)); core->apic = apic; if (!check_apic_avail()) { panic("No APIC found on core %u, dying\n", core->id); } /* In response to AMD erratum #663 * the damn thing may give us lint interrupts * even when we have them masked */ if (nk_is_amd() && cpuid_get_family() == 0x15) { APIC_DEBUG("Writing Bridge Ctrl MSR for AMD Errata #663\n"); msr_write(AMD_MSR_NBRIDGE_CTL, msr_read(AMD_MSR_NBRIDGE_CTL) | (1ULL<<23) | (1ULL<<54)); } base_addr = apic_get_base_addr(); /* idempotent when not compiled as HRT */ apic->base_addr = pa_to_va(base_addr); #ifndef NAUT_CONFIG_HVM_HRT if (core->is_bsp) { /* map in the lapic as uncacheable */ if (nk_map_page_nocache(apic->base_addr, PTE_PRESENT_BIT|PTE_WRITABLE_BIT, PS_4K) == -1) { panic("Could not map APIC\n"); } } #endif apic->version = apic_get_version(apic); apic->id = apic_get_id(apic); #ifndef NAUT_CONFIG_XEON_PHI if (apic->version < 0x10 || apic->version > 0x15) { panic("Unsupported APIC version (0x%1x)\n", (unsigned)apic->version); } #endif val = apic_read(apic, APIC_REG_LDR) & ~APIC_LDR_MASK; val |= SET_APIC_LOGICAL_ID(0); apic_write(apic, APIC_REG_LDR, val); apic_write(apic, APIC_REG_TPR, apic_read(apic, APIC_REG_TPR) & 0xffffff00); // accept all interrupts apic_write(apic, APIC_REG_LVTT, APIC_DEL_MODE_FIXED | APIC_LVT_DISABLED); // disable timer interrupts intially apic_write(apic, APIC_REG_LVTPC, APIC_DEL_MODE_FIXED | APIC_LVT_DISABLED | APIC_PC_INT_VEC); // disable perf cntr interrupts apic_write(apic, APIC_REG_LVTTHMR, APIC_DEL_MODE_FIXED | APIC_LVT_DISABLED | APIC_THRML_INT_VEC); // disable thermal interrupts /* do we have AMD extended LVT entries to deal with */ if (nk_is_amd() && amd_has_ext_lvt(apic)) { amd_setup_ext_lvt(apic); } /* mask 8259a interrupts */ apic_write(apic, APIC_REG_LVT0, APIC_DEL_MODE_EXTINT | APIC_LVT_DISABLED); /* only BSP takes NMI interrupts */ apic_write(apic, APIC_REG_LVT1, APIC_DEL_MODE_NMI | (core->is_bsp ? 0 : APIC_LVT_DISABLED)); apic_write(apic, APIC_REG_LVTERR, APIC_DEL_MODE_FIXED | APIC_ERROR_INT_VEC); // allow error interrupts // clear the ESR apic_write(apic, APIC_REG_ESR, 0u); apic_global_enable(); // assign interrupt handlers if (core->is_bsp) { if (register_int_handler(APIC_NULL_KICK_VEC, null_kick, apic) != 0) { panic("Could not register null kick interrupt handler\n"); } if (register_int_handler(APIC_SPUR_INT_VEC, spur_int_handler, apic) != 0) { panic("Could not register spurious interrupt handler\n"); } if (register_int_handler(APIC_ERROR_INT_VEC, error_int_handler, apic) != 0) { panic("Could not register spurious interrupt handler\n"); return; } /* we shouldn't ever get these, but just in case */ if (register_int_handler(APIC_PC_INT_VEC, pc_int_handler, apic) != 0) { panic("Could not register perf counter interrupt handler\n"); return; } if (register_int_handler(APIC_THRML_INT_VEC, thermal_int_handler, apic) != 0) { panic("Could not register thermal interrupt handler\n"); return; } if (register_int_handler(APIC_EXT_LVT_DUMMY_VEC, dummy_int_handler, apic) != 0) { panic("Could not register dummy ext lvt handler\n"); return; } } apic_assign_spiv(apic, APIC_SPUR_INT_VEC); /* turn it on */ apic_sw_enable(apic); /* pass in quantum as milliseconds */ #ifndef NAUT_CONFIG_XEON_PHI apic_timer_setup(apic, 1000/NAUT_CONFIG_HZ); #endif apic_dump(apic); }
void intr_disable() { uint8_t id = apic_get_id(); intr_sema[id]++; asm("cli"); }
void ipi_notify_init(void) { my_arch_id = apic_get_id(); // Publish the address of the notify page in the global kernel state global->notify[my_arch_id] = local_phys_to_gen_phys(mem_to_local_phys((lvaddr_t)my_notify_page)); }