All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH] arm/arm64: fix mmu_enabled
@ 2015-07-29 14:03 Andrew Jones
  0 siblings, 0 replies; only message in thread
From: Andrew Jones @ 2015-07-29 14:03 UTC (permalink / raw
  To: kvm; +Cc: pbonzini, lkurusa

We recently modified how mmu_enabled works in order to speed
spinlocks up (see c33efcf3 and b141dbac). Unfortunately c33efcf3
was a bit hasty in removing mmu_set_enabled. I had forgotten
one of the reasons I introduced it was because secondaries
don't go through mmu_enable(), they go straight to asm_mmu_enable
from secondary_entry. This patch brings it back, albeit renamed
to mmu_mark_enabled to match mmu_mark_disabled.

The patch also moves mmu_mark_disabled from psci code to smp code,
as psci code shouldn't need to care about mmu stuff, and because
we now have a nice balance in the smp code - we mark the mmu disabled
for the secondary before we kick it, and then mark it enabled on the
init.

Finally, a bit unrelated, I've added a lengthy comment to
__mmu_enabled in order to warn about what can't be called from there.
We need to be cautious there because mmu_enabled() gets scattered
around easily, being in basic functions, and thus there's risk of
recursion.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Reported-by: Levente Kurusa <lkurusa@redhat.com>
---

Couldn't test on arm32, as I usually do, since my board is out to lunch.
The issue was found on arm64, a mustang. Testing there shows this patch
resolves the issue. It works on tcg too, but it didn't have a problem
there in the first place...


 lib/arm/asm/mmu-api.h |  3 ++-
 lib/arm/mmu.c         | 26 +++++++++++++++++++-------
 lib/arm/psci.c        |  2 --
 lib/arm/smp.c         |  3 +++
 4 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/lib/arm/asm/mmu-api.h b/lib/arm/asm/mmu-api.h
index f41738be7f9ec..bf0e6a0961416 100644
--- a/lib/arm/asm/mmu-api.h
+++ b/lib/arm/asm/mmu-api.h
@@ -7,8 +7,9 @@ static inline bool mmu_enabled(void)
 {
 	return mmu_disabled_cpu_count == 0 || __mmu_enabled();
 }
-extern void mmu_enable(pgd_t *pgtable);
+extern void mmu_mark_enabled(int cpu);
 extern void mmu_mark_disabled(int cpu);
+extern void mmu_enable(pgd_t *pgtable);
 extern void mmu_disable(void);
 extern void mmu_enable_idmap(void);
 extern void mmu_init_io_sect(pgd_t *pgtable, unsigned long virt_offset);
diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c
index a74d70cb56908..1b7e4fb3cd47e 100644
--- a/lib/arm/mmu.c
+++ b/lib/arm/mmu.c
@@ -22,17 +22,18 @@ bool __mmu_enabled(void)
 {
 	int cpu = current_thread_info()->cpu;
 
+	/*
+	 * mmu_enabled is called from places that are guarding the
+	 * use of exclusive ops (which require the mmu to be enabled).
+	 * That means we CANNOT call anything from here that may use a
+	 * spinlock, atomic bitop, etc., otherwise we'll recurse.
+	 * [cpumask_]test_bit is safe though.
+	 */
 	return !cpumask_test_cpu(cpu, &mmu_disabled_cpumask);
 }
 
-extern void asm_mmu_enable(phys_addr_t pgtable);
-void mmu_enable(pgd_t *pgtable)
+void mmu_mark_enabled(int cpu)
 {
-	int cpu = current_thread_info()->cpu;
-
-	asm_mmu_enable(__pa(pgtable));
-	flush_tlb_all();
-
 	if (cpumask_test_and_clear_cpu(cpu, &mmu_disabled_cpumask))
 		--mmu_disabled_cpu_count;
 }
@@ -43,6 +44,17 @@ void mmu_mark_disabled(int cpu)
 		++mmu_disabled_cpu_count;
 }
 
+extern void asm_mmu_enable(phys_addr_t pgtable);
+void mmu_enable(pgd_t *pgtable)
+{
+	int cpu = current_thread_info()->cpu;
+
+	asm_mmu_enable(__pa(pgtable));
+	flush_tlb_all();
+
+	mmu_mark_enabled(cpu);
+}
+
 extern void asm_mmu_disable(void);
 void mmu_disable(void)
 {
diff --git a/lib/arm/psci.c b/lib/arm/psci.c
index c4469c9ea1baa..aca88851171f5 100644
--- a/lib/arm/psci.c
+++ b/lib/arm/psci.c
@@ -9,7 +9,6 @@
 #include <asm/psci.h>
 #include <asm/setup.h>
 #include <asm/page.h>
-#include <asm/mmu-api.h>
 
 #define T PSCI_INVOKE_ARG_TYPE
 __attribute__((noinline))
@@ -30,7 +29,6 @@ int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
 extern void secondary_entry(void);
 int cpu_psci_cpu_boot(unsigned int cpu)
 {
-	mmu_mark_disabled(cpu);
 	int err = psci_cpu_on(cpus[cpu], __pa(secondary_entry));
 	if (err)
 		printf("failed to boot CPU%d (%d)\n", cpu, err);
diff --git a/lib/arm/smp.c b/lib/arm/smp.c
index ca435dcd5f4a2..3cfc6d5ddedd0 100644
--- a/lib/arm/smp.c
+++ b/lib/arm/smp.c
@@ -9,6 +9,7 @@
 #include <alloc.h>
 #include <asm/thread_info.h>
 #include <asm/cpumask.h>
+#include <asm/barrier.h>
 #include <asm/mmu.h>
 #include <asm/psci.h>
 #include <asm/smp.h>
@@ -23,6 +24,7 @@ secondary_entry_fn secondary_cinit(void)
 	secondary_entry_fn entry;
 
 	thread_info_init(ti, 0);
+	mmu_mark_enabled(ti->cpu);
 
 	/*
 	 * Save secondary_data.entry locally to avoid opening a race
@@ -45,6 +47,7 @@ void smp_boot_secondary(int cpu, secondary_entry_fn entry)
 
 	secondary_data.stack = stack_base + THREAD_START_SP;
 	secondary_data.entry = entry;
+	mmu_mark_disabled(cpu);
 	assert(cpu_psci_cpu_boot(cpu) == 0);
 
 	while (!cpu_online(cpu))
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-07-29 14:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-29 14:03 [kvm-unit-tests PATCH] arm/arm64: fix mmu_enabled Andrew Jones

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.