khypervisor  v1
gic/gic.c
Go to the documentation of this file.
00001 #include "gic.h"
00002 #include "armv7_p15.h"
00003 #include "a15_cp15_sysregs.h"
00004 #include "smp.h"
00005 #include "context.h"
00006 #include "hvmm_trace.h"
00007 #include <gic_regs.h>
00008 #include "virqmap.h"
00009 #include "virq.h"
00010 #include "hvmm_types.h"
00011 
00012 #include <log/print.h>
00013 #include <log/uart_print.h>
00014 #include <config/cfg_platform.h>
00015 
00016 #define CBAR_PERIPHBASE_MSB_MASK    0x000000FF
00017 
00018 #define ARM_CPUID_CORTEXA15   0x412fc0f1
00019 
00020 #define MIDR_MASK_PPN       (0x0FFF <<4)
00021 #define MIDR_PPN_CORTEXA15  (0xC0F << 4)
00022 
00023 
00024 #define GIC_INT_PRIORITY_DEFAULT_WORD   ( (GIC_INT_PRIORITY_DEFAULT << 24 ) \
00025                                          |(GIC_INT_PRIORITY_DEFAULT << 16 ) \
00026                                          |(GIC_INT_PRIORITY_DEFAULT << 8 ) \
00027                                          |(GIC_INT_PRIORITY_DEFAULT ) )
00028 
00029 #define GIC_SIGNATURE_INITIALIZED   0x5108EAD7
00030 
00031 struct gic {
00032     uint32_t baseaddr;
00033     volatile uint32_t *ba_gicd;
00034     volatile uint32_t *ba_gicc;
00035     volatile uint32_t *ba_gich;
00036     volatile uint32_t *ba_gicv;
00037     volatile uint32_t *ba_gicvi;
00038     uint32_t lines;
00039     uint32_t cpus;
00040     gic_irq_handler_t handlers[GIC_NUM_MAX_IRQS];
00041     uint32_t initialized;
00042 };
00043 
00044 static struct gic _gic;
00045 
00046 static void gic_dump_registers(void)
00047 {
00048 
00049     uint32_t midr;
00050 
00051     HVMM_TRACE_ENTER();
00052 
00053     midr = read_midr();
00054     uart_print( "midr:"); uart_print_hex32(midr); uart_print("\n\r");
00055 
00056     if ( (midr & MIDR_MASK_PPN) == MIDR_PPN_CORTEXA15) {
00057         uint32_t value;
00058         uart_print( "cbar:"); uart_print_hex32(_gic.baseaddr); uart_print("\n\r");
00059         uart_print( "ba_gicd:"); uart_print_hex32((uint32_t)_gic.ba_gicd); uart_print("\n\r");
00060         uart_print( "ba_gicc:"); uart_print_hex32((uint32_t)_gic.ba_gicc); uart_print("\n\r");
00061         uart_print( "ba_gich:"); uart_print_hex32((uint32_t)_gic.ba_gich); uart_print("\n\r");
00062         uart_print( "ba_gicv:"); uart_print_hex32((uint32_t)_gic.ba_gicv); uart_print("\n\r");
00063         uart_print( "ba_gicvi:"); uart_print_hex32((uint32_t)_gic.ba_gicvi); uart_print("\n\r");
00064         value = _gic.ba_gicd[GICD_CTLR]; uart_print( "GICD_CTLR:"); uart_print_hex32(value); uart_print("\n\r");
00065         value = _gic.ba_gicd[GICD_TYPER]; uart_print( "GICD_TYPER:"); uart_print_hex32(value); uart_print("\n\r");
00066         value = _gic.ba_gicd[GICD_IIDR]; uart_print( "GICD_IIDR:"); uart_print_hex32(value); uart_print("\n\r");
00067     }
00068     HVMM_TRACE_EXIT();
00069 }
00070 
00071 
00072 static uint64_t gic_periphbase_pa(void)
00073 {
00074 // CBAR:   4,  c0,   0
00075 // MRC p15, 4, <Rt>, c15, c0, 0; Read Configuration Base Address Register
00076     uint64_t periphbase = (uint64_t) read_cbar();
00077     uint64_t pbmsb = periphbase & ((uint64_t)CBAR_PERIPHBASE_MSB_MASK);
00078     if ( pbmsb ) {
00079         periphbase &= ~ ((uint64_t)CBAR_PERIPHBASE_MSB_MASK);
00080         periphbase |= (pbmsb << 32);
00081     }
00082     
00083     return periphbase;
00084 }
00085 
00086 static hvmm_status_t gic_init_baseaddr(uint32_t *va_base)
00087 {
00088 // MIDR[15:4], CRn:c0, Op1:0, CRm:c0, Op2:0  == 0xC0F (Cortex-A15)
00089 // Cortex-A15 C15 System Control, C15 Registers
00090 // Name: Op1, CRm, Op2
00091     uint32_t midr;
00092     hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
00093 
00094     HVMM_TRACE_ENTER();
00095 
00096     midr = read_midr();
00097     uart_print( "midr:"); uart_print_hex32(midr); uart_print("\n\r");
00098 
00099     /* 
00100      * Note:
00101      * We currently support GICv2 with Cortex-A15 only. 
00102      * Other architectures with GICv2 support will be further listed and added for support later
00103      */
00104     if ( (midr & MIDR_MASK_PPN) == MIDR_PPN_CORTEXA15) {
00105         /* fall-back to periphbase addr from cbar */
00106         if ( va_base == 0 ) va_base = (uint32_t *) (uint32_t) (gic_periphbase_pa() & 0x00000000FFFFFFFFULL);
00107         _gic.baseaddr = (uint32_t) va_base;
00108         uart_print( "cbar:"); uart_print_hex32(_gic.baseaddr); uart_print("\n\r");
00109         _gic.ba_gicd = (uint32_t *) (_gic.baseaddr + GIC_OFFSET_GICD);
00110         _gic.ba_gicc = (uint32_t *) (_gic.baseaddr + GIC_OFFSET_GICC);
00111         _gic.ba_gich = (uint32_t *) (_gic.baseaddr + GIC_OFFSET_GICH);
00112         _gic.ba_gicv = (uint32_t *) (_gic.baseaddr + GIC_OFFSET_GICV);
00113         _gic.ba_gicvi = (uint32_t *) (_gic.baseaddr + GIC_OFFSET_GICVI);
00114 
00115         result = HVMM_STATUS_SUCCESS;
00116     } else {
00117         uart_print( "GICv2 Unsupported\n\r" );
00118         uart_print( "midr.ppn:"); uart_print_hex32(midr & MIDR_MASK_PPN); uart_print("\n\r");
00119 
00120         result = HVMM_STATUS_UNSUPPORTED_FEATURE;
00121     }
00122 
00123     HVMM_TRACE_EXIT();
00124     return result;
00125 }
00126 
00127 
00128 static hvmm_status_t gic_init_dist(void)
00129 {
00130     uint32_t type;
00131     int i;
00132     uint32_t cpumask;
00133 
00134     HVMM_TRACE_ENTER();
00135 
00136     /* Disable Distributor */
00137     _gic.ba_gicd[GICD_CTLR] = 0;
00138 
00139     type = _gic.ba_gicd[GICD_TYPER];
00140     _gic.lines = 32 * ((type & GICD_TYPE_LINES_MASK) + 1);
00141     _gic.cpus = 1 + ((type & GICD_TYPE_CPUS_MASK) >> GICD_TYPE_CPUS_SHIFT);
00142     uart_print( "GIC: lines:"); uart_print_hex32(_gic.lines ); 
00143     uart_print( " cpus:"); uart_print_hex32(_gic.cpus);
00144     uart_print( " IID:" ); uart_print_hex32(_gic.ba_gicd[GICD_IIDR]); uart_print("\n\r");
00145 
00146     /* Interrupt polarity for SPIs (Global Interrupts) active-low */
00147     for( i = 32; i < _gic.lines; i += 16 ) {
00148         _gic.ba_gicd[GICD_ICFGR + i / 16] = 0x0;
00149     }
00150 
00151     /* Default Priority for all Interrupts
00152      * Private/Banked interrupts will be configured separately 
00153      */
00154     for( i = 32; i < _gic.lines; i+= 4 ) {
00155         _gic.ba_gicd[GICD_IPRIORITYR + i / 4] = GIC_INT_PRIORITY_DEFAULT_WORD;
00156     }
00157 
00158     /* Disable all global interrupts. 
00159      * Private/Banked interrupts will be configured separately 
00160      */
00161     for( i = 32; i < _gic.lines; i+= 32 ) {
00162         _gic.ba_gicd[GICD_ICENABLER + i / 32] = 0xFFFFFFFF;
00163     }
00164 
00165     /* Route all global IRQs to this CPU */
00166     cpumask = 1 << smp_processor_id();
00167     cpumask |= cpumask << 8;
00168     cpumask |= cpumask << 16;
00169     for( i = 32; i < _gic.lines; i += 4 ) {
00170         _gic.ba_gicd[GICD_ITARGETSR + i / 4] = cpumask;
00171     }
00172 
00173 
00174     /* Enable Distributor */
00175     _gic.ba_gicd[GICD_CTLR] = GICD_CTLR_ENABLE;
00176     HVMM_TRACE_EXIT();
00177     return HVMM_STATUS_SUCCESS;
00178 }
00179 
00180 /* Initializes GICv2 CPU Interface */
00181 static hvmm_status_t gic_init_cpui(void)
00182 {
00183     hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
00184     int i;
00185 
00186     /* Disable forwarding PPIs(ID16~31) */
00187     _gic.ba_gicd[GICD_ICENABLER] = 0xFFFF0000;
00188     /* Enable forwarding SGIs(ID0~15) */
00189     _gic.ba_gicd[GICD_ISENABLER] = 0x0000FFFF;
00190     
00191     /* Default priority for SGIs and PPIs */
00192     for( i = 0; i < 32; i += 4 ) {
00193         _gic.ba_gicd[GICD_IPRIORITYR | i/4] = GIC_INT_PRIORITY_DEFAULT_WORD;
00194     }
00195 
00196     /* No Priority Masking: the lowest value as the threshold : 255 */
00197     _gic.ba_gicc[GICC_PMR] = 0xFF;
00198     _gic.ba_gicc[GICC_BPR] = 0x0;
00199 
00200     /* Enable signaling of interrupts and GICC_EOIR only drops priority */
00201     _gic.ba_gicc[GICC_CTLR] = GICC_CTL_ENABLE | GICC_CTL_EOI;
00202 
00203     result = HVMM_STATUS_SUCCESS;
00204     return result;
00205 }
00206 
00207 /* API functions */
00208 hvmm_status_t gic_enable_irq(uint32_t irq)
00209 {
00210     _gic.ba_gicd[GICD_ISENABLER + irq / 32] = (1u << (irq % 32));
00211     return HVMM_STATUS_SUCCESS;
00212 }
00213 
00214 hvmm_status_t gic_disable_irq(uint32_t irq)
00215 {
00216     _gic.ba_gicd[GICD_ICENABLER + irq / 32] = (1u << (irq % 32));
00217     return HVMM_STATUS_SUCCESS;
00218 }
00219 
00220 hvmm_status_t gic_deactivate_irq(uint32_t irq)
00221 {
00222     _gic.ba_gicc[GICC_DIR] = irq;
00223     return HVMM_STATUS_SUCCESS;
00224 }
00225 
00226 hvmm_status_t gic_test_set_irq_handler(int irq, gic_irq_handler_t handler, void *pdata )
00227 {
00228     hvmm_status_t result = HVMM_STATUS_BUSY;
00229     if ( irq < GIC_NUM_MAX_IRQS ) {
00230         _gic.handlers[irq] = handler;
00231         result = HVMM_STATUS_SUCCESS;
00232     }
00233     return result;
00234 }
00235 
00236 volatile uint32_t *gic_vgic_baseaddr(void)
00237 {
00238     if ( _gic.initialized != GIC_SIGNATURE_INITIALIZED ) {
00239         HVMM_TRACE_ENTER();
00240         uart_print("gic: ERROR - not initialized\n\r");
00241         HVMM_TRACE_EXIT();
00242     }
00243 
00244     return _gic.ba_gich;
00245 }
00246 
00247 hvmm_status_t gic_init(void)
00248 {
00249     hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
00250     int i;
00251 
00252     HVMM_TRACE_ENTER();
00253 
00254     for( i = 0; i < GIC_NUM_MAX_IRQS; i++) {
00255         _gic.handlers[i] = 0;
00256     }
00257     
00258     /*
00259      * Determining VA of GIC base adddress has not been defined yet. Let is use the PA for the time being
00260      */
00261     result = gic_init_baseaddr((void*)CFG_GIC_BASE_PA);
00262 
00263     if ( result == HVMM_STATUS_SUCCESS ) {
00264         gic_dump_registers();
00265     }
00266 
00267     /*
00268      * Initialize and Enable GIC Distributor
00269      */
00270     if ( result == HVMM_STATUS_SUCCESS ) {
00271         result = gic_init_dist();
00272     }
00273 
00274     /*
00275      * Initialize and Enable GIC CPU Interface for this CPU
00276      */
00277     if ( result == HVMM_STATUS_SUCCESS ) {
00278         result = gic_init_cpui();
00279     }
00280     if ( result == HVMM_STATUS_SUCCESS ) {
00281         _gic.initialized = GIC_SIGNATURE_INITIALIZED;
00282     }
00283 
00284     HVMM_TRACE_EXIT();
00285     return result;
00286 }
00287 
00288 /*
00289  * example: gic_test_configure_irq( 26, 
00290                                     GIC_INT_POLARITY_LEVEL, 
00291                                     (1u << smp_processor_id()), 
00292                                     GIC_INT_PRIORITY_DEFAULT );
00293  */
00294 hvmm_status_t gic_test_configure_irq(uint32_t irq, gic_int_polarity_t polarity,  uint8_t cpumask, uint8_t priority)
00295 {
00296     hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
00297 
00298     HVMM_TRACE_ENTER();
00299     if ( irq < _gic.lines ) {
00300         uint32_t icfg;
00301         volatile uint8_t *reg8;
00302         /* disable forwarding */
00303         result = gic_disable_irq( irq );
00304 
00305         if ( result == HVMM_STATUS_SUCCESS ) {
00306 
00307             /* polarity: level or edge */
00308             icfg = _gic.ba_gicd[GICD_ICFGR + irq / 16];
00309             if ( polarity == GIC_INT_POLARITY_LEVEL ) {
00310                 icfg &= ~( 2u << (2 * (irq % 16)) );
00311             } else {
00312                 icfg |= ( 2u << (2 * (irq % 16)) );
00313             }
00314             _gic.ba_gicd[GICD_ICFGR + irq / 16] = icfg;
00315 
00316             /* routing */
00317         
00318             reg8 = (uint8_t *) &(_gic.ba_gicd[GICD_ITARGETSR]);
00319             reg8[irq] = cpumask;
00320 
00321             /* priority */
00322             reg8 = (uint8_t *) &(_gic.ba_gicd[GICD_IPRIORITYR]);
00323             reg8[irq] = priority;
00324 
00325             /* enable forwarding */
00326             result = gic_enable_irq( irq );
00327         }
00328     } else {
00329         uart_print( "invalid irq:"); uart_print_hex32(irq); uart_print("\n\r");
00330         result = HVMM_STATUS_UNSUPPORTED_FEATURE;
00331     }
00332 
00333     HVMM_TRACE_EXIT();
00334     return result;
00335 }
00336 
00337 void gic_interrupt(int fiq, void *pregs)
00338 {
00339     /*
00340      * 1. ACK - CPU Interface - GICC_IAR read
00341      * 2. Completion - CPU Interface - GICC_EOIR
00342      * 2.1 Deactivation - CPU Interface - GICC_DIR
00343      */
00344     uint32_t iar;
00345 
00346     uint32_t irq;
00347     struct arch_regs *regs = pregs;
00348     const struct virqmap_entry *virq_entry;
00349 
00350     /* ACK */
00351     iar = _gic.ba_gicc[GICC_IAR];
00352     irq = iar & GICC_IAR_INTID_MASK;
00353     if ( irq < _gic.lines ) {
00354         virq_entry = virqmap_for_pirq(irq);
00355 
00356         /* ISR */
00357         printh( "ISR(irq):%x\n", irq);
00358 
00359         /* IRQ INJECTION */
00360         if(virq_entry != VIRQMAP_ENTRY_NOTFOUND) { 
00361 
00362             /* priority drop only for hanlding irq in guest */
00363             _gic.ba_gicc[GICC_EOIR] = irq;
00364             virq_inject(virq_entry->vmid, virq_entry->virq, irq, 1);
00365 
00366         } else {
00367 
00368             if ( _gic.handlers[irq] ) {
00369                 _gic.handlers[irq]( irq, regs, 0 );
00370             }
00371 
00372             /* Completion & Deactivation */
00373             _gic.ba_gicc[GICC_EOIR] = irq;
00374             _gic.ba_gicc[GICC_DIR] = irq;
00375         }
00376     } else {
00377         printh( "gic:no pending irq:%x\n", irq);
00378     }
00379 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines