diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
index 28239c610..09535f8c3 100644
--- a/lib/powerpc/asm/processor.h
+++ b/lib/powerpc/asm/processor.h
@@ -10,6 +10,9 @@ void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
 void do_handle_exception(struct pt_regs *regs);
 #endif /* __ASSEMBLY__ */
 
+extern bool host_is_tcg;
+extern bool host_is_kvm;
+
 extern bool cpu_has_hv;
 extern bool cpu_has_power_mce;
 extern bool cpu_has_siar;
diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
index 8ff4939e2..2b9d67466 100644
--- a/lib/powerpc/setup.c
+++ b/lib/powerpc/setup.c
@@ -235,6 +235,8 @@ void cpu_init(struct cpu *cpu, int cpu_id)
 	cpu->in_user = false;
 }
 
+bool host_is_tcg;
+bool host_is_kvm;
 bool is_hvmode;
 
 void setup(const void *fdt)
@@ -290,6 +292,29 @@ void setup(const void *fdt)
 	assert(ret == 0);
 	freemem += fdt_size;
 
+	if (!fdt_node_check_compatible(fdt, 0, "qemu,pseries")) {
+		assert(!cpu_has_hv);
+
+		/*
+		 * host_is_tcg incorrectly does not get set when running
+		 * KVM on a TCG host (using powernv HV emulation or spapr
+		 * nested HV).
+		 */
+		ret = fdt_subnode_offset(fdt, 0, "hypervisor");
+		if (ret < 0) {
+			host_is_tcg = true;
+			host_is_kvm = false;
+		} else {
+			/* KVM is the only supported hypervisor */
+			assert(!fdt_node_check_compatible(fdt, ret, "linux,kvm"));
+			host_is_tcg = false;
+			host_is_kvm = true;
+		}
+	} else {
+		assert(cpu_has_hv);
+		host_is_tcg = true;
+		host_is_kvm = false;
+	}
 	ret = dt_get_initrd(&tmp, &initrd_size);
 	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
 	if (ret == 0) {
diff --git a/powerpc/atomics.c b/powerpc/atomics.c
index 975711fc8..7d6dfaed9 100644
--- a/powerpc/atomics.c
+++ b/powerpc/atomics.c
@@ -119,7 +119,7 @@ static void test_lwarx_stwcx(int argc, char *argv[])
 		      "stwcx.	%1,0,%3;"
 		      : "=&r"(old) : "r"(1), "r"(var), "r"((char *)var+1) : "cr0", "memory");
 	/* unaligned larx/stcx. is not required by the ISA to cause an exception, in TCG the stcx does not. */
-	report_kfail(true, old == 0 && *var == 0 && got_interrupt && recorded_regs.trap == 0x600, "unaligned stwcx. causes fault");
+	report_kfail(host_is_tcg, old == 0 && *var == 0 && got_interrupt && recorded_regs.trap == 0x600, "unaligned stwcx. causes fault");
 	got_interrupt = false;
 
 	handle_exception(0x600, NULL, NULL);
diff --git a/powerpc/interrupts.c b/powerpc/interrupts.c
index ba965ff76..6511c76f2 100644
--- a/powerpc/interrupts.c
+++ b/powerpc/interrupts.c
@@ -78,7 +78,8 @@ static void test_mce(void)
 
 	is_fetch = false;
 	asm volatile("lbz %0,0(%1)" : "=r"(tmp) : "r"(addr));
-	report(got_interrupt, "MCE on access to invalid real address");
+	/* KVM does not MCE on access outside partition scope */
+	report_kfail(host_is_kvm, got_interrupt, "MCE on access to invalid real address");
 	if (got_interrupt) {
 		report(mfspr(SPR_DAR) == addr, "MCE sets DAR correctly");
 		if (cpu_has_power_mce)
@@ -88,7 +89,8 @@ static void test_mce(void)
 
 	is_fetch = true;
 	asm volatile("mtctr %0 ; bctrl" :: "r"(addr) : "ctr", "lr");
-	report(got_interrupt, "MCE on fetch from invalid real address");
+	/* KVM does not MCE on access outside partition scope */
+	report_kfail(host_is_kvm, got_interrupt, "MCE on fetch from invalid real address");
 	if (got_interrupt) {
 		report(recorded_regs.nip == addr, "MCE sets SRR0 correctly");
 		if (cpu_has_power_mce)
diff --git a/powerpc/mmu.c b/powerpc/mmu.c
index fef790506..27220b71f 100644
--- a/powerpc/mmu.c
+++ b/powerpc/mmu.c
@@ -172,7 +172,7 @@ static void test_tlbie(int argc, char **argv)
 	handle_exception(0x700, NULL, NULL);
 
 	/* TCG has a known race invalidating other CPUs */
-	report_kfail(true, !tlbie_test_failed, "tlbie");
+	report_kfail(host_is_tcg, !tlbie_test_failed, "tlbie");
 }
 
 #define THIS_ITERS 100000
diff --git a/powerpc/pmu.c b/powerpc/pmu.c
index 8b13ee4cd..960f90787 100644
--- a/powerpc/pmu.c
+++ b/powerpc/pmu.c
@@ -107,7 +107,7 @@ static void test_pmc5_with_sc(void)
 	pmc5_2 = mfspr(SPR_PMC5);
 
 	/* TCG does not count instructions around syscalls correctly */
-	report_kfail(true, pmc5_1 + 20 == pmc5_2, "PMC5 counts instructions with syscall");
+	report_kfail(host_is_tcg, pmc5_1 + 20 == pmc5_2, "PMC5 counts instructions with syscall");
 
 	handle_exception(0xc00, NULL, NULL);
 }
@@ -336,7 +336,7 @@ static void test_bhrb(void)
 				break;
 		}
 		report(nr_bhrbe, "BHRB has been written");
-		report_kfail(true, nr_bhrbe == 8, "BHRB has written 8 entries");
+		report_kfail(!host_is_tcg, nr_bhrbe == 8, "BHRB has written 8 entries");
 		if (nr_bhrbe == 8) {
 			report(bhrbe[4] == (unsigned long)dummy_branch_1,
 					"correct unconditional branch address");
@@ -369,7 +369,7 @@ static void test_bhrb(void)
 				break;
 		}
 		report(nr_bhrbe, "BHRB has been written");
-		report_kfail(true, nr_bhrbe == 6, "BHRB has written 6 entries");
+		report_kfail(!host_is_tcg, nr_bhrbe == 6, "BHRB has written 6 entries");
 		if (nr_bhrbe == 6) {
 			report(bhrbe[4] == (unsigned long)dummy_branch_1,
 					"correct unconditional branch address");
diff --git a/powerpc/sprs.c b/powerpc/sprs.c
index c5844985a..c496efe9e 100644
--- a/powerpc/sprs.c
+++ b/powerpc/sprs.c
@@ -590,7 +590,7 @@ int main(int argc, char **argv)
 
 		if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) {
 			/* known failure KVM migration of CTRL */
-			report_kfail(true && i == 136,
+			report_kfail(host_is_kvm && i == 136,
 				"%-10s(%4d):\t        0x%08lx <==>         0x%08lx",
 				sprs[i].name, i,
 				before[i], after[i]);
diff --git a/powerpc/timebase.c b/powerpc/timebase.c
index 02a4e33c0..b1378dd2b 100644
--- a/powerpc/timebase.c
+++ b/powerpc/timebase.c
@@ -94,7 +94,7 @@ static void test_dec(int argc, char **argv)
 			break;
 	}
 	/* POWER CPUs can have a slight (few ticks) variation here */
-	report_kfail(true, tb2 - tb1 >= dec_max - dec, "decrementer remains within TB after mtDEC");
+	report_kfail(!host_is_tcg, tb2 - tb1 >= dec_max - dec, "decrementer remains within TB after mtDEC");
 
 	tb1 = get_tb();
 	mtspr(SPR_DEC, dec_max);
@@ -159,7 +159,7 @@ static void test_dec(int argc, char **argv)
 	local_irq_enable();
 	local_irq_disable();
 	/* TCG does not model this correctly */
-	report_kfail(true, !got_interrupt, "no interrupt after wrap to positive");
+	report_kfail(host_is_tcg, !got_interrupt, "no interrupt after wrap to positive");
 	got_interrupt = false;
 
 	handle_exception(0x900, NULL, NULL);
diff --git a/powerpc/tm.c b/powerpc/tm.c
index 507eaf492..d4f436147 100644
--- a/powerpc/tm.c
+++ b/powerpc/tm.c
@@ -135,7 +135,7 @@ int main(int argc, char **argv)
 	}
 	/* kvm-unit-tests can limit number of CPUs present */
 	/* KVM does not report TM in secondary threads in POWER9 */
-	report_kfail(true, cpus_with_tm >= nr_cpus_present,
+	report_kfail(host_is_kvm, cpus_with_tm >= nr_cpus_present,
 	       "TM available in all 'ibm,pa-features' properties");
 
 	all = argc == 1 || !strcmp(argv[1], "all");
