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 ;
2010-01-08 02:58:01 +01:00
ulong spr_val = kvmppc_get_gpr ( vcpu , rs ) ;
2009-01-03 16:23:10 -06:00
switch ( sprn ) {
case SPRN_PID :
vcpu_e500 - > pid [ 0 ] = vcpu - > arch . shadow_pid =
2010-01-08 02:58:01 +01:00
vcpu - > arch . pid = spr_val ;
2009-01-03 16:23:10 -06:00
break ;
case SPRN_PID1 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > pid [ 1 ] = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_PID2 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > pid [ 2 ] = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS0 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas0 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS1 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas1 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS2 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas2 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS3 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas3 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS4 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas4 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS6 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas6 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS7 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > mas7 = spr_val ; break ;
2010-01-22 18:50:29 +08:00
case SPRN_L1CSR0 :
vcpu_e500 - > l1csr0 = spr_val ;
vcpu_e500 - > l1csr0 & = ~ ( L1CSR0_DCFI | L1CSR0_CLFC ) ;
break ;
2009-01-03 16:23:10 -06:00
case SPRN_L1CSR1 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > l1csr1 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_HID0 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > hid0 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_HID1 :
2010-01-08 02:58:01 +01:00
vcpu_e500 - > hid1 = spr_val ; break ;
2009-01-03 16:23:10 -06:00
2009-02-17 16:52:08 +08:00
case SPRN_MMUCSR0 :
emulated = kvmppc_e500_emul_mt_mmucsr0 ( vcpu_e500 ,
2010-01-08 02:58:01 +01:00
spr_val ) ;
2009-02-17 16:52:08 +08:00
break ;
2009-01-03 16:23:13 -06:00
/* extra exceptions */
case SPRN_IVOR32 :
2010-01-08 02:58:01 +01:00
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_UNAVAIL ] = spr_val ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR33 :
2010-01-08 02:58:01 +01:00
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_DATA ] = spr_val ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR34 :
2010-01-08 02:58:01 +01:00
vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_ROUND ] = spr_val ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR35 :
2010-01-08 02:58:01 +01:00
vcpu - > arch . ivor [ BOOKE_IRQPRIO_PERFORMANCE_MONITOR ] = spr_val ;
2009-01-03 16:23:13 -06:00
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 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > pid [ 0 ] ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_PID1 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > pid [ 1 ] ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_PID2 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > pid [ 2 ] ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS0 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas0 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS1 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas1 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS2 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas2 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS3 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas3 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS4 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas4 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS6 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas6 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_MAS7 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > mas7 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_TLB0CFG :
2010-01-22 19:36:53 +08:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > tlb0cfg ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_TLB1CFG :
2010-01-22 19:36:53 +08:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > tlb1cfg ) ; break ;
2010-01-22 18:50:29 +08:00
case SPRN_L1CSR0 :
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > l1csr0 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_L1CSR1 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > l1csr1 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_HID0 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > hid0 ) ; break ;
2009-01-03 16:23:10 -06:00
case SPRN_HID1 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu_e500 - > hid1 ) ; break ;
2009-01-03 16:23:10 -06:00
2009-02-17 16:52:08 +08:00
case SPRN_MMUCSR0 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , 0 ) ; break ;
2009-02-17 16:52:08 +08:00
2009-06-05 14:54:31 +08:00
case SPRN_MMUCFG :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , mfspr ( SPRN_MMUCFG ) ) ; break ;
2009-06-05 14:54:31 +08:00
2009-01-03 16:23:13 -06:00
/* extra exceptions */
case SPRN_IVOR32 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_UNAVAIL ] ) ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR33 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_DATA ] ) ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR34 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu - > arch . ivor [ BOOKE_IRQPRIO_SPE_FP_ROUND ] ) ;
2009-01-03 16:23:13 -06:00
break ;
case SPRN_IVOR35 :
2010-01-08 02:58:01 +01:00
kvmppc_set_gpr ( vcpu , rt , vcpu - > arch . ivor [ BOOKE_IRQPRIO_PERFORMANCE_MONITOR ] ) ;
2009-01-03 16:23:13 -06:00
break ;
2009-01-03 16:23:10 -06:00
default :
emulated = kvmppc_booke_emulate_mfspr ( vcpu , sprn , rt ) ;
}
return emulated ;
}