[kvm-unit-tests PATCH 1/4] arm64: irq handlers don't use esr

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



irq handlers need to be run from a different default vector
handler, and have a different "install" API, than sync
exception handlers.

Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx>
---
 lib/arm64/asm/processor.h |  8 ++++++--
 lib/arm64/processor.c     | 50 +++++++++++++++++++++++++++++++++++++----------
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 228a21c7f8856..30615c5946011 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -44,11 +44,15 @@ enum vector {
 typedef void (*vector_fn)(enum vector v, struct pt_regs *regs,
 			  unsigned int esr);
 typedef void (*exception_fn)(struct pt_regs *regs, unsigned int esr);
+typedef void (*irq_handler_fn)(struct pt_regs *regs);
 extern void install_vector_handler(enum vector v, vector_fn fn);
 extern void install_exception_handler(enum vector v, unsigned int ec,
 				      exception_fn fn);
-extern void default_vector_handler(enum vector v, struct pt_regs *regs,
-				   unsigned int esr);
+extern void install_irq_handler(enum vector v, irq_handler_fn fn);
+extern void default_vector_sync_handler(enum vector v, struct pt_regs *regs,
+					unsigned int esr);
+extern void default_vector_irq_handler(enum vector v, struct pt_regs *regs,
+				       unsigned int esr);
 extern void vector_handlers_default_init(vector_fn *handlers);
 
 extern void show_regs(struct pt_regs *regs);
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index c240ce33c3d0c..f0ce882527262 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -101,7 +101,7 @@ bool get_far(unsigned int esr, unsigned long *far)
 }
 
 static void bad_exception(enum vector v, struct pt_regs *regs,
-			  unsigned int esr, bool bad_vector)
+			  unsigned int esr, bool esr_valid, bool bad_vector)
 {
 	unsigned long far;
 	bool far_valid = get_far(esr, &far);
@@ -113,7 +113,7 @@ static void bad_exception(enum vector v, struct pt_regs *regs,
 					vector_names[v]);
 		else
 			printf("Got bad vector=%d\n", v);
-	} else {
+	} else if (esr_valid) {
 		if (ec_names[ec])
 			printf("Unhandled exception ec=0x%x (%s)\n", ec,
 					ec_names[ec]);
@@ -137,8 +137,16 @@ void install_exception_handler(enum vector v, unsigned int ec, exception_fn fn)
 		ti->exception_handlers[v][ec] = fn;
 }
 
-void default_vector_handler(enum vector v, struct pt_regs *regs,
-			    unsigned int esr)
+void install_irq_handler(enum vector v, irq_handler_fn fn)
+{
+	struct thread_info *ti = current_thread_info();
+
+	if (v < VECTOR_MAX)
+		ti->exception_handlers[v][0] = (exception_fn)fn;
+}
+
+void default_vector_sync_handler(enum vector v, struct pt_regs *regs,
+				 unsigned int esr)
 {
 	struct thread_info *ti = thread_info_sp(regs->sp);
 	unsigned int ec = esr >> ESR_EL1_EC_SHIFT;
@@ -154,15 +162,37 @@ void default_vector_handler(enum vector v, struct pt_regs *regs,
 	if (ec < EC_MAX && ti->exception_handlers[v][ec])
 		ti->exception_handlers[v][ec](regs, esr);
 	else
-		bad_exception(v, regs, esr, false);
+		bad_exception(v, regs, esr, true, false);
+}
+
+void default_vector_irq_handler(enum vector v, struct pt_regs *regs,
+				unsigned int esr)
+{
+	struct thread_info *ti = thread_info_sp(regs->sp);
+	irq_handler_fn irq_handler =
+		(irq_handler_fn)ti->exception_handlers[v][0];
+
+	if (ti->flags & TIF_USER_MODE) {
+		if (irq_handler) {
+			irq_handler(regs);
+			return;
+		}
+		ti = current_thread_info();
+		irq_handler = (irq_handler_fn)ti->exception_handlers[v][0];
+	}
+
+	if (irq_handler)
+		irq_handler(regs);
+	else
+		bad_exception(v, regs, esr, false, false);
 }
 
 void vector_handlers_default_init(vector_fn *handlers)
 {
-	handlers[EL1H_SYNC]	= default_vector_handler;
-	handlers[EL1H_IRQ]	= default_vector_handler;
-	handlers[EL0_SYNC_64]	= default_vector_handler;
-	handlers[EL0_IRQ_64]	= default_vector_handler;
+	handlers[EL1H_SYNC]	= default_vector_sync_handler;
+	handlers[EL1H_IRQ]	= default_vector_irq_handler;
+	handlers[EL0_SYNC_64]	= default_vector_sync_handler;
+	handlers[EL0_IRQ_64]	= default_vector_irq_handler;
 }
 
 void do_handle_exception(enum vector v, struct pt_regs *regs, unsigned int esr)
@@ -180,7 +210,7 @@ void do_handle_exception(enum vector v, struct pt_regs *regs, unsigned int esr)
 	if (v < VECTOR_MAX && ti->vector_handlers[v])
 		ti->vector_handlers[v](v, regs, esr);
 	else
-		bad_exception(v, regs, esr, true);
+		bad_exception(v, regs, esr, true, true);
 }
 
 void install_vector_handler(enum vector v, vector_fn fn)
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux