Ensure that we always call the Linux page fault handler with the correct
cr2 value set. So far this is not the case if a second fault happens
while we execute the domain fault handler (which may, e.g., perform a
sleepy migration before returning).

Instead of re-writing cr2 directly in hardware, make use of the paravirt
capabilities of Linux and simply overload read/write_cr2 for this
purpose.

Signed-off-by: Jan Kiszka <[email protected]>
---
 arch/x86/include/asm/ipipe.h  |    2 ++
 arch/x86/include/asm/system.h |    5 +++++
 arch/x86/kernel/ipipe.c       |   10 ++++++++++
 3 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/ipipe.h b/arch/x86/include/asm/ipipe.h
index 32b2ece..baec016 100644
--- a/arch/x86/include/asm/ipipe.h
+++ b/arch/x86/include/asm/ipipe.h
@@ -33,6 +33,8 @@
 
 DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
 
+DECLARE_PER_CPU(unsigned long, __ipipe_cr2);
+
 static inline unsigned __ipipe_get_irq_vector(int irq)
 {
 #ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index 2760033..093687e 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -308,8 +308,13 @@ static inline void native_wbinvd(void)
 #else
 #define read_cr0()     (native_read_cr0())
 #define write_cr0(x)   (native_write_cr0(x))
+#ifdef CONFIG_IPIPE
+#define read_cr2()     __raw_get_cpu_var(__ipipe_cr2)
+#define write_cr2(x)   __raw_get_cpu_var(__ipipe_cr2) = (x)
+#else /* !CONFIG_IPIPE */
 #define read_cr2()     (native_read_cr2())
 #define write_cr2(x)   (native_write_cr2(x))
+#endif /* !CONFIG_IPIPE */
 #define read_cr3()     (native_read_cr3())
 #define write_cr3(x)   (native_write_cr3(x))
 #define read_cr4()     (native_read_cr4())
diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
index b1b6912..9425fbd 100644
--- a/arch/x86/kernel/ipipe.c
+++ b/arch/x86/kernel/ipipe.c
@@ -53,6 +53,9 @@ int __ipipe_tick_irq = 0;     /* Legacy timer */
 
 DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
 
+DEFINE_PER_CPU(unsigned long, __ipipe_cr2);
+EXPORT_PER_CPU_SYMBOL_GPL(__ipipe_cr2);
+
 #ifdef CONFIG_SMP
 
 static cpumask_t __ipipe_cpu_sync_map;
@@ -712,6 +715,7 @@ int __ipipe_handle_exception(struct pt_regs *regs, long 
error_code, int vector)
 {
        bool root_entry = false;
        unsigned long flags = 0;
+       unsigned long cr2 = 0;
 
        if (ipipe_root_domain_p) {
                root_entry = true;
@@ -734,6 +738,9 @@ int __ipipe_handle_exception(struct pt_regs *regs, long 
error_code, int vector)
                return 1;
 #endif /* CONFIG_KGDB */
 
+       if (vector == ex_do_page_fault)
+               cr2 = native_read_cr2();
+
        if (unlikely(ipipe_trap_notify(vector, regs))) {
                if (root_entry)
                        local_irq_restore_nosync(flags);
@@ -779,6 +786,9 @@ int __ipipe_handle_exception(struct pt_regs *regs, long 
error_code, int vector)
                }
        }
 
+       if (vector == ex_do_page_fault)
+               write_cr2(cr2);
+
        __ipipe_std_extable[vector](regs, error_code);
 
        /*


_______________________________________________
Adeos-main mailing list
[email protected]
https://mail.gna.org/listinfo/adeos-main

Reply via email to