2009-01-03 16:23:10 -06:00
/*
* Copyright ( C ) 2008 Freescale Semiconductor , Inc . All rights reserved .
*
* Author : Yu Liu , < yu . liu @ freescale . com >
*
* Description :
* This file is derived from arch / powerpc / kvm / 44 x_emulate . c ,
* by Hollis Blanchard < hollisb @ us . ibm . com > .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License , version 2 , as
* published by the Free Software Foundation .
*/
# include <asm/kvm_ppc.h>
# include <asm/disassemble.h>
# include <asm/kvm_e500.h>
# include "booke.h"
# include "e500_tlb.h"
# define XOP_TLBIVAX 786
# define XOP_TLBSX 914
# define XOP_TLBRE 946
# define XOP_TLBWE 978
int kvmppc_core_emulate_op ( struct kvm_run * run , struct kvm_vcpu * vcpu ,
unsigned int inst , int * advance )
{
int emulated = EMULATE_DONE ;
int ra ;
int rb ;
switch ( get_op ( inst ) ) {
case 31 :
switch ( get_xop ( inst ) ) {
case XOP_TLBRE :
emulated = kvmppc_e500_emul_tlbre ( vcpu ) ;
break ;
case XOP_TLBWE :
emulated = kvmppc_e500_emul_tlbwe ( vcpu ) ;
break ;
case XOP_TLBSX :
rb = get_rb ( inst ) ;
emulated = kvmppc_e500_emul_tlbsx ( vcpu , rb ) ;
break ;
case XOP_TLBIVAX :
ra = get_ra ( inst ) ;
rb = get_rb ( inst ) ;
emulated = kvmppc_e500_emul_tlbivax ( vcpu , ra , rb ) ;
break ;
default :
emulated = EMULATE_FAIL ;
}
break ;
default :
emulated = EMULATE_FAIL ;
}
if ( emulated = = EMULATE_FAIL )
emulated = kvmppc_booke_emulate_op ( run , vcpu , inst , advance ) ;
return emulated ;
}
int kvmppc_core_emulate_mtspr ( struct kvm_vcpu * vcpu , int sprn , int rs )
{
struct kvmppc_vcpu_e500 * vcpu_e500 = to_e500 ( vcpu ) ;
int emulated = EMULATE_DONE ;
switch ( sprn ) {
case SPRN_PID :
vcpu_e500 - > pid [ 0 ] = vcpu - > arch . shadow_pid =
vcpu - > arch . pid = vcpu - > arch . gpr [ rs ] ;
break ;
case SPRN_PID1 :
vcpu_e500 - > pid [ 1 ] = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_PID2 :
vcpu_e500 - > pid [ 2 ] = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS0 :
vcpu_e500 - > mas0 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS1 :
vcpu_e500 - > mas1 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS2 :
vcpu_e500 - > mas2 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS3 :
vcpu_e500 - > mas3 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS4 :
vcpu_e500 - > mas4 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS6 :
vcpu_e500 - > mas6 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_MAS7 :
vcpu_e500 - > mas7 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_L1CSR1 :
vcpu_e500 - > l1csr1 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_HID0 :
vcpu_e500 - > hid0 = vcpu - > arch . gpr [ rs ] ; break ;
case SPRN_HID1 :
vcpu_e500 - > hid1 = vcpu - > arch . gpr [ rs ] ; break ;
2009-02-17 16:52:08 +08:00
case SPRN_MMUCSR0 :
emulated = kvmppc_e500_emul_mt_mmucsr0 ( vcpu_e500 ,
vcpu - > arch . gpr [ rs ] ) ;
break ;
2009-01-03 16:23:13 -06:00
/* extra exceptions */
case SPRN_IVOR32 :
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_UNAVAIL ] = vcpu - > arch . gpr [ rs ] ;
break ;
case SPRN_IVOR33 :
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_DATA ] = vcpu - > arch . gpr [ rs ] ;
break ;
case SPRN_IVOR34 :
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_ROUND ] = vcpu - > arch . gpr [ rs ] ;
break ;
case SPRN_IVOR35 :
vcpu - > arch . ivor [ BOOKE_IRQPRIO_PERFORMANCE_MONITOR ] = vcpu - > arch . gpr [ rs ] ;
break ;
2009-01-03 16:23:10 -06:00
default :
emulated = kvmppc_booke_emulate_mtspr ( vcpu , sprn , rs ) ;
}
return emulated ;
}
int kvmppc_core_emulate_mfspr ( struct kvm_vcpu * vcpu , int sprn , int rt )
{
struct kvmppc_vcpu_e500 * vcpu_e500 = to_e500 ( vcpu ) ;
int emulated = EMULATE_DONE ;
switch ( sprn ) {
case SPRN_PID :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > pid [ 0 ] ; break ;
case SPRN_PID1 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > pid [ 1 ] ; break ;
case SPRN_PID2 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > pid [ 2 ] ; break ;
case SPRN_MAS0 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas0 ; break ;
case SPRN_MAS1 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas1 ; break ;
case SPRN_MAS2 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas2 ; break ;
case SPRN_MAS3 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas3 ; break ;
case SPRN_MAS4 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas4 ; break ;
case SPRN_MAS6 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas6 ; break ;
case SPRN_MAS7 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > mas7 ; break ;
case SPRN_TLB0CFG :
vcpu - > arch . gpr [ rt ] = mfspr ( SPRN_TLB0CFG ) ;
vcpu - > arch . gpr [ rt ] & = ~ 0xfffUL ;
vcpu - > arch . gpr [ rt ] | = vcpu_e500 - > guest_tlb_size [ 0 ] ;
break ;
case SPRN_TLB1CFG :
vcpu - > arch . gpr [ rt ] = mfspr ( SPRN_TLB1CFG ) ;
vcpu - > arch . gpr [ rt ] & = ~ 0xfffUL ;
vcpu - > arch . gpr [ rt ] | = vcpu_e500 - > guest_tlb_size [ 1 ] ;
break ;
case SPRN_L1CSR1 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > l1csr1 ; break ;
case SPRN_HID0 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > hid0 ; break ;
case SPRN_HID1 :
vcpu - > arch . gpr [ rt ] = vcpu_e500 - > hid1 ; break ;
2009-02-17 16:52:08 +08:00
case SPRN_MMUCSR0 :
vcpu - > arch . gpr [ rt ] = 0 ; break ;
2009-06-05 14:54:31 +08:00
case SPRN_MMUCFG :
vcpu - > arch . gpr [ rt ] = mfspr ( SPRN_MMUCFG ) ; break ;
2009-01-03 16:23:13 -06:00
/* extra exceptions */
case SPRN_IVOR32 :
vcpu - > arch . gpr [ rt ] = vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_UNAVAIL ] ;
break ;
case SPRN_IVOR33 :
vcpu - > arch . gpr [ rt ] = vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_DATA ] ;
break ;
case SPRN_IVOR34 :
vcpu - > arch . gpr [ rt ] = vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_ROUND ] ;
break ;
case SPRN_IVOR35 :
vcpu - > arch . gpr [ rt ] = vcpu - > arch . ivor [ BOOKE_IRQPRIO_PERFORMANCE_MONITOR ] ;
break ;
2009-01-03 16:23:10 -06:00
default :
emulated = kvmppc_booke_emulate_mfspr ( vcpu , sprn , rt ) ;
}
return emulated ;
}