khypervisor  v1
virq.c
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines