@@ -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;
@@ -208,6 +208,9 @@ void cpu_init(struct cpu *cpu, int cpu_id)
cpu->exception_stack += SZ_64K - 64;
}
+bool host_is_tcg;
+bool host_is_kvm;
+
void setup(const void *fdt)
{
void *freemem = &stacktop;
@@ -259,6 +262,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) {
@@ -72,7 +72,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)
@@ -82,7 +83,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)
@@ -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(i == 136, pass,
+ report_kfail(host_is_kvm && i == 136, pass,
"%-10s(%4d):\t 0x%08lx <==> 0x%08lx",
sprs[i].name, i,
before[i], after[i]);
@@ -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");