[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Fix an error when read from APIC registers like IRR, ISR and TMR.
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 3e31c5e160cfd01493e3e89256c733dda7efc922 # Parent 885c1513c6743cc6d8373f973a4fa696ce5215cb [HVM] Fix an error when read from APIC registers like IRR, ISR and TMR. >From SDM3 spec, for APIC registers, all 32-bit registers should be accessed using 128-bit aligned 32bit loads or stores. And wider registers (64-bit or 256-bit) must be accessed using multiple 32-bit loads or stores. In old APIC virtualization code, we use IRR, ISR and TMR which are 256-bit registers as contiguous bit maps other than multiple 32-bit. So guest always fetch error values. Original patch was: * Signed-off-by: Xiaohui Xin <xiaohui.xin@xxxxxxxxx> * Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx> * Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/vlapic.c | 35 ++++++++++++++++------------------- xen/include/asm-x86/hvm/vlapic.h | 30 ++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 27 deletions(-) diff -r 885c1513c674 -r 3e31c5e160cf xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Sep 13 15:15:27 2006 +0100 +++ b/xen/arch/x86/hvm/vlapic.c Wed Sep 13 15:59:14 2006 +0100 @@ -66,12 +66,10 @@ int vlapic_find_highest_irr(struct vlapi { int result; - result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_IRR), - MAX_VECTOR); - - ASSERT( result == -1 || result >= 16); - - return result; + result = vlapic_find_highest_vector(vlapic->regs + APIC_IRR); + ASSERT((result == -1) || (result >= 16)); + + return result; } s_time_t get_apictime_scheduled(struct vcpu *v) @@ -89,10 +87,8 @@ int vlapic_find_highest_isr(struct vlapi { int result; - result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_ISR), - MAX_VECTOR); - - ASSERT( result == -1 || result >= 16); + result = vlapic_find_highest_vector(vlapic->regs + APIC_ISR); + ASSERT((result == -1) || (result >= 16)); return result; } @@ -221,7 +217,8 @@ static int vlapic_accept_irq(struct vcpu if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) ) break; - if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) && trig_mode) + if ( vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR) && + trig_mode) { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "level trig mode repeatedly for vector %d\n", vector); @@ -232,7 +229,7 @@ static int vlapic_accept_irq(struct vcpu { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "level trig mode for vector %d\n", vector); - set_bit(vector, vlapic->regs + APIC_TMR); + vlapic_set_vector(vector, vlapic->regs + APIC_TMR); } hvm_prod_vcpu(v); @@ -358,10 +355,10 @@ void vlapic_EOI_set(struct vlapic *vlapi if ( vector == -1 ) return ; - clear_bit(vector, vlapic->regs + APIC_ISR); + vlapic_clear_vector(vector, vlapic->regs + APIC_ISR); vlapic_update_ppr(vlapic); - if ( test_and_clear_bit(vector, vlapic->regs + APIC_TMR) ) + if ( vlapic_test_and_clear_vector(vector, vlapic->regs + APIC_TMR) ) ioapic_update_EOI(vlapic->domain, vector); } @@ -816,7 +813,7 @@ void vlapic_timer_fn(void *data) vlapic->timer_last_update = now; - if ( test_and_set_bit(timer_vector, vlapic->regs + APIC_IRR )) + if ( vlapic_test_and_set_vector(timer_vector, vlapic->regs + APIC_IRR) ) vlapic->intr_pending_count[timer_vector]++; if ( vlapic_lvtt_period(vlapic) ) @@ -893,7 +890,7 @@ int cpu_get_apic_interrupt(struct vcpu * HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "Sending an illegal vector 0x%x.", highest_irr); - set_bit(err_vector, vlapic->regs + APIC_IRR); + vlapic_set_vector(err_vector, vlapic->regs + APIC_IRR); highest_irr = err_vector; } @@ -943,15 +940,15 @@ void vlapic_post_injection(struct vcpu * switch ( deliver_mode ) { case APIC_DM_FIXED: case APIC_DM_LOWEST: - set_bit(vector, vlapic->regs + APIC_ISR); - clear_bit(vector, vlapic->regs + APIC_IRR); + vlapic_set_vector(vector, vlapic->regs + APIC_ISR); + vlapic_clear_vector(vector, vlapic->regs + APIC_IRR); vlapic_update_ppr(vlapic); if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) ) { vlapic->intr_pending_count[vector]--; if ( vlapic->intr_pending_count[vector] > 0 ) - test_and_set_bit(vector, vlapic->regs + APIC_IRR); + vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR); } break; diff -r 885c1513c674 -r 3e31c5e160cf xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Wed Sep 13 15:15:27 2006 +0100 +++ b/xen/include/asm-x86/hvm/vlapic.h Wed Sep 13 15:59:14 2006 +0100 @@ -23,12 +23,28 @@ #include <asm/msr.h> #include <public/hvm/ioreq.h> -static __inline__ int find_highest_bit(unsigned long *data, int nr_bits) +#define MAX_VECTOR 256 + +#define VEC_POS(v) ((v)%32) +#define REG_POS(v) (((v)/32)* 0x10) +#define vlapic_test_and_set_vector(vec, bitmap) \ + test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)) +#define vlapic_test_and_clear_vector(vec, bitmap) \ + test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)) +#define vlapic_set_vector(vec, bitmap) \ + set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)) +#define vlapic_clear_vector(vec, bitmap) \ + clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)) + +static inline int vlapic_find_highest_vector(u32 *bitmap) { - int length = BITS_TO_LONGS(nr_bits); - while ( length && !data[--length] ) + int word_offset = MAX_VECTOR / 32; + + /* Work backwards through the bitmap (first 32-bit word in every four). */ + while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) ) continue; - return (fls(data[length]) - 1) + (length * BITS_PER_LONG); + + return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32); } #define VLAPIC(v) (v->arch.hvm_vcpu.vlapic) @@ -83,8 +99,6 @@ typedef struct direct_intr_info { int source[6]; } direct_intr_info_t; -#define MAX_VECTOR 256 - struct vlapic { uint32_t status; uint32_t vcpu_id; @@ -108,9 +122,9 @@ static inline int vlapic_set_irq(struct { int ret; - ret = test_and_set_bit(vec, vlapic->regs + APIC_IRR); + ret = vlapic_test_and_set_vector(vec, vlapic->regs + APIC_IRR); if ( trig ) - set_bit(vec, vlapic->regs + APIC_TMR); + vlapic_set_vector(vec, vlapic->regs + APIC_TMR); /* We may need to wake up target vcpu, besides set pending bit here */ return ret; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |