ia64/xen-unstable

changeset 10211:5be9e927533d

[HVM] Fix a bug in the emulation of the xchg instruction.

This bug has prevented us from booting fully virtualized SMP guests
that write to the APIC using the xchg instruction (when
CONFIG_X86_GOOD_APIC is not set). On 32 bit platforms, sles 10 kernels
are built without CONFIG_x86_GOOD_APIC not set and hence we have had
problems booting fully virtualized SMP sles 10 guests.

Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue May 30 12:30:47 2006 +0100 (2006-05-30)
parents 1dd2062668b2
children e0ec3587a2f0
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/platform.c
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Tue May 30 12:28:46 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/io.c	Tue May 30 12:30:47 2006 +0100
     1.3 @@ -648,6 +648,16 @@ static void hvm_mmio_assist(struct vcpu 
     1.4              regs->eflags &= ~X86_EFLAGS_CF;
     1.5  
     1.6          break;
     1.7 +
     1.8 +    case INSTR_XCHG:
     1.9 +	if (src & REGISTER) {
    1.10 +		index = operand_index(src);
    1.11 +		set_reg_value(size, index, 0, regs, p->u.data);
    1.12 +	} else {
    1.13 +		index = operand_index(dst);
    1.14 +		set_reg_value(size, index, 0, regs, p->u.data);
    1.15 +	}
    1.16 +	break;
    1.17      }
    1.18  
    1.19      hvm_load_cpu_guest_regs(v, regs);
     2.1 --- a/xen/arch/x86/hvm/platform.c	Tue May 30 12:28:46 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/platform.c	Tue May 30 12:30:47 2006 +0100
     2.3 @@ -954,10 +954,26 @@ void handle_mmio(unsigned long va, unsig
     2.4          mmio_opp->instr = mmio_inst.instr;
     2.5          mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
     2.6          mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
     2.7 -
     2.8 -        /* send the request and wait for the value */
     2.9 -        send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.10 -                      mmio_inst.op_size, 0, IOREQ_WRITE, 0);
    2.11 +	if (mmio_inst.operand[0] & REGISTER) {
    2.12 +		long value;
    2.13 +		unsigned long operand = mmio_inst.operand[0];
    2.14 +		value = get_reg_value(operand_size(operand), 
    2.15 +				      operand_index(operand), 0,
    2.16 +                    		      mmio_opp->inst_decoder_regs);
    2.17 +        	/* send the request and wait for the value */
    2.18 +        	send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.19 +                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
    2.20 +	} else {
    2.21 +		/* the destination is a register */
    2.22 +		long value;
    2.23 +		unsigned long operand = mmio_inst.operand[1];
    2.24 +		value = get_reg_value(operand_size(operand), 
    2.25 +				      operand_index(operand), 0,
    2.26 +                    		      mmio_opp->inst_decoder_regs);
    2.27 +        	/* send the request and wait for the value */
    2.28 +        	send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.29 +                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
    2.30 +	}
    2.31          break;
    2.32  
    2.33      default: