khypervisor  v1
virqmap.c
Go to the documentation of this file.
00001 #include <k-hypervisor-config.h>
00002 #include "virqmap.h"
00003 #include "context.h"
00004 #include "hvmm_types.h"
00005 #include "vdev/vdev_gicd.h"
00006 #include <asm-arm_inline.h>
00007 
00008 #include <config/cfg_platform.h>
00009 #include <log/print.h>
00010 
00011 /* return the bit position of the first bit set from msb
00012  * for example, firstbit32(0x7F = 111 1111) returns 7
00013  */
00014 #define firstbit32(word) ( 31 - asm_clz(word) )
00015 #define NUM_MAX_VIRQS   128
00016 #define NUM_STATUS_WORDS    (NUM_MAX_VIRQS / 32)
00017 
00018 static struct virqmap_entry _virqmap[GIC_NUM_MAX_IRQS];
00019 static uint32_t old_vgicd_status[NUM_GUESTS_STATIC][NUM_STATUS_WORDS] = {{0,}, };        // old status
00020 
00021 /* 
00022  * Creates a mapping table between PIRQ and VIRQ.vmid/pirq/coreid.
00023  * Mapping of between pirq and virq is hard-coded.
00024  */
00025 hvmm_status_t virqmap_init(void) 
00026 {
00027     // TODO(wonseok): read file and initialize the mapping.
00028     HVMM_TRACE_ENTER();
00029     int i;
00030 
00031     for (i = 0; i < GIC_NUM_MAX_IRQS; i++) {
00032         _virqmap[i].vmid = VMID_INVALID;
00033         _virqmap[i].virq = 0;
00034     }
00035 
00036     // NOTE(wonseok): referenced by https://github.com/kesl/khypervisor/wiki/Hardware-Resources-of-Guest-Linux-on-FastModels-RTSM_VE-Cortex-A15x1
00037     CFG_GUEST0_VIRQMAP(_virqmap);
00038     CFG_GUEST1_VIRQMAP(_virqmap);
00039 
00040     vgicd_set_callback_changed_istatus(&virqmap_vgicd_changed_istatus_callback_handler);
00041 
00042     HVMM_TRACE_EXIT();
00043 
00044     return HVMM_STATUS_SUCCESS;
00045 }
00046 
00047 const struct virqmap_entry *virqmap_for_pirq(uint32_t pirq)
00048 {
00049     const struct virqmap_entry * result = VIRQMAP_ENTRY_NOTFOUND;
00050 
00051     if ( _virqmap[pirq].vmid != VMID_INVALID) {
00052         result = &_virqmap[pirq];
00053     }
00054     return result;
00055 }
00056 
00057 uint32_t virqmap_pirq(vmid_t vmid, uint32_t virq)
00058 {
00059     uint32_t pirq = PIRQ_INVALID;
00060 
00061     /* FIXME: This is ridiculously inefficient to loop up to GIC_NUM_MAX_IRQS */
00062     int i;
00063     for (i = 0; i < GIC_NUM_MAX_IRQS; i++) {
00064         if ( _virqmap[i].vmid == vmid && _virqmap[i].virq == virq ) {
00065             pirq = i;
00066             break;
00067         }
00068     }
00069     return pirq;
00070 }
00071 
00072 
00073 void virqmap_vgicd_changed_istatus_callback_handler( vmid_t vmid, uint32_t istatus, uint8_t word_offset )
00074 {
00075     uint32_t cstatus;                          // changed bits only
00076     uint32_t minirq;
00077     int bit;
00078 
00079     minirq = word_offset * 32;                 /* irq range: 0~31 + word_offset * size_of_istatus_in_bits */
00080     cstatus = old_vgicd_status[vmid][word_offset] ^ istatus;   // find changed bits
00081 
00082     while(cstatus) {
00083         uint32_t virq;
00084         uint32_t pirq;
00085         bit = firstbit32(cstatus);
00086 
00087         virq = minirq + bit;
00088         pirq = virqmap_pirq(vmid, virq);
00089 
00090         if ( pirq != PIRQ_INVALID ) {
00091             /* changed bit */
00092             if ( istatus & (1 << bit) ) {
00093                 printh("[%s : %d] enabled irq num is %d\n", __FUNCTION__, __LINE__, bit + minirq);
00094                 gic_test_configure_irq(pirq, GIC_INT_POLARITY_LEVEL, gic_cpumask_current(), GIC_INT_PRIORITY_DEFAULT );
00095             } else {
00096                 printh("[%s : %d] disabled irq num is %d\n",__FUNCTION__, __LINE__, bit + minirq);
00097                 gic_disable_irq(pirq);
00098             }
00099         } else {
00100             printh( "WARNING: Ignoring virq %d for guest %d has no mapped pirq\n", virq, vmid );
00101         }
00102         cstatus &= ~(1<< bit);
00103     }
00104     old_vgicd_status[vmid][word_offset] = istatus;
00105 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines