|
khypervisor
v1
|
#include "vdev_gicd.h"#include <context.h>#include <gic_regs.h>#include <vdev.h>#include <log/print.h>
Go to the source code of this file.
| #define VGICD_IIDR_DEFAULT (0x43B) |
Definition at line 10 of file vdev_gicd.c.
| #define VGICD_ITLINESNUM 128 |
Definition at line 8 of file vdev_gicd.c.
| #define VGICD_NUM_IENABLER (VGICD_ITLINESNUM/32) |
Definition at line 12 of file vdev_gicd.c.
| #define VGICD_NUM_IGROUPR (VGICD_ITLINESNUM/32) |
Definition at line 11 of file vdev_gicd.c.
| #define VGICD_TYPER_DEFAULT ((VGICD_ITLINESNUM >> 5) - 1) |
Definition at line 9 of file vdev_gicd.c.
| static hvmm_status_t access_handler | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 96 of file vdev_gicd.c.
{
printh( "%s: %s offset:%d value:%x\n", __FUNCTION__, write ? "write" : "read", offset, write ? *pvalue : (uint32_t) pvalue );
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
uint8_t offsetidx = (uint8_t) ((offset & 0xF00) >> 8);
result = _handler_map[offsetidx].handler(write, offset, pvalue, access_size);
return result;
}
| static hvmm_status_t handler_000 | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 108 of file vdev_gicd.c.
{
//CTLR; /*0x000 RW*/
//TYPER; /* RO*/
//IIDR; /* RO*/
//IGROUPR[32]; /* 0x080 ~ 0x0FF */
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid = context_current_vmid();
struct gicd_regs *regs = &_regs[vmid];
uint32_t woffset = offset/4;
switch(woffset) {
case GICD_CTLR: /* RW */
if ( write ) {
regs->CTLR = *pvalue;
} else {
*pvalue = regs->CTLR;
}
result = HVMM_STATUS_SUCCESS;
break;
case GICD_TYPER: /* RO */
if ( write == 0 ) {
*pvalue = VGICD_TYPER_DEFAULT;
result = HVMM_STATUS_SUCCESS;
}
break;
case GICD_IIDR: /* RO */
if ( write == 0 ) {
*pvalue = VGICD_IIDR_DEFAULT;
result = HVMM_STATUS_SUCCESS;
}
break;
default: /* RW GICD_IGROUPR */
{
int igroup = woffset - GICD_IGROUPR;
if ( igroup >= 0 && igroup < VGICD_NUM_IGROUPR ) {
if ( write ) {
regs->IGROUPR[igroup] = *pvalue;
} else {
*pvalue = regs->IGROUPR[igroup];
}
result = HVMM_STATUS_SUCCESS;
}
}
break;
}
if ( result != HVMM_STATUS_SUCCESS ) {
printh("vgicd: invalid access offset:%x write:%d\n", offset, write );
}
return result;
}

| static hvmm_status_t handler_F00 | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 412 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
printh( "vgicd:%s: not implemented\n", __FUNCTION__ );
return result;
}
| static hvmm_status_t handler_ICFGR | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 375 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid;
struct gicd_regs *regs;
uint32_t *preg;
vmid = context_current_vmid();
regs = &_regs[vmid];
/* FIXME: Support 8/16/32bit access */
offset >>= 2;
preg = &(regs->ICFGR[offset - GICD_ICFGR]);
if ( write ) {
*preg = *pvalue;
} else {
*pvalue = *preg;
}
result = HVMM_STATUS_SUCCESS;
return result;
}

| static hvmm_status_t handler_IPRIORITYR | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 307 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid;
struct gicd_regs *regs;
uint32_t *preg;
vmid = context_current_vmid();
regs = &_regs[vmid];
/* FIXME: Support 8/16/32bit access */
offset >>= 2;
preg = &(regs->ICFGR[offset - GICD_IPRIORITYR]);
if ( write ) {
*preg = *pvalue;
} else {
*pvalue = *preg;
}
result = HVMM_STATUS_SUCCESS;
return result;
}

| static hvmm_status_t handler_ISCACTIVER | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 300 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
printh( "vgicd:%s: not implemented\n", __FUNCTION__ );
return result;
}
| static hvmm_status_t handler_ISCENABLER | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 179 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid = context_current_vmid();
struct gicd_regs *regs = &_regs[vmid];
uint32_t *preg_s;
uint32_t *preg_c;
if( write && *pvalue == 0) {
/* Writes 0 -> Has no effect. */
result = HVMM_STATUS_SUCCESS;
return result;
}
preg_s = &(regs->ISCENABLER[(offset >> 2 ) - GICD_ISENABLER]);
preg_c = &(regs->ISCENABLER[(offset >> 2 ) - GICD_ICENABLER]);
if ( access_size == VDEV_ACCESS_WORD ) {
if ( (offset >> 2 ) < (GICD_ISENABLER + VGICD_NUM_IENABLER) ) {
/* ISENABLER */
if ( write ) {
*preg_s |= *pvalue;
vgicd_changed_istatus(vmid, *preg_s, (offset >> 2) - GICD_ISENABLER );
} else {
*pvalue = *preg_s;
}
result = HVMM_STATUS_SUCCESS;
} else if ( (offset >> 2 ) >= GICD_ICENABLER && (offset >> 2 ) < (GICD_ICENABLER + VGICD_NUM_IENABLER) ) {
/* ICENABLER */
if ( write ){
*preg_c &= ~(*pvalue);
vgicd_changed_istatus(vmid, *preg_c, (offset >> 2) - GICD_ICENABLER );
} else {
*pvalue = *preg_c;
}
result = HVMM_STATUS_SUCCESS;
}
} else if ( access_size == VDEV_ACCESS_HWORD ) {
if ( (offset >> 2) < ( GICD_ISENABLER + VGICD_NUM_IENABLER) ) {
uint16_t *preg_s16 = (uint16_t *)preg_s;
preg_s16 += (offset & 0x3) >> 1;
if ( write ) {
*preg_s16 |= (uint16_t)(*pvalue & 0xFFFF);
vgicd_changed_istatus(vmid, *preg_s, (offset >> 2) - GICD_ISENABLER );
} else {
*pvalue = (uint32_t)*preg_s16;
}
result = HVMM_STATUS_SUCCESS;
} else if ( (offset >> 2 ) >= GICD_ICENABLER && (offset >> 2 ) < (GICD_ICENABLER + VGICD_NUM_IENABLER) ) {
uint16_t *preg_c16 = (uint16_t *)preg_c;
preg_c16 += (offset & 0x3) >> 1;
if( write ){
*preg_c16 &= ~((uint16_t)(*pvalue & 0xFFFF));
vgicd_changed_istatus(vmid, *preg_c, (offset >> 2) - GICD_ICENABLER );
} else {
*pvalue = (uint32_t)*preg_c16;
}
result = HVMM_STATUS_SUCCESS;
}
} else if ( access_size == VDEV_ACCESS_BYTE ) {
if ( (offset >> 2) < ( GICD_ISENABLER + VGICD_NUM_IENABLER) ) {
uint8_t *preg_s8 = (uint8_t *)preg_s;
preg_s8 += (offset & 0x3);
if ( write ) {
*preg_s8 |= (uint8_t)(*pvalue & 0xFF);
vgicd_changed_istatus(vmid, *preg_s, (offset >> 2) - GICD_ISENABLER );
} else {
*pvalue = (uint32_t)*preg_s8;
}
result = HVMM_STATUS_SUCCESS;
} else if( ( offset >> 2 ) >= GICD_ICENABLER && ( offset >> 2 ) < (GICD_ICENABLER + VGICD_NUM_IENABLER) ) {
uint8_t *preg_c8 = (uint8_t *)preg_c;
preg_c8 += ( offset & 0x3 );
if ( write ){
*preg_c8 &= ~((uint8_t)(*pvalue & 0xFF));
vgicd_changed_istatus(vmid, *preg_c, (offset >> 2) - GICD_ICENABLER );
} else {
*pvalue = (uint32_t)*preg_c8;
}
result = HVMM_STATUS_SUCCESS;
}
}
return result;
}

| static hvmm_status_t handler_ISCPENDR | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 264 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid = context_current_vmid();
struct gicd_regs *regs = &_regs[vmid];
uint32_t *preg_s;
uint32_t *preg_c;
preg_s = &(regs->ISPENDR[(offset >> 2 ) - GICD_ISPENDR]);
preg_c = &(regs->ISPENDR[(offset >> 2 ) - GICD_ICPENDR]);
offset >>= 2;
if ( access_size == VDEV_ACCESS_WORD ) {
if ( (offset >> 2 ) < (GICD_ISPENDR + VGICD_NUM_IENABLER) ) {
/* ISPEND */
if ( write ) {
*preg_s |= *pvalue;
} else {
*pvalue = *preg_s;
}
result = HVMM_STATUS_SUCCESS;
} else if ( (offset >> 2 ) >= GICD_ICPENDR && (offset >> 2 ) < (GICD_ICPENDR + VGICD_NUM_IENABLER) ) {
/* ICPEND */
if ( write ){
*preg_c &= ~(*pvalue);
} else {
*pvalue = *preg_c;
}
result = HVMM_STATUS_SUCCESS;
}
}
printh( "vgicd:%s: not implemented\n", __FUNCTION__ );
return result;
}

| static hvmm_status_t handler_ITARGETSR | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 330 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
vmid_t vmid;
struct gicd_regs *regs;
uint32_t *preg;
vmid = context_current_vmid();
regs = &_regs[vmid];
preg = &(regs->ITARGETSR[(offset >>2) - GICD_ITARGETSR]);
if ( access_size == VDEV_ACCESS_WORD ) {
offset >>= 2;
if ( write ) {
if ( offset > (GICD_ITARGETSR + 7) ) {
/* RO: ITARGETSR0 ~ 7 */
*preg = *pvalue;
}
} else {
*pvalue = *preg;
}
} else if ( access_size == VDEV_ACCESS_HWORD ) {
uint16_t *preg16 = (uint16_t *) preg;
preg16 += (offset & 0x3) >> 1;
if ( write ) {
if ( (offset >>2) > (GICD_ITARGETSR + 7) )
*preg16 = (uint16_t) (*pvalue & 0xFFFF);
} else {
*pvalue = (uint32_t) *preg16;
}
} else if ( access_size == VDEV_ACCESS_BYTE ) {
uint8_t *preg8 = (uint8_t *) preg;
preg8 += (offset & 0x3);
if ( write ) {
if ( (offset >>2) > (GICD_ITARGETSR + 7) )
*preg8 = (uint8_t) (*pvalue & 0xFF);
} else {
*pvalue = (uint32_t) *preg8;
}
}
result = HVMM_STATUS_SUCCESS;
return result;
}

| static hvmm_status_t handler_NSACR | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 405 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
printh( "vgicd:%s: not implemented\n", __FUNCTION__ );
return result;
}
| static hvmm_status_t handler_PPISPISR_CA15 | ( | uint32_t | write, |
| uint32_t | offset, | ||
| uint32_t * | pvalue, | ||
| vdev_access_size_t | access_size | ||
| ) | [static] |
Definition at line 398 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BAD_ACCESS;
printh( "vgicd:%s: not implemented\n", __FUNCTION__ );
return result;
}
| hvmm_status_t vdev_gicd_init | ( | uint32_t | base_addr | ) |
Definition at line 433 of file vdev_gicd.c.
{
hvmm_status_t result = HVMM_STATUS_BUSY;
vdev_gicd_reset_values();
_vdev_info.name = "vgicd";
_vdev_info.base = base_addr;
_vdev_info.size = 4096;
_vdev_info.handler = access_handler;
result = vdev_reg_device(&_vdev_info);
if ( result == HVMM_STATUS_SUCCESS ) {
printh("%s: vdev registered:'%s'\n", __FUNCTION__, _vdev_info.name);
} else {
printh("%s: Unable to register vdev:'%s' code=%x\n", __FUNCTION__, _vdev_info.name, result);
}
return result;
}

| static void vdev_gicd_reset_values | ( | void | ) | [static] |
Definition at line 419 of file vdev_gicd.c.
{
int i;
for (i = 0; i < NUM_GUESTS_STATIC; i++ ) {
/* ITARGETS[0~ 7], CPU Targets are set to 0, due to current single-core support design */
int j = 0;
for ( j = 0; j < 7; j++ ) {
_regs[i].ITARGETSR[j] = 0;
}
}
}
| void vgicd_changed_istatus | ( | vmid_t | vmid, |
| uint32_t | istatus, | ||
| uint8_t | word_offset | ||
| ) |
Definition at line 171 of file vdev_gicd.c.
{
if ( _cb_changed_istatus != 0 ) {
_cb_changed_istatus( vmid, istatus, word_offset );
}
}
| void vgicd_set_callback_changed_istatus | ( | vgicd_changed_istatus_callback_t | callback | ) |
Definition at line 166 of file vdev_gicd.c.
{
_cb_changed_istatus = callback;
}
Definition at line 71 of file vdev_gicd.c.
struct gicd_handler_entry _handler_map[0x10] [static] |
{
{ 0x00, handler_000 },
{ 0x01, handler_ISCENABLER },
{ 0x02, handler_ISCPENDR },
{ 0x03, handler_ISCACTIVER },
{ 0x04, handler_IPRIORITYR },
{ 0x05, handler_IPRIORITYR },
{ 0x06, handler_IPRIORITYR },
{ 0x07, handler_IPRIORITYR },
{ 0x08, handler_ITARGETSR },
{ 0x09, handler_ITARGETSR },
{ 0x0A, handler_ITARGETSR },
{ 0x0B, handler_ITARGETSR },
{ 0x0C, handler_ICFGR },
{ 0x0D, handler_PPISPISR_CA15 },
{ 0x0E, handler_NSACR },
{ 0x0F, handler_F00 },
}
Definition at line 76 of file vdev_gicd.c.
struct gicd_regs _regs[NUM_GUESTS_STATIC] [static] |
Definition at line 74 of file vdev_gicd.c.
vdev_info_t _vdev_info [static] |
Definition at line 73 of file vdev_gicd.c.
1.7.6.1