void virqmap_vgicd_changed_istatus_callback_handler( vmid_t vmid, uint32_t istatus, uint8_t word_offset ) { uint32_t cstatus; // changed bits only uint32_t minirq; int bit; minirq = word_offset * 32; /* irq range: 0~31 + word_offset * size_of_istatus_in_bits */ cstatus = old_vgicd_status[vmid][word_offset] ^ istatus; // find changed bits while(cstatus) { uint32_t virq; uint32_t pirq; bit = firstbit32(cstatus); virq = minirq + bit; pirq = virqmap_pirq(vmid, virq); if ( pirq != PIRQ_INVALID ) { /* changed bit */ if ( istatus & (1 << bit) ) { printh("[%s : %d] enabled irq num is %d\n", __FUNCTION__, __LINE__, bit + minirq); gic_test_configure_irq(pirq, GIC_INT_POLARITY_LEVEL, gic_cpumask_current(), GIC_INT_PRIORITY_DEFAULT ); } else { printh("[%s : %d] disabled irq num is %d\n",__FUNCTION__, __LINE__, bit + minirq); gic_disable_irq(pirq); } } else { printh( "WARNING: Ignoring virq %d for guest %d has no mapped pirq\n", virq, vmid ); } cstatus &= ~(1<< bit); } old_vgicd_status[vmid][word_offset] = istatus; }
hvmm_status_t gic_configure_irq(uint32_t irq, enum gic_int_polarity polarity, uint8_t cpumask, uint8_t priority) { hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR; HVMM_TRACE_ENTER(); if (irq < _gic.lines) { uint32_t icfg; volatile uint8_t *reg8; /* disable forwarding */ result = gic_disable_irq(irq); if (result == HVMM_STATUS_SUCCESS) { /* polarity: level or edge */ icfg = _gic.ba_gicd[GICD_ICFGR + irq / 16]; if (polarity == GIC_INT_POLARITY_LEVEL) icfg &= ~(2u << (2 * (irq % 16))); else icfg |= (2u << (2 * (irq % 16))); _gic.ba_gicd[GICD_ICFGR + irq / 16] = icfg; /* routing */ reg8 = (uint8_t *) &(_gic.ba_gicd[GICD_ITARGETSR]); reg8[irq] = cpumask; /* priority */ reg8 = (uint8_t *) &(_gic.ba_gicd[GICD_IPRIORITYR]); reg8[irq] = priority; /* enable forwarding */ result = gic_enable_irq(irq); } } else { uart_print("invalid irq:"); uart_print_hex32(irq); uart_print("\n\r"); result = HVMM_STATUS_UNSUPPORTED_FEATURE; } HVMM_TRACE_EXIT(); return result; }