khypervisor
v1
|
00001 #include "virq.h" 00002 #include <k-hypervisor-config.h> 00003 #include <hvmm_trace.h> 00004 #include <vgic.h> 00005 #include <gic.h> 00006 #include <slotpirq.h> 00007 00008 #include <log/print.h> 00009 00010 #define VIRQ_MIN_VALID_PIRQ 16 00011 #define VIRQ_NUM_MAX_PIRQS 1024 00012 00013 #define VALID_PIRQ(pirq) (pirq >= VIRQ_MIN_VALID_PIRQ && pirq < VIRQ_NUM_MAX_PIRQS) 00014 00015 #define VIRQ_MAX_ENTRIES 128 00016 00017 struct virq_entry { 00018 uint32_t pirq; 00019 uint32_t virq; 00020 uint8_t hw; 00021 uint8_t valid; 00022 }; 00023 00024 static struct virq_entry _guest_virqs[NUM_GUESTS_STATIC][VIRQ_MAX_ENTRIES + 1]; 00025 00026 hvmm_status_t virq_inject(vmid_t vmid, uint32_t virq, uint32_t pirq, uint8_t hw) 00027 { 00028 hvmm_status_t result = HVMM_STATUS_BUSY; 00029 int i; 00030 struct virq_entry *q = &_guest_virqs[vmid][0]; 00031 int slot = slotvirq_getslot(vmid, virq); 00032 if ( slot == SLOT_INVALID ) { 00033 /* Inject only the same virq is not present in a slot */ 00034 for( i = 0; i < VIRQ_MAX_ENTRIES; i++ ) { 00035 if ( q[i].valid == 0 ) { 00036 q[i].pirq = pirq; 00037 q[i].virq = virq; 00038 q[i].hw = hw; 00039 q[i].valid = 1; 00040 result = HVMM_STATUS_SUCCESS; 00041 break; 00042 } 00043 } 00044 printh( "virq: queueing virq %d pirq %d to vmid %d %s\n", virq, pirq, vmid, result == HVMM_STATUS_SUCCESS ? "done" : "failed"); 00045 } else { 00046 printh( "virq: rejected queueing duplicated virq %d pirq %d to vmid %d %s\n", virq, pirq, vmid); 00047 } 00048 return result; 00049 } 00050 00051 static void virq_flush(vmid_t vmid) 00052 { 00053 /* Actual injection of queued VIRQs takes place here */ 00054 00055 int i; 00056 int count = 0; 00057 struct virq_entry *entries = &_guest_virqs[vmid][0]; 00058 00059 for( i = 0; i < VIRQ_MAX_ENTRIES; i++) { 00060 if ( entries[i].valid ) { 00061 uint32_t slot; 00062 if ( entries[i].hw ) { 00063 slot = vgic_inject_virq_hw(entries[i].virq, VIRQ_STATE_PENDING, GIC_INT_PRIORITY_DEFAULT, entries[i].pirq); 00064 if ( slot != VGIC_SLOT_NOTFOUND ) { 00065 slotpirq_set( vmid, slot, entries[i].pirq ); 00066 } 00067 } else { 00068 slot = vgic_inject_virq_sw(entries[i].virq, VIRQ_STATE_PENDING, GIC_INT_PRIORITY_DEFAULT, smp_processor_id(), 1); 00069 } 00070 00071 if (slot == VGIC_SLOT_NOTFOUND ) { 00072 break; 00073 } 00074 00075 slotvirq_set( vmid, slot, entries[i].virq ); 00076 00077 /* Forget */ 00078 entries[i].valid = 0; 00079 00080 count++; 00081 } 00082 } 00083 if ( count > 0 ) { 00084 printh( "virq: injected %d virqs to vmid %d \n", count, vmid ); 00085 } 00086 } 00087 00088 hvmm_status_t virq_init(void) 00089 { 00090 int i, j; 00091 00092 for( i = 0; i < NUM_GUESTS_STATIC; i++) { 00093 for( j = 0; j < (VIRQ_MAX_ENTRIES + 1); j++ ) { 00094 _guest_virqs[i][j].valid = 0; 00095 } 00096 } 00097 00098 vgic_setcallback_virq_flush(&virq_flush); 00099 return HVMM_STATUS_SUCCESS; 00100 } 00101