|
khypervisor
v1
|
#include <vgic.h>#include <hvmm_trace.h>#include <armv7_p15.h>#include <gic.h>#include <gic_regs.h>#include <slotpirq.h>#include <context.h>#include <k-hypervisor-config.h>#include <asm-arm_inline.h>#include <log/print.h>
Go to the source code of this file.
| #define __VGIC_DISABLE_TRACE__ |
| #define VGIC_MAINTENANCE_INTERRUPT_IRQ 25 |
| #define VGIC_READY | ( | ) | (_vgic.initialized == VGIC_SIGNATURE_INITIALIZED) |
| #define VGIC_SIGNATURE_INITIALIZED 0x45108EAD |
| #define VGIC_SIMULATE_HWVIRQ |
| static void _vgic_dump_regs | ( | void | ) | [static] |
Definition at line 162 of file vgic.c.
{
#ifndef __VGIC_DISABLE_TRACE__
/*
* HCR * VTR * VMCR * MISR * EISR0 * EISR1 * ELSR0 * ELSR1 * APR * LR0~n
*/
int i;
HVMM_TRACE_ENTER();
uart_print(" hcr:"); uart_print_hex32( _vgic.base[GICH_HCR] ); uart_print("\n\r");
uart_print(" vtr:"); uart_print_hex32( _vgic.base[GICH_VTR] ); uart_print("\n\r");
uart_print(" vmcr:"); uart_print_hex32( _vgic.base[GICH_VMCR] ); uart_print("\n\r");
uart_print(" misr:"); uart_print_hex32( _vgic.base[GICH_MISR] ); uart_print("\n\r");
uart_print("eisr0:"); uart_print_hex32( _vgic.base[GICH_EISR0] ); uart_print("\n\r");
uart_print("eisr1:"); uart_print_hex32( _vgic.base[GICH_EISR1] ); uart_print("\n\r");
uart_print("elsr0:"); uart_print_hex32( _vgic.base[GICH_ELSR0] ); uart_print("\n\r");
uart_print("elsr1:"); uart_print_hex32( _vgic.base[GICH_ELSR1] ); uart_print("\n\r");
uart_print(" apr:"); uart_print_hex32( _vgic.base[GICH_APR] ); uart_print("\n\r");
uart_print(" LR:\n\r");
for( i = 0; i < _vgic.num_lr; i++ ) {
if ( vgic_is_free_slot(i) != i ) {
uart_print_hex32( _vgic.base[GICH_LR + i] ); uart_print(" - "); uart_print_hex32(i); uart_print("\n\r");
}
}
HVMM_TRACE_EXIT();
#endif
}

| static void _vgic_dump_status | ( | void | ) | [static] |
Definition at line 133 of file vgic.c.
{
/*
* === VGIC Status Summary ===
* Initialized: Yes
* Num ListRegs: n
* Hypervisor Control
* - Enabled: Yes
* - EOICount:
* - Underflow:
* - LRENPIE:
* - NPIE:
* - VGrp0EIE:
* - VGrp0DIE:
* - VGrp1EIE:
* - VGrp1DIE:
* VGIC Type
* - ListRegs:
* - PREbits:
* - PRIbits:
* Virtual Machine Control
* -
*/
uart_print("=== VGIC Status ===\n\r");
uart_print(" Initialized:"); uart_print( ( VGIC_READY() ? "Yes" : "No" ) ); uart_print("\n\r");
uart_print(" Num ListRegs:"); uart_print_hex32( _vgic.num_lr ); uart_print("\n\r");
uart_print(" LR_MASK:"); uart_print_hex64( _vgic.valid_lr_mask ); uart_print("\n\r");
}
| static void _vgic_isr_maintenance_irq | ( | int | irq, |
| void * | pregs, | ||
| void * | pdata | ||
| ) | [static] |
Definition at line 192 of file vgic.c.
{
HVMM_TRACE_ENTER();
if ( _vgic.base[GICH_MISR] & GICH_MISR_EOI ) {
/* clean up invalid entries from List Registers */
uint32_t eisr = _vgic.base[GICH_EISR0];
uint32_t slot;
uint32_t pirq;
vmid_t vmid;
vmid = context_current_vmid();
while(eisr) {
slot = (31 - asm_clz(eisr));
eisr &= ~(1 << slot);
_vgic.base[GICH_LR + slot] = 0;
/* deactivate associated pirq at the slot */
pirq = slotpirq_get(vmid, slot);
if ( pirq != PIRQ_INVALID ) {
gic_deactivate_irq(pirq);
slotpirq_clear(vmid, slot);
printh( "vgic: deactivated pirq %d at slot %d\n", pirq, slot );
} else {
printh( "vgic: deactivated virq at slot %d\n", slot );
}
slotvirq_clear(vmid, slot);
}
eisr = _vgic.base[GICH_EISR1];
while(eisr) {
slot = (31 - asm_clz(eisr));
eisr &= ~(1 << slot);
_vgic.base[GICH_LR + slot + 32] = 0;
/* deactivate associated pirq at the slot */
pirq = slotpirq_get(vmid, slot + 32);
if ( pirq != PIRQ_INVALID ) {
gic_deactivate_irq(pirq);
slotpirq_clear(vmid, slot + 32);
printh( "vgic: deactivated pirq %d at slot %d\n", pirq, slot );
} else {
printh( "vgic: deactivated virq at slot %d\n", slot );
}
slotvirq_clear(vmid, slot);
}
}
if ( _vgic.base[GICH_MISR] & GICH_MISR_NP ) {
/* No pending virqs, no need to keep vgic enabled */
_vgic.base[GICH_HCR] &= ~(GICH_HCR_NPIE);
printh( "vgic: no pending virqs, disabling no pending interrupt\n" );
{
int i;
printh( "vgic: active virqs...\n" );
for (i = 0; i < _vgic.num_lr; i++ ) {
if ( _vgic.base[GICH_LR + i] & 0x20000000 ) {
printh( "- lr[%d]: %x\n", i, _vgic.base[GICH_LR + i] );
}
}
}
}
{
uint64_t elsr;
elsr = _vgic.base[GICH_ELSR1];
elsr <<= 32;
elsr |= _vgic.base[GICH_ELSR0];
if ( ((~elsr) & _vgic.valid_lr_mask) == 0 ) {
/* No valid interrupt */
vgic_enable(0);
vgic_injection_enable(0);
printh( "vgic: no valid virqs, disabling vgic\n" );
} else {
printh( "vgic:MISR:%x ELSR0:%x ELSR1:%x\n",
_vgic.base[GICH_MISR],
_vgic.base[GICH_ELSR0],
_vgic.base[GICH_ELSR1]);
}
}
HVMM_TRACE_EXIT();
}

| static uint64_t _vgic_valid_lr_mask | ( | uint32_t | num_lr | ) | [static] |
Definition at line 425 of file vgic.c.
{
uint64_t mask_valid_lr = 0xFFFFFFFFFFFFFFFFULL;
if ( num_lr < VGIC_MAX_LISTREGISTERS ) {
mask_valid_lr >>= num_lr;
mask_valid_lr <<= num_lr;
mask_valid_lr = ~mask_valid_lr;
}
return mask_valid_lr;
}
| hvmm_status_t vgic_enable | ( | uint8_t | enable | ) |
Definition at line 277 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
if ( VGIC_READY() ) {
if ( enable ) {
uint32_t hcr = _vgic.base[GICH_HCR];
hcr |= GICH_HCR_EN | GICH_HCR_NPIE;
_vgic.base[GICH_HCR] = hcr;
} else {
_vgic.base[GICH_HCR] &= ~(GICH_HCR_EN | GICH_HCR_NPIE);
}
result = HVMM_STATUS_SUCCESS;
}
return result;
}
| static uint32_t vgic_find_free_slot | ( | void | ) | [static] |
Definition at line 82 of file vgic.c.
{
uint32_t slot;
uint32_t shift = 0;
slot = _vgic.base[GICH_ELSR0];
if ( slot == 0 && _vgic.num_lr > 32 ) {
/* first 32 slots are occupied, try the later */
slot = _vgic.base[GICH_ELSR1];
shift = 32;
}
if ( slot ) {
slot &= -(slot);
slot = (31 - asm_clz(slot));
slot += shift;
} else {
/* 64 slots are fully occupied */
slot = VGIC_SLOT_NOTFOUND;
}
return slot;
}
| hvmm_status_t vgic_flush_virqs | ( | vmid_t | vmid | ) |
Definition at line 530 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_IGNORED;
if ( _cb_virq_flush != 0 ) {
_cb_virq_flush(vmid);
result = HVMM_STATUS_SUCCESS;
}
return result;
}
| hvmm_status_t vgic_init | ( | void | ) |
Definition at line 451 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
HVMM_TRACE_ENTER();
_vgic.base = gic_vgic_baseaddr();
_vgic.num_lr = (_vgic.base[GICH_VTR] & GICH_VTR_LISTREGS_MASK) + 1;
_vgic.valid_lr_mask = _vgic_valid_lr_mask( _vgic.num_lr );
_vgic.initialized = VGIC_SIGNATURE_INITIALIZED;
vgic_maintenance_irq_enable(1);
slotpirq_init();
result = HVMM_STATUS_SUCCESS;
_vgic_dump_status();
_vgic_dump_regs();
HVMM_TRACE_EXIT();
return result;
}

| hvmm_status_t vgic_init_status | ( | struct vgic_status * | status, |
| vmid_t | vmid | ||
| ) |
Definition at line 475 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_SUCCESS;
int i;
status->hcr = 0;
status->apr = 0;
status->vmcr = 0;
status->saved_once = 0;
for( i = 0; i < _vgic.num_lr; i++) {
status->lr[i] = 0;
}
return result;
}
| uint32_t vgic_inject_virq | ( | uint32_t | virq, |
| uint32_t | slot, | ||
| virq_state_t | state, | ||
| uint32_t | priority, | ||
| uint8_t | hw, | ||
| uint32_t | physrc, | ||
| uint8_t | maintenance | ||
| ) |
Definition at line 332 of file vgic.c.
{
uint32_t physicalid;
uint32_t lr_desc;
HVMM_TRACE_ENTER();
physicalid = (hw ? physrc : (maintenance << 9) | (physrc & 0x7)) << GICH_LR_PHYSICALID_SHIFT;
physicalid &= GICH_LR_PHYSICALID_MASK;
lr_desc = (GICH_LR_HW_MASK & (hw << GICH_LR_HW_SHIFT) ) |
/* (GICH_LR_GRP1_MASK & (1 << GICH_LR_GRP1_SHIFT) )| */
(GICH_LR_STATE_MASK & (state << GICH_LR_STATE_SHIFT) ) |
(GICH_LR_PRIORITY_MASK & ( (priority >> 3) << GICH_LR_PRIORITY_SHIFT) ) |
physicalid |
(GICH_LR_VIRTUALID_MASK & virq );
slot = vgic_is_free_slot( slot );
HVMM_TRACE_HEX32("lr_desc:", lr_desc);
HVMM_TRACE_HEX32("free slot:", slot);
if ( slot != VGIC_SLOT_NOTFOUND ) {
_vgic.base[GICH_LR + slot] = lr_desc;
vgic_injection_enable(1);
vgic_enable(1);
}
_vgic_dump_regs();
HVMM_TRACE_EXIT();
return slot;
}

| uint32_t vgic_inject_virq_hw | ( | uint32_t | virq, |
| virq_state_t | state, | ||
| uint32_t | priority, | ||
| uint32_t | pirq | ||
| ) |
Definition at line 371 of file vgic.c.
{
uint32_t slot = VGIC_SLOT_NOTFOUND;
HVMM_TRACE_ENTER();
slot = vgic_find_free_slot();
HVMM_TRACE_HEX32("slot:", slot);
if ( slot != VGIC_SLOT_NOTFOUND ) {
#ifdef VGIC_SIMULATE_HWVIRQ
slot = vgic_inject_virq( virq, slot, state, priority, 0, 0, 1 );
#else
slot = vgic_inject_virq( virq, slot, state, priority, 1, pirq, 0 );
#endif
}
HVMM_TRACE_EXIT();
return slot;
}

| uint32_t vgic_inject_virq_sw | ( | uint32_t | virq, |
| virq_state_t | state, | ||
| uint32_t | priority, | ||
| uint32_t | cpuid, | ||
| uint8_t | maintenance | ||
| ) |
Definition at line 390 of file vgic.c.
{
uint32_t slot = VGIC_SLOT_NOTFOUND;
HVMM_TRACE_ENTER();
slot = vgic_find_free_slot();
HVMM_TRACE_HEX32("slot:", slot);
if ( slot != VGIC_SLOT_NOTFOUND ) {
slot = vgic_inject_virq( virq, slot, state, priority, 0, cpuid, maintenance );
}
HVMM_TRACE_EXIT();
return slot;
}

| hvmm_status_t vgic_injection_enable | ( | uint8_t | enable | ) |
| static uint32_t vgic_is_free_slot | ( | uint32_t | slot | ) | [static] |
Definition at line 114 of file vgic.c.
{
uint32_t free_slot = VGIC_SLOT_NOTFOUND;
if ( slot < 32 ) {
if ( _vgic.base[GICH_ELSR0] & (1 << slot) )
free_slot = slot;
} else {
if ( _vgic.base[GICH_ELSR1] & (1 << (slot - 32)) )
free_slot = slot;
}
if ( free_slot != slot ) {
free_slot = vgic_find_free_slot();
}
return free_slot;
}

| hvmm_status_t vgic_maintenance_irq_enable | ( | uint8_t | enable | ) |
Definition at line 406 of file vgic.c.
{
uint32_t irq = VGIC_MAINTENANCE_INTERRUPT_IRQ;
HVMM_TRACE_ENTER();
if ( enable ) {
gic_test_set_irq_handler( irq, &_vgic_isr_maintenance_irq, 0 );
gic_test_configure_irq( irq,
GIC_INT_POLARITY_LEVEL,
gic_cpumask_current(),
GIC_INT_PRIORITY_DEFAULT );
} else {
gic_test_set_irq_handler( irq, 0, 0 );
gic_disable_irq( irq );
}
HVMM_TRACE_EXIT();
return HVMM_STATUS_SUCCESS;
}

| hvmm_status_t vgic_restore_status | ( | struct vgic_status * | status, |
| vmid_t | vmid | ||
| ) |
Definition at line 509 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
int i;
for( i = 0; i < _vgic.num_lr; i++) {
_vgic.base[GICH_LR + i] = status->lr[i];
}
_vgic.base[GICH_APR] = status->apr;
_vgic.base[GICH_VMCR] = status->vmcr;
_vgic.base[GICH_HCR] = status->hcr;
/* Inject queued virqs to the next guest */
vgic_flush_virqs(vmid);
_vgic_dump_regs();
result = HVMM_STATUS_SUCCESS;
return result;
}

| hvmm_status_t vgic_save_status | ( | struct vgic_status * | status, |
| vmid_t | vmid | ||
| ) |
Definition at line 491 of file vgic.c.
{
hvmm_status_t result = HVMM_STATUS_SUCCESS;
int i;
for( i = 0; i < _vgic.num_lr; i++ ) {
status->lr[i] = _vgic.base[GICH_LR + i];
}
status->hcr = _vgic.base[GICH_HCR];
status->apr = _vgic.base[GICH_APR];
status->vmcr = _vgic.base[GICH_VMCR];
status->saved_once = VGIC_SIGNATURE_INITIALIZED;
vgic_enable(0);
return result;
}

| hvmm_status_t vgic_setcallback_virq_flush | ( | void(*)(vmid_t vmid) | callback | ) |
Definition at line 440 of file vgic.c.
{
_cb_virq_flush = callback;
if ( _cb_virq_flush == 0 ) {
printh( "vgic: virq_flush() cleared\n" );
} else {
printh( "vgic: virq_flush() set to function at %x\n", (uint32_t) _cb_virq_flush );
}
return HVMM_STATUS_SUCCESS;
}
void(* _cb_virq_flush)(vmid_t vmid)=0 [static] |
1.7.6.1