lapic: continuous LVT registers as an array

Pointer arithmetic is currently used to calculate the address of a specific
Local Vector Table (LVT) register (except LVT_CMCI) in lapic, since the
registers are continuously placed with fixed padding in between. However each of
these registers are declared as a single uint32_t in struct lapic, resulting
pointer arithmetic on a non-array pointer which violates MISRA C requirements.

This patch refactors struct lapic by converting the LVT registers fields (again
except LVT_CMCI) to an array named lvt. The LVT indices are reordered to reflect
the order of the LVT registers on hardware, and reused to index this lvt array.

The code before and after the changes is semantically equivalent.

Signed-off-by: Junjie Mao <junjie.mao@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
Junjie Mao 2018-05-29 19:37:58 +08:00 committed by lijinxia
parent 9a604ed00e
commit 2266e133fb
2 changed files with 44 additions and 49 deletions

View File

@ -227,28 +227,28 @@ vlapic_id_write_handler(struct vlapic *vlapic)
static inline bool
vlapic_lvtt_oneshot(struct vlapic *vlapic)
{
return ((vlapic->apic_page->lvt_timer & APIC_LVTT_TM)
return ((vlapic->apic_page->lvt[APIC_LVT_TIMER].val & APIC_LVTT_TM)
== APIC_LVTT_TM_ONE_SHOT);
}
static inline bool
vlapic_lvtt_period(struct vlapic *vlapic)
{
return ((vlapic->apic_page->lvt_timer & APIC_LVTT_TM)
return ((vlapic->apic_page->lvt[APIC_LVT_TIMER].val & APIC_LVTT_TM)
== APIC_LVTT_TM_PERIODIC);
}
static inline bool
vlapic_lvtt_tsc_deadline(struct vlapic *vlapic)
{
return ((vlapic->apic_page->lvt_timer & APIC_LVTT_TM)
return ((vlapic->apic_page->lvt[APIC_LVT_TIMER].val & APIC_LVTT_TM)
== APIC_LVTT_TM_TSCDLT);
}
static inline bool
vlapic_lvtt_masked(struct vlapic *vlapic)
{
return !!(vlapic->apic_page->lvt_timer & APIC_LVTT_M);
return !!(vlapic->apic_page->lvt[APIC_LVT_TIMER].val & APIC_LVTT_M);
}
static void vlapic_create_timer(struct vlapic *vlapic)
@ -416,28 +416,6 @@ vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
return 1;
}
static inline uint32_t *
vlapic_get_lvtptr(struct vlapic *vlapic, uint32_t offset)
{
struct lapic *lapic = vlapic->apic_page;
int i;
switch (offset) {
case APIC_OFFSET_CMCI_LVT:
return &lapic->lvt_cmci;
case APIC_OFFSET_TIMER_LVT:
case APIC_OFFSET_THERM_LVT:
case APIC_OFFSET_PERF_LVT:
case APIC_OFFSET_LINT0_LVT:
case APIC_OFFSET_LINT1_LVT:
case APIC_OFFSET_ERROR_LVT:
i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
return (&lapic->lvt_timer) + i;
default:
panic("vlapic_get_lvt: invalid LVT\n");
}
}
static inline int
lvt_off_to_idx(uint32_t offset)
{
@ -476,6 +454,28 @@ lvt_off_to_idx(uint32_t offset)
return index;
}
static inline uint32_t *
vlapic_get_lvtptr(struct vlapic *vlapic, uint32_t offset)
{
struct lapic *lapic = vlapic->apic_page;
int i;
switch (offset) {
case APIC_OFFSET_CMCI_LVT:
return &lapic->lvt_cmci;
case APIC_OFFSET_TIMER_LVT:
case APIC_OFFSET_THERM_LVT:
case APIC_OFFSET_PERF_LVT:
case APIC_OFFSET_LINT0_LVT:
case APIC_OFFSET_LINT1_LVT:
case APIC_OFFSET_ERROR_LVT:
i = lvt_off_to_idx(offset);
return &(lapic->lvt[i].val);
default:
panic("vlapic_get_lvt: invalid LVT\n");
}
}
static inline uint32_t
vlapic_get_lvt(struct vlapic *vlapic, uint32_t offset)
{
@ -557,22 +557,22 @@ vlapic_mask_lvts(struct vlapic *vlapic)
lapic->lvt_cmci |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_CMCI_LVT);
lapic->lvt_timer |= APIC_LVT_M;
lapic->lvt[APIC_LVT_TIMER].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_TIMER_LVT);
lapic->lvt_thermal |= APIC_LVT_M;
lapic->lvt[APIC_LVT_THERMAL].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_THERM_LVT);
lapic->lvt_pcint |= APIC_LVT_M;
lapic->lvt[APIC_LVT_PMC].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_PERF_LVT);
lapic->lvt_lint0 |= APIC_LVT_M;
lapic->lvt[APIC_LVT_LINT0].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_LINT0_LVT);
lapic->lvt_lint1 |= APIC_LVT_M;
lapic->lvt[APIC_LVT_LINT1].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_LINT1_LVT);
lapic->lvt_error |= APIC_LVT_M;
lapic->lvt[APIC_LVT_ERROR].val |= APIC_LVT_M;
vlapic_lvt_write_handler(vlapic, APIC_OFFSET_ERROR_LVT);
}
@ -1500,10 +1500,10 @@ void vlapic_restore(struct vlapic *vlapic, struct lapic_regs *regs)
lapic->tmr[i].val = regs->tmr[i];
lapic->svr = regs->svr;
vlapic_svr_write_handler(vlapic);
lapic->lvt_timer = regs->lvtt;
lapic->lvt_lint0 = regs->lvt0;
lapic->lvt_lint1 = regs->lvt1;
lapic->lvt_error = regs->lvterr;
lapic->lvt[APIC_LVT_TIMER].val = regs->lvtt;
lapic->lvt[APIC_LVT_LINT0].val = regs->lvt0;
lapic->lvt[APIC_LVT_LINT1].val = regs->lvt1;
lapic->lvt[APIC_LVT_ERROR].val = regs->lvterr;
lapic->icr_timer = regs->ticr;
lapic->ccr_timer = regs->tccr;
lapic->dcr_timer = regs->tdcr;
@ -1788,7 +1788,7 @@ static int vlapic_timer_expired(void *data)
/* inject vcpu timer interrupt if not masked */
if (!vlapic_lvtt_masked(vlapic))
vlapic_intr_edge(vcpu, lapic->lvt_timer & APIC_LVTT_VECTOR);
vlapic_intr_edge(vcpu, lapic->lvt[APIC_LVT_TIMER].val & APIC_LVTT_VECTOR);
if (!vlapic_lvtt_period(vlapic))
vlapic->vlapic_timer.timer.fire_tsc = 0;

View File

@ -158,12 +158,7 @@ struct lapic {
uint32_t lvt_cmci; PAD3;
uint32_t icr_lo; PAD3;
uint32_t icr_hi; PAD3;
uint32_t lvt_timer; PAD3;
uint32_t lvt_thermal; PAD3;
uint32_t lvt_pcint; PAD3;
uint32_t lvt_lint0; PAD3;
uint32_t lvt_lint1; PAD3;
uint32_t lvt_error; PAD3;
struct lapic_reg lvt[6];
uint32_t icr_timer; PAD3;
uint32_t ccr_timer; PAD3;
/* reserved */ PAD4;
@ -421,12 +416,12 @@ struct ioapic {
#define APIC_EXTF_IER_CAP 0x00000001
/* LVT table indices */
#define APIC_LVT_LINT0 0
#define APIC_LVT_LINT1 1
#define APIC_LVT_TIMER 2
#define APIC_LVT_ERROR 3
#define APIC_LVT_PMC 4
#define APIC_LVT_THERMAL 5
#define APIC_LVT_TIMER 0
#define APIC_LVT_THERMAL 1
#define APIC_LVT_PMC 2
#define APIC_LVT_LINT0 3
#define APIC_LVT_LINT1 4
#define APIC_LVT_ERROR 5
#define APIC_LVT_CMCI 6
#define APIC_LVT_MAX APIC_LVT_CMCI