X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fapic.c;h=e143990f8c31e546c0cde2523401657896c413e7;hb=bd18ee6111c1b75fa0bbd670307d1ec1c622f91f;hp=f899419bcba5bc301d5ab177d3ca718e036e50f5;hpb=af10c7cdec94c879b207983a60581feae911546b;p=palacios.git diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index f899419..e143990 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -19,28 +19,108 @@ #include +#include #include #include #define BASE_ADDR_MSR 0x0000001B #define DEFAULT_BASE_ADDR 0xfee00000 - -struct apic_base_addr_reg { - uchar_t rsvd; - uint_t bsc : 1; - uint_t rsvd2 : 2; - uint_t apic_enable : 1; - ullong_t base_addr : 40; - uint_t rsvd3 : 12; +#define APIC_ID_OFFSET 0x020 +#define APIC_VERSION_OFFSET 0x030 +#define TPR_OFFSET 0x080 +#define APR_OFFSET 0x090 +#define PPR_OFFSET 0x0a0 +#define EOI_OFFSET 0x0b0 +#define REMOTE_READ_OFFSET 0x0c0 +#define LDR_OFFSET 0x0d0 +#define DFR_OFFSET 0x0e0 +#define SPURIOUS_INT_VEC_OFFSET 0x0f0 +#define ISR_OFFSET 0x100 // 0x100 - 0x170 +#define TMR_OFFSET 0x180 // 0x180 - 0x1f0 +#define IRR_OFFSET 0x200 // 0x200 - 0x270 +#define ESR_OFFSET 0x280 +#define INT_CMD_LO_OFFSET 0x300 +#define INT_CMD_HI_OFFSET 0x310 +#define TMR_LOC_VEC_TBL_OFFSET 0x320 +#define THERM_LOC_VEC_TBL_OFFSET 0x330 +#define PERF_CTR_LOC_VEC_TBL_OFFSET 0x340 +#define LINT0_VEC_TBL_OFFSET 0x350 +#define LINT1_VEC_TBL_OFFSET 0x360 +#define ERR_VEC_TBL_OFFSET 0x370 +#define TMR_INIT_CNT_OFFSET 0x380 +#define TMR_CUR_CNT_OFFSET 0x390 +#define TMR_DIV_CFG_OFFSET 0x3e0 +#define EXT_APIC_FEATURE_OFFSET 0x400 +#define EXT_APIC_CMD_OFFSET 0x410 +#define SEOI_OFFSET 0x420 +#define IER_OFFSET 0x480 // 0x480 - 0x4f0 +#define EXT_INT_LOC_VEC_TBL_OFFSET 0x500 // 0x500 - 0x530 + + +struct apic_base_addr_msr { + union { + uint64_t val; + struct { + uchar_t rsvd; + uint_t cpu_core : 1; + uint_t rsvd2 : 2; + uint_t apic_enable : 1; + ullong_t base_addr : 40; + uint_t rsvd3 : 12; + } __attribute__((packed)); + } __attribute__((packed)); } __attribute__((packed)); + + + struct apic_state { addr_t base_addr; - v3_msr_t base_addr_reg; + /* MSRs */ + v3_msr_t base_addr_msr; + + + /* memory map registers */ + + struct lapic_id_reg lapic_id; + struct apic_ver_reg apic_ver; + struct ext_apic_ctrl_reg ext_apic_ctrl; + struct local_vec_tbl_reg local_vec_tbl; + struct tmr_vec_tbl_reg tmr_vec_tbl; + struct div_cfg_reg div_cfg; + struct lint_vec_tbl_reg lint_vec_tbl; + struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl; + struct therm_loc_vec_tbl_reg therm_loc_vec_tbl; + struct err_vec_tbl_reg err_vec_tbl; + struct err_status_reg err_status; + struct spurious_int_reg spurious_int; + struct int_cmd_reg int_cmd; + struct loc_dst_reg loc_dst; + struct dst_fmt_reg dst_fmt; + struct arb_prio_reg arb_prio; + struct task_prio_reg task_prio; + struct proc_prio_reg proc_prio; + struct ext_apic_feature_reg ext_apic_feature; + struct spec_eoi_reg spec_eoi; + + + uint32_t tmr_cur_cnt_reg; + uint32_t tmr_init_cnt_reg; + + + + uint32_t rem_rd_data; + + uchar_t int_req_reg[32]; + uchar_t int_svc_reg[32]; + uchar_t int_en_reg[32]; + uchar_t trig_mode_reg[32]; + uint32_t eoi; + }; @@ -48,7 +128,7 @@ struct apic_state { static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) { struct vm_device * dev = (struct vm_device *)priv_data; struct apic_state * apic = (struct apic_state *)dev->private_data; - PrintDebug("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_reg.hi, apic->base_addr_reg.lo); + PrintDebug("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo); return -1; } @@ -65,14 +145,102 @@ static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) { static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { - PrintDebug("Read from apic address space\n"); - return -1; + struct vm_device * dev = (struct vm_device *)priv_data; + struct apic_state * apic = (struct apic_state *)dev->private_data; + addr_t reg_addr = guest_addr - apic->base_addr; + + if (length != 4) { + PrintError("Invalid apic readlength\n"); + return -1; + } + + switch (reg_addr) { + case APIC_ID_OFFSET: + case APIC_VERSION_OFFSET: + case TPR_OFFSET: + case APR_OFFSET: + case PPR_OFFSET: + case EOI_OFFSET: + case REMOTE_READ_OFFSET: + case LDR_OFFSET: + case DFR_OFFSET: + case SPURIOUS_INT_VEC_OFFSET: + case ISR_OFFSET: + case TMR_OFFSET: + case IRR_OFFSET: + case ESR_OFFSET: + case INT_CMD_LO_OFFSET: + case INT_CMD_HI_OFFSET: + case TMR_LOC_VEC_TBL_OFFSET: + case THERM_LOC_VEC_TBL_OFFSET: + case PERF_CTR_LOC_VEC_TBL_OFFSET: + case LINT0_VEC_TBL_OFFSET: + case LINT1_VEC_TBL_OFFSET: + case ERR_VEC_TBL_OFFSET: + case TMR_INIT_CNT_OFFSET: + case TMR_CUR_CNT_OFFSET: + case TMR_DIV_CFG_OFFSET: + case EXT_APIC_FEATURE_OFFSET: + case EXT_APIC_CMD_OFFSET: + case SEOI_OFFSET: + case IER_OFFSET: + case EXT_INT_LOC_VEC_TBL_OFFSET: + default: + PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr); + return -1; + } + return length; } static int apic_write(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { PrintDebug("Write to apic address space\n"); - return -1; + struct vm_device * dev = (struct vm_device *)priv_data; + struct apic_state * apic = (struct apic_state *)dev->private_data; + addr_t reg_addr = guest_addr - apic->base_addr; + + if (length != 4) { + PrintError("Invalid apic write length\n"); + return -1; + } + + switch (reg_addr) { + case APIC_ID_OFFSET: + case APIC_VERSION_OFFSET: + case TPR_OFFSET: + case APR_OFFSET: + case PPR_OFFSET: + case EOI_OFFSET: + case REMOTE_READ_OFFSET: + case LDR_OFFSET: + case DFR_OFFSET: + case SPURIOUS_INT_VEC_OFFSET: + case ISR_OFFSET: + case TMR_OFFSET: + case IRR_OFFSET: + case ESR_OFFSET: + case INT_CMD_LO_OFFSET: + case INT_CMD_HI_OFFSET: + case TMR_LOC_VEC_TBL_OFFSET: + case THERM_LOC_VEC_TBL_OFFSET: + case PERF_CTR_LOC_VEC_TBL_OFFSET: + case LINT0_VEC_TBL_OFFSET: + case LINT1_VEC_TBL_OFFSET: + case ERR_VEC_TBL_OFFSET: + case TMR_INIT_CNT_OFFSET: + case TMR_CUR_CNT_OFFSET: + case TMR_DIV_CFG_OFFSET: + case EXT_APIC_FEATURE_OFFSET: + case EXT_APIC_CMD_OFFSET: + case SEOI_OFFSET: + case IER_OFFSET: + case EXT_INT_LOC_VEC_TBL_OFFSET: + default: + PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr); + return -1; + } + + return length; }