khypervisor  v1
Data Structures | Defines | Functions | Variables
gic/vgic.c File Reference
#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>
Include dependency graph for vgic.c:

Go to the source code of this file.

Data Structures

struct  vgic

Defines

#define __VGIC_DISABLE_TRACE__
#define VGIC_SIMULATE_HWVIRQ
#define VGIC_MAINTENANCE_INTERRUPT_IRQ   25
#define VGIC_MAX_LISTREGISTERS   VGIC_NUM_MAX_SLOTS
#define VGIC_SIGNATURE_INITIALIZED   0x45108EAD
#define VGIC_READY()   (_vgic.initialized == VGIC_SIGNATURE_INITIALIZED)

Functions

hvmm_status_t vgic_injection_enable (uint8_t enable)
static uint32_t vgic_find_free_slot (void)
static uint32_t vgic_is_free_slot (uint32_t slot)
static void _vgic_dump_status (void)
static void _vgic_dump_regs (void)
static void _vgic_isr_maintenance_irq (int irq, void *pregs, void *pdata)
hvmm_status_t vgic_enable (uint8_t enable)
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)
uint32_t vgic_inject_virq_hw (uint32_t virq, virq_state_t state, uint32_t priority, uint32_t pirq)
uint32_t vgic_inject_virq_sw (uint32_t virq, virq_state_t state, uint32_t priority, uint32_t cpuid, uint8_t maintenance)
hvmm_status_t vgic_maintenance_irq_enable (uint8_t enable)
static uint64_t _vgic_valid_lr_mask (uint32_t num_lr)
hvmm_status_t vgic_setcallback_virq_flush (void(*callback)(vmid_t vmid))
hvmm_status_t vgic_init (void)
hvmm_status_t vgic_init_status (struct vgic_status *status, vmid_t vmid)
hvmm_status_t vgic_save_status (struct vgic_status *status, vmid_t vmid)
hvmm_status_t vgic_restore_status (struct vgic_status *status, vmid_t vmid)
hvmm_status_t vgic_flush_virqs (vmid_t vmid)

Variables

static struct vgic _vgic
static void(* _cb_virq_flush )(vmid_t vmid)=0

Define Documentation

Definition at line 14 of file vgic.c.

Definition at line 29 of file vgic.c.

Definition at line 31 of file vgic.c.

#define VGIC_READY ( )    (_vgic.initialized == VGIC_SIGNATURE_INITIALIZED)

Definition at line 33 of file vgic.c.

#define VGIC_SIGNATURE_INITIALIZED   0x45108EAD

Definition at line 32 of file vgic.c.

Definition at line 15 of file vgic.c.


Function Documentation

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
}

Here is the call graph for this function:

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();
}

Here is the call graph for this function:

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;
}

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;
}

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_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;
}

Here is the call graph for this function:

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;
}

Here is the call graph for this function:

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;
}

Here is the call graph for this function:

Definition at line 298 of file vgic.c.

{
    uint32_t hcr;

    hcr = read_hcr();
    if ( enable ) {
        if ( (hcr & HCR_VI) == 0 ) {
            hcr |= HCR_VI;
            write_hcr(hcr);
        }
    } else {
        if ( hcr & HCR_VI ) {
            hcr &= ~(HCR_VI);
            write_hcr(hcr);
        }
    }

    hcr = read_hcr();
    printh( " updated hcr: %x\n", hcr);
    return HVMM_STATUS_SUCCESS;
}
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;
}

Here is the call graph for this function:

Definition at line 406 of file vgic.c.

Here is the call graph for this function:

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;
}

Here is the call graph for this function:

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;
}

Here is the call graph for this function:

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;
}

Variable Documentation

void(* _cb_virq_flush)(vmid_t vmid)=0 [static]

Definition at line 80 of file vgic.c.

struct vgic _vgic [static]

Definition at line 79 of file vgic.c.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines