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