khypervisor
v1
|
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 }