From: Jack Lange Date: Sat, 7 Feb 2009 20:45:26 +0000 (-0600) Subject: apic register definitions added X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=bd18ee6111c1b75fa0bbd670307d1ec1c622f91f apic register definitions added --- diff --git a/palacios/include/devices/apic_regs.h b/palacios/include/devices/apic_regs.h new file mode 100644 index 0000000..ea1d55a --- /dev/null +++ b/palacios/include/devices/apic_regs.h @@ -0,0 +1,312 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + + +struct lapic_id_reg { + union { + uint32_t val; + struct { + uint_t rsvd : 24; + uint_t apic_id : 8; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + +struct apic_ver_reg { + union { + uint32_t val; + struct { + uint_t ver : 8; + uint_t rsvd1 : 8; + uint_t max_lvts : 8; + uint_t rsvd2 : 7; + uint_t ext_reg_present : 1; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct ext_apic_ctrl_reg { + union { + uint32_t val; + struct { + uint_t ver : 1; + uint_t seoi_enable : 1; + uint_t ext_id_enable : 1; + uint_t rsvd2 : 29; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct local_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t rsvd1 : 1; + uint_t del_status : 1; + uint_t rsvd2 : 1; + uint_t rem_irr : 1; + uint_t trig_mode : 1; + uint_t mask : 1; + uint_t tmr_mode : 1; + uint_t rsvd3 : 14; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct tmr_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t rsvd : 4; + uint_t del_status : 1; + uint_t rsvd2 : 3; + uint_t mask : 1; + uint_t tmr_mode : 1; + uint_t rsvd3 : 14; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct div_cfg_reg { + union { + uint32_t val; + struct { + uint_t div_val : 2; + uint_t rsvd : 1; + uint_t div_val2 : 1; + uint_t rsvd2 : 28; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct lint_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t rsvd1 : 1; + uint_t del_status : 1; + uint_t rsvd2 : 1; + uint_t rem_irr : 1; + uint_t trig_mode : 1; + uint_t mask : 1; + uint_t rsvd3 : 15; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct perf_ctr_loc_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t rsvd1 : 1; + uint_t del_status : 1; + uint_t rsvd2 : 3; + uint_t mask : 1; + uint_t rsvd3 : 15; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct therm_loc_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t rsvd1 : 1; + uint_t del_status : 1; + uint_t rsvd2 : 3; + uint_t mask : 1; + uint_t rsvd3 : 15; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + +struct err_vec_tbl_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t rsvd1 : 1; + uint_t del_status : 1; + uint_t rsvd2 : 3; + uint_t mask : 1; + uint_t rsvd3 : 15; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct err_status_reg { + union { + uint32_t val; + struct { + uint_t rsvd1 : 2; + uint_t sent_acc_err : 1; + uint_t recv_acc_err : 1; + uint_t rsvd2 : 1; + uint_t sent_ill_err : 1; + uint_t recv_ill_err : 1; + uint_t ill_reg_addr : 1; + uint_t rsvd3 : 24; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct spurious_int_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t apic_soft_en : 1; + uint_t foc_cpu_chk : 1; + uint_t rsvd1 : 22; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + +struct int_cmd_reg { + union { + uint64_t val; + + struct { + uint32_t lo; + uint32_t hi; + } __attribute__((packed)); + + struct { + uint_t vec : 8; + uint_t msg_type : 3; + uint_t dst_mode : 1; + uint_t del_status : 1; + uint_t rsvd1 : 1; + uint_t lvl : 1; + uint_t trig_mode : 1; + uint_t rem_rd_status : 2; + uint_t dst_shorthand : 2; + uint64_t rsvd2 : 36; + uint32_t dst : 8; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct loc_dst_reg { + union { + uint32_t val; + struct { + uint_t rsvd1 : 24; + uint_t dst_log_id : 8; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct dst_fmt_reg { + union { + uint32_t val; + struct { + uint_t rsvd1 : 28; + uint_t model : 4; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct arb_prio_reg { + union { + uint32_t val; + struct { + uint_t arb_prio_sub : 4; + uint_t arb_prio : 4; + uint_t rsvd1 : 24; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + + + +struct task_prio_reg { + union { + uint32_t val; + struct { + uint_t task_prio_sub : 4; + uint_t task_prio : 4; + uint_t rsvd1 : 24; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + + +struct proc_prio_reg { + union { + uint32_t val; + struct { + uint_t proc_prio_sub : 4; + uint_t proc_prio : 4; + uint_t rsvd1 : 24; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + +struct ext_apic_feature_reg { + union { + uint32_t val; + struct { + uint_t int_en_reg_cap : 1; + uint_t spec_eoi_cap : 1; + uint_t ext_apic_id_cap: 1; + uint_t rsvd1 : 13; + uint_t ext_lvt_cnt : 8; + uint_t rsvd2 : 8; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct spec_eoi_reg { + union { + uint32_t val; + struct { + uint_t vec : 8; + uint_t rsvd1 : 24; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + 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; }