From 7e970c18f85f99acc678d90128b6e01dce1bf273 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 01 Nov 2024 02:40:12 +0000
Subject: [PATCH] gmac get mac form eeprom
---
kernel/arch/arm/mm/fault.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/kernel/arch/arm/mm/fault.c b/kernel/arch/arm/mm/fault.c
index efa4020..e23d0ff 100644
--- a/kernel/arch/arm/mm/fault.c
+++ b/kernel/arch/arm/mm/fault.c
@@ -9,6 +9,7 @@
#include <linux/signal.h>
#include <linux/mm.h>
#include <linux/hardirq.h>
+#include <linux/irq_pipeline.h>
#include <linux/init.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
@@ -21,10 +22,68 @@
#include <asm/system_misc.h>
#include <asm/system_info.h>
#include <asm/tlbflush.h>
+#include <asm/dovetail.h>
+#define CREATE_TRACE_POINTS
+#include <asm/trace/exceptions.h>
#include "fault.h"
#ifdef CONFIG_MMU
+
+#ifdef CONFIG_IRQ_PIPELINE
+/*
+ * We need to synchronize the virtual interrupt state with the hard
+ * interrupt state we received on entry, then turn hardirqs back on to
+ * allow code which does not require strict serialization to be
+ * preempted by an out-of-band activity.
+ */
+static inline
+unsigned long fault_entry(int exception, struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ trace_ARM_trap_entry(exception, regs);
+
+ flags = hard_local_save_flags();
+
+ /*
+ * The companion core must demote the current context to
+ * in-band stage if running oob on entry.
+ */
+ mark_trap_entry(exception, regs);
+
+ if (raw_irqs_disabled_flags(flags)) {
+ stall_inband();
+ trace_hardirqs_off();
+ }
+
+ hard_local_irq_enable();
+
+ return flags;
+}
+
+static inline
+void fault_exit(int exception, struct pt_regs *regs,
+ unsigned long flags)
+{
+ WARN_ON_ONCE(irq_pipeline_debug() && hard_irqs_disabled());
+
+ /*
+ * We expect kentry_exit_pipelined() to clear the stall bit if
+ * kentry_enter_pipelined() observed it that way.
+ */
+ mark_trap_exit(exception, regs);
+ trace_ARM_trap_exit(exception, regs);
+ hard_local_irq_restore(flags);
+}
+
+#else /* !CONFIG_IRQ_PIPELINE */
+
+#define fault_entry(__exception, __regs) ({ 0; })
+#define fault_exit(__exception, __regs, __flags) \
+ do { (void)(__flags); } while (0)
+
+#endif /* !CONFIG_IRQ_PIPELINE */
/*
* This is useful to dump out the page tables associated with
@@ -96,6 +155,15 @@
pr_cont("\n");
}
#else /* CONFIG_MMU */
+unsigned long fault_entry(int exception, struct pt_regs *regs)
+{
+ return 0;
+}
+
+static inline void fault_exit(int exception, struct pt_regs *regs,
+ unsigned long combo)
+{ }
+
void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr)
{ }
#endif /* CONFIG_MMU */
@@ -116,6 +184,7 @@
/*
* No handler, we'll have to terminate things with extreme prejudice.
*/
+ irq_pipeline_oops();
bust_spinlocks(1);
pr_alert("8<--- cut here ---\n");
pr_alert("Unable to handle kernel %s at virtual address %08lx\n",
@@ -168,14 +237,22 @@
{
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->active_mm;
+ unsigned long irqflags;
/*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
- if (user_mode(regs))
+ if (user_mode(regs)) {
+ irqflags = fault_entry(ARM_TRAP_ACCESS, regs);
__do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
- else
+ fault_exit(ARM_TRAP_ACCESS, regs, irqflags);
+ } else
+ /*
+ * irq_pipeline: kernel faults are either quickly
+ * recoverable via fixup, or lethal. In both cases, we
+ * can skip the interrupt state synchronization.
+ */
__do_kernel_fault(mm, addr, fsr, regs);
}
@@ -244,9 +321,12 @@
int sig, code;
vm_fault_t fault;
unsigned int flags = FAULT_FLAG_DEFAULT;
+ unsigned long irqflags;
+
+ irqflags = fault_entry(ARM_TRAP_ACCESS, regs);
if (kprobe_page_fault(regs, fsr))
- return 0;
+ goto out;
tsk = current;
mm = tsk->mm;
@@ -302,7 +382,7 @@
if (fault_signal_pending(fault, regs)) {
if (!user_mode(regs))
goto no_context;
- return 0;
+ goto out;
}
if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) {
@@ -318,7 +398,7 @@
* Handle the "normal" case first - VM_FAULT_MAJOR
*/
if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
- return 0;
+ goto out;
/*
* If we are in kernel mode at this point, we
@@ -334,7 +414,7 @@
* got oom-killed)
*/
pagefault_out_of_memory();
- return 0;
+ goto out;
}
if (fault & VM_FAULT_SIGBUS) {
@@ -355,10 +435,13 @@
}
__do_user_fault(addr, fsr, sig, code, regs);
- return 0;
+ goto out;
no_context:
__do_kernel_fault(mm, addr, fsr, regs);
+out:
+ fault_exit(ARM_TRAP_ACCESS, regs, irqflags);
+
return 0;
}
#else /* CONFIG_MMU */
@@ -396,6 +479,8 @@
p4d_t *p4d, *p4d_k;
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k;
+
+ WARN_ON_ONCE(irqs_pipelined() && !hard_irqs_disabled());
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);
@@ -470,7 +555,11 @@
static int
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
+ unsigned long irqflags;
+
+ irqflags = fault_entry(ARM_TRAP_SECTION, regs);
do_bad_area(addr, fsr, regs);
+ fault_exit(ARM_TRAP_SECTION, regs, irqflags);
return 0;
}
#endif /* CONFIG_ARM_LPAE */
@@ -518,10 +607,12 @@
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
+ unsigned long irqflags;
if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
return;
+ irqflags = fault_entry(ARM_TRAP_DABT, regs);
pr_alert("8<--- cut here ---\n");
pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n",
inf->name, fsr, addr);
@@ -529,6 +620,7 @@
arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
fsr, 0);
+ fault_exit(ARM_TRAP_DABT, regs, irqflags);
}
void __init
@@ -548,15 +640,18 @@
do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
{
const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
+ unsigned long irqflags;
if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
return;
+ irqflags = fault_entry(ARM_TRAP_PABT, regs);
pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
inf->name, ifsr, addr);
arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
ifsr, 0);
+ fault_exit(ARM_TRAP_PABT, regs, irqflags);
}
/*
--
Gitblit v1.6.2