aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/hvm/vlapic.h
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-09-13 15:59:14 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-09-13 15:59:14 +0100
commitc7d036be9277592853b6ed6e5ef2691a8f0a487c (patch)
tree5347af64a71953cf58cab8feca3585c2312d67ca /xen/include/asm-x86/hvm/vlapic.h
parent37a7b1e0457a0ceec2a5bad4473000f81ef530dd (diff)
downloadxen-c7d036be9277592853b6ed6e5ef2691a8f0a487c.tar.gz
xen-c7d036be9277592853b6ed6e5ef2691a8f0a487c.tar.bz2
xen-c7d036be9277592853b6ed6e5ef2691a8f0a487c.zip
[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@intel.com> * Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com> * Signed-off-by: Eddie Dong <eddie.dong@intel.com> Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/include/asm-x86/hvm/vlapic.h')
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h30
1 files changed, 22 insertions, 8 deletions
diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 7550bf3b05..1da56bd0ca 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -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 vlapic *vlapic,
{
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;