diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2007-12-19 11:14:05 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2007-12-19 11:14:05 +0000 |
commit | dde6ba19a11be4a9d8298e1fc46282727af6e654 (patch) | |
tree | 3420337000d1def357acbe9220ee3f107a81b4de | |
parent | 692779e12869a2da82059623c8e6885efdae1ff5 (diff) | |
download | xen-dde6ba19a11be4a9d8298e1fc46282727af6e654.tar.gz xen-dde6ba19a11be4a9d8298e1fc46282727af6e654.tar.bz2 xen-dde6ba19a11be4a9d8298e1fc46282727af6e654.zip |
hvm: Some cleanups to vlapic emulation.
Some of this was suggested by Dexuan Cui.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r-- | xen/arch/x86/hvm/vlapic.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index e32ac13b00..a52a44f628 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -472,7 +472,7 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address, struct vlapic *vlapic = vcpu_vlapic(v); unsigned int offset = address - vlapic_base_address(vlapic); - if ( offset > APIC_TDCR ) + if ( offset > (APIC_TDCR + 0x3) ) return 0; alignment = offset & 0x3; @@ -535,7 +535,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address, * According to the IA32 Manual, all accesses should be 32 bits. * Some OSes do 8- or 16-byte accesses, however. */ - val &= 0xffffffff; + val = (uint32_t)val; if ( len != 4 ) { unsigned int tmp; @@ -549,32 +549,27 @@ static void vlapic_write(struct vcpu *v, unsigned long address, switch ( len ) { case 1: - val = (tmp & ~(0xff << (8*alignment))) | - ((val & 0xff) << (8*alignment)); + val = ((tmp & ~(0xff << (8*alignment))) | + ((val & 0xff) << (8*alignment))); break; case 2: if ( alignment & 1 ) - { - gdprintk(XENLOG_ERR, "Uneven alignment error for " - "2-byte vlapic access\n"); - goto exit_and_crash; - } - - val = (tmp & ~(0xffff << (8*alignment))) | - ((val & 0xffff) << (8*alignment)); + goto unaligned_exit_and_crash; + val = ((tmp & ~(0xffff << (8*alignment))) | + ((val & 0xffff) << (8*alignment))); break; default: gdprintk(XENLOG_ERR, "Local APIC write with len = %lx, " "should be 4 instead\n", len); - exit_and_crash: - domain_crash(v->domain); - return; + goto exit_and_crash; } } + else if ( (offset & 0x3) != 0 ) + goto unaligned_exit_and_crash; - offset &= 0xff0; + offset &= ~0x3; switch ( offset ) { @@ -671,6 +666,14 @@ static void vlapic_write(struct vcpu *v, unsigned long address, "Local APIC Write to read-only register 0x%x\n", offset); break; } + + return; + + unaligned_exit_and_crash: + gdprintk(XENLOG_ERR, "Unaligned LAPIC write len=0x%lx at offset=0x%x.\n", + len, offset); + exit_and_crash: + domain_crash(v->domain); } static int vlapic_range(struct vcpu *v, unsigned long addr) |