This patch adds emulation support for conditional branches.
Signed-off-by: Alexander Graf <[email protected]>
---
arch/powerpc/include/asm/ppc-opcode.h | 1 +
arch/powerpc/kvm/emulate.c | 51 +++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/arch/powerpc/include/asm/ppc-opcode.h
b/arch/powerpc/include/asm/ppc-opcode.h
index 5160af9..e130156 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -116,6 +116,7 @@
#define OP_CMPI 11
#define OP_ADDIS 15
+#define OP_BC 16
#define OP_ORI 24
#define OP_ANDI 28
#define OP_LWZ 32
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 7b8acb0..aeadc30 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -473,6 +473,54 @@ static int kvmppc_emulate_cmp(struct kvm_vcpu *vcpu, u64
value0, u64 value1,
return EMULATE_DONE;
}
+int kvmppc_emulate_bc(struct kvm_vcpu *vcpu, u32 inst, bool is_32bit)
+{
+ u64 addr = (s64)(s16)get_d(inst);
+ int bo = get_rt(inst);
+ int bi = get_ra(inst);
+
+ /* If not absolute, PC gets added */
+ if (!(inst & 0x2))
+ addr += kvmppc_get_pc(vcpu);
+ if (is_32bit)
+ addr = (u32)addr;
+
+ /* LR gets set with LK=1 */
+ if (inst & 0x1)
+ kvmppc_set_lr(vcpu, kvmppc_get_pc(vcpu) + 4);
+
+ /* CTR handling */
+ if (!(bo & 0x4)) {
+ ulong ctr = kvmppc_get_ctr(vcpu);
+ ctr--;
+ if (is_32bit)
+ ctr = (u32)ctr;
+ kvmppc_set_ctr(vcpu, ctr);
+ if (((bo & 0x2) && (ctr != 0)) ||
+ (!(bo & 0x2) && (ctr == 0))) {
+ /* Condition not fulfilled, go to next inst */
+ return EMULATE_DONE;
+ }
+ }
+
+ /* CR handling */
+ if (!(bo & 0x10)) {
+ uint32_t mask = 1 << (3 - (bi & 0x3));
+ u32 cr_part = kvmppc_get_cr(vcpu) >> (28 - (bi & ~0x3));
+ if (((bo & 0x8) && (cr_part != mask)) ||
+ (!(bo & 0x8) && (cr_part == mask))) {
+ /* Condition not fulfilled, go to next inst */
+ return EMULATE_DONE;
+ }
+ }
+
+ /* Off we branch ... */
+ kvmppc_set_pc(vcpu, addr);
+
+ /* Indicate that we don't want to advance the PC */
+ return EMULATE_AGAIN;
+}
+
/* Emulates privileged and non-privileged instructions */
int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu)
{
@@ -536,6 +584,9 @@ int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu)
kvmppc_emulate_cmp(vcpu, value, (s16)get_d(inst), true,
get_rt(inst) >> 2, !(get_rt(inst) & 1));
break;
+ case OP_BC:
+ emulated = kvmppc_emulate_bc(vcpu, inst, is_32bit);
+ break;
case 31:
switch (get_xop(inst)) {
case OP_31_XOP_MFCR:
--
1.8.1.4
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html