Created
January 3, 2018 04:52
-
-
Save pothos/9f0b85abb15b7dd0600730ee3c693699 to your computer and use it in GitHub Desktop.
Patches for NEON/LoGA on Linux 4.4 (Gentoo) with NVIDIA driver 304.137 (works with NVIDIA Quadro NVS 295)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/arch/x86/include/asm/pf_in.h b/arch/x86/include/asm/pf_in.h | |
new file mode 100644 | |
index 0000000..e05341a | |
--- /dev/null | |
+++ b/arch/x86/include/asm/pf_in.h | |
@@ -0,0 +1,39 @@ | |
+/* | |
+ * Fault Injection Test harness (FI) | |
+ * Copyright (C) Intel Crop. | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License | |
+ * as published by the Free Software Foundation; either version 2 | |
+ * of the License, or (at your option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ * GNU General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License | |
+ * along with this program; if not, write to the Free Software | |
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
+ * USA. | |
+ * | |
+ */ | |
+ | |
+#ifndef __PF_H_ | |
+#define __PF_H_ | |
+ | |
+enum reason_type { | |
+ NOT_ME, /* page fault is not in regions */ | |
+ NOTHING, /* access others point in regions */ | |
+ REG_READ, /* read from addr to reg */ | |
+ REG_WRITE, /* write from reg to addr */ | |
+ IMM_WRITE, /* write from imm to addr */ | |
+ OTHERS /* Other instructions can not intercept */ | |
+}; | |
+ | |
+enum reason_type get_ins_type(unsigned long ins_addr); | |
+unsigned int get_ins_mem_width(unsigned long ins_addr); | |
+unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs); | |
+unsigned long get_ins_imm_val(unsigned long ins_addr); | |
+ | |
+#endif /* __PF_H_ */ | |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c | |
index eef44d9..6cc2f5c 100644 | |
--- a/arch/x86/mm/fault.c | |
+++ b/arch/x86/mm/fault.c | |
@@ -25,6 +25,10 @@ | |
#define CREATE_TRACE_POINTS | |
#include <asm/trace/exceptions.h> | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
/* | |
* Page fault error code bits: | |
* | |
@@ -1075,6 +1079,12 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code, | |
kmemcheck_hide(regs); | |
prefetchw(&mm->mmap_sem); | |
+#ifdef CONFIG_NEON_FACE | |
+ // fault handled by neon GPU scheduler subsystem | |
+ if ((*neon_face->fault_handler)(regs, address) == 0) | |
+ return; | |
+#endif // CONFIG_NEON_FACE | |
+ | |
if (unlikely(kmmio_fault(regs, address))) | |
return; | |
diff --git a/arch/x86/mm/pf_in.c b/arch/x86/mm/pf_in.c | |
index 9f0614d..0fa7430 100644 | |
--- a/arch/x86/mm/pf_in.c | |
+++ b/arch/x86/mm/pf_in.c | |
@@ -27,7 +27,6 @@ | |
*/ | |
#include <linux/module.h> | |
-#include <linux/ptrace.h> /* struct pt_regs */ | |
#include "pf_in.h" | |
#ifdef __i386__ | |
@@ -530,3 +529,9 @@ do_work: | |
err: | |
return 0; | |
} | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+EXPORT_SYMBOL(get_ins_imm_val); | |
+EXPORT_SYMBOL(get_ins_type); | |
+EXPORT_SYMBOL(get_ins_reg_val); | |
+#endif // CONFIG_NEON_FACE | |
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c | |
index 8ddb5d0..cca4735 100644 | |
--- a/arch/x86/mm/tlb.c | |
+++ b/arch/x86/mm/tlb.c | |
@@ -239,6 +239,9 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) | |
preempt_enable(); | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+EXPORT_SYMBOL(flush_tlb_page); | |
+#endif // CONFIG_NEON_FACE | |
static void do_flush_tlb_all(void *info) | |
{ | |
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile | |
index e9ed439..48ca48a 100644 | |
--- a/drivers/gpu/Makefile | |
+++ b/drivers/gpu/Makefile | |
@@ -2,5 +2,5 @@ | |
# taken to initialize them in the correct order. Link order is the only way | |
# to ensure this currently. | |
obj-$(CONFIG_TEGRA_HOST1X) += host1x/ | |
-obj-y += drm/ vga/ | |
+obj-y += drm/ vga/ neon/ | |
obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/ | |
diff --git a/drivers/gpu/neon/Kconfig b/drivers/gpu/neon/Kconfig | |
new file mode 100644 | |
index 0000000..fd51848 | |
--- /dev/null | |
+++ b/drivers/gpu/neon/Kconfig | |
@@ -0,0 +1,9 @@ | |
+config NEON_FACE | |
+ bool "NEON interface" | |
+ default y | |
+ depends on X86_64 | |
+ help | |
+ Choose this option if you have a system that has an Nvidia | |
+ Tesla/Fermi GPU for which you want to enable the kernel-level | |
+ GPU-workload scheduling interface. No effect should be noticeable | |
+ on the system unless the respective module is loaded. | |
diff --git a/drivers/gpu/neon/Makefile b/drivers/gpu/neon/Makefile | |
new file mode 100644 | |
index 0000000..e287c03 | |
--- /dev/null | |
+++ b/drivers/gpu/neon/Makefile | |
@@ -0,0 +1,9 @@ | |
+# /***************************************************************************/ | |
+# /*! | |
+# \author Konstantinos Menychtas --- [email protected] | |
+# \brief "NEON interface for black-box GPU kernel-level management" | |
+# */ | |
+# /***************************************************************************/ | |
+ | |
+ccflags-y := -Iinclude/neon | |
+obj-$(CONFIG_NEON_FACE) += neon_face.o | |
diff --git a/drivers/gpu/neon/neon_face.c b/drivers/gpu/neon/neon_face.c | |
new file mode 100644 | |
index 0000000..88f477a | |
--- /dev/null | |
+++ b/drivers/gpu/neon/neon_face.c | |
@@ -0,0 +1,221 @@ | |
+/***************************************************************************/ | |
+/*! | |
+ \author Konstantinos Menychtas --- [email protected] | |
+ \brief "NEON interface for black-box GPU kernel-level management" | |
+*/ | |
+/***************************************************************************/ | |
+ | |
+#include <linux/kernel.h> | |
+#include <linux/module.h> | |
+#include <linux/semaphore.h> | |
+#include <linux/wait.h> | |
+#include <neon/neon_face.h> | |
+ | |
+/****************************************************************************/ | |
+// Neon TracePoint | |
+ | |
+#define CREATE_TRACE_POINTS | |
+#include <trace/events/neon.h> | |
+EXPORT_TRACEPOINT_SYMBOL(neon_record); | |
+ | |
+/****************************************************************************/ | |
+// Interface: Neon/Driver | |
+ | |
+/****************************************************************************/ | |
+// neon_ioctl | |
+/****************************************************************************/ | |
+int | |
+neon_face_ioctl(int cmd_nr, | |
+ void *pre_cmd_val, | |
+ void *post_cmd_val) | |
+{ | |
+ // pass ioctl information to state machine | |
+ // stub; to be overloaded by driver | |
+ return 0; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_map_pages | |
+/****************************************************************************/ | |
+int | |
+neon_face_map_pages(struct vm_area_struct *vma, | |
+ unsigned long addr, | |
+ unsigned long offset, | |
+ unsigned long size, | |
+ unsigned int area, | |
+ neon_map_area_t pages) | |
+{ | |
+ // pass mmap requests to state machine | |
+ // stub; to be overloaded by driver | |
+ return 0; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_pin_pages | |
+/****************************************************************************/ | |
+int | |
+neon_face_pin_pages(void *user_address, | |
+ struct page **pinned_pages, | |
+ unsigned long long *pte_array, | |
+ unsigned long long nr_pages) | |
+{ | |
+ // pass lock_user_pages requests to state machine | |
+ // stub; to be overloaded by driver | |
+ return 0; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_unpin_pages | |
+/****************************************************************************/ | |
+int | |
+neon_face_unpin_pages(struct page **pinned_pages, | |
+ unsigned long long *pte_array, | |
+ unsigned long long nr_pages) | |
+{ | |
+ // pass unlock_user_pages requests to state machine | |
+ // stub; to be overloaded by driver | |
+ return 0; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// Interface: Neon/Linux | |
+ | |
+/****************************************************************************/ | |
+// neon_copy_task | |
+/****************************************************************************/ | |
+int | |
+neon_face_copy_task(unsigned long clone_flags, | |
+ struct task_struct *tsk) | |
+{ | |
+ // "copy" neon-related task-struct during new thread creation (do_fork) | |
+ // stub; to be overloaded by neon module | |
+ return 0; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_exit_task | |
+/****************************************************************************/ | |
+void | |
+neon_face_exit_task(struct task_struct *tsk) | |
+{ | |
+ // clean-up function for task holding a context | |
+ // stub; to be overloaded by neon module | |
+ return; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_fault_handler | |
+/****************************************************************************/ | |
+int | |
+neon_face_fault_handler(struct pt_regs *regs, | |
+ unsigned long addr) | |
+{ | |
+ // handle fault at guarded (channel-register-mapped) page | |
+ // stub; to be overloaded by neon module | |
+ | |
+ // default return 1 to signify that fault does not concern a GPU | |
+ // memory area being tracked, so it has to be managed by the | |
+ // normal handler | |
+ return 1; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_unmap_vma | |
+/****************************************************************************/ | |
+void | |
+neon_face_unmap_vma(struct vm_area_struct *vma) | |
+{ | |
+ // properly clean up as related vma gets unmapped | |
+ // stub; to be overloaded by neon module | |
+ return; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_tweet | |
+/****************************************************************************/ | |
+void | |
+neon_tweet(const char *str) | |
+{ | |
+ // associate a tracepoint to str, allowing str to appear inline | |
+ // with the rest of neon's trace | |
+ // stub; to be overloaded by neon module | |
+ return; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// Default = none | |
+ | |
+neon_face_t neon_face_none = { | |
+ .ioctl = neon_face_ioctl, | |
+ .map_pages = neon_face_map_pages, | |
+ .pin_pages = neon_face_pin_pages, | |
+ .unpin_pages = neon_face_unpin_pages, | |
+ .unmap_vma = neon_face_unmap_vma, | |
+ .fault_handler = neon_face_fault_handler, | |
+ .copy_task = neon_face_copy_task, | |
+ .exit_task = neon_face_exit_task, | |
+ .tweet = neon_tweet, | |
+}; | |
+ | |
+neon_face_t *neon_face = &neon_face_none; | |
+EXPORT_SYMBOL(neon_face); | |
+ | |
+DEFINE_SEMAPHORE(neon_face_sem); | |
+ | |
+/****************************************************************************/ | |
+// neon_register | |
+/****************************************************************************/ | |
+int | |
+neon_face_register(neon_face_t *face) | |
+{ | |
+ if(down_trylock(&neon_face_sem) == 0) { | |
+ // pr_info("NEON: register neon face [none 0x%p] 0x%p ---> 0x%p", | |
+ // &neon_face_none, neon_face, face); | |
+ if(face != NULL) | |
+ neon_face = face; | |
+ else | |
+ neon_face = &neon_face_none; | |
+ up(&neon_face_sem); | |
+ return 0; | |
+ } | |
+ | |
+ return 1; | |
+} | |
+EXPORT_SYMBOL(neon_face_register); | |
+ | |
+/****************************************************************************/ | |
+// neon_face_init | |
+/****************************************************************************/ | |
+static int | |
+__init neon_face_init(void) | |
+{ | |
+ if(neon_face_register(&neon_face_none) == 0) { | |
+ pr_info("NEON: interface loaded.\n"); | |
+ return 0; | |
+ } else | |
+ pr_info("NEON: interface could not be loaded.\n"); | |
+ | |
+ return 1; | |
+} | |
+ | |
+/****************************************************************************/ | |
+// neon_face_exit | |
+/****************************************************************************/ | |
+static void | |
+__exit neon_face_exit(void) | |
+{ | |
+ if(neon_face_register(NULL) == 0) | |
+ pr_info("NEON: interface unloaded.\n"); | |
+ else | |
+ pr_warning("NEON: interface could not be unloaded.\n"); | |
+ | |
+ return; | |
+} | |
+ | |
+module_init(neon_face_init); | |
+module_exit(neon_face_exit); | |
+ | |
+MODULE_LICENSE("GPL"); | |
+MODULE_AUTHOR("Konstantinos Menychtas"); | |
+MODULE_DESCRIPTION("NEON Interface for Black-Box" | |
+ "GPU kernel-level management"); | |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig | |
index e0606c0..11e81e1 100644 | |
--- a/drivers/video/Kconfig | |
+++ b/drivers/video/Kconfig | |
@@ -22,6 +22,8 @@ source "drivers/gpu/vga/Kconfig" | |
source "drivers/gpu/host1x/Kconfig" | |
source "drivers/gpu/ipu-v3/Kconfig" | |
+source "drivers/gpu/neon/Kconfig" | |
+ | |
source "drivers/gpu/drm/Kconfig" | |
menu "Frame buffer Devices" | |
diff --git a/include/linux/mm.h b/include/linux/mm.h | |
index 00bad77..d98576e 100644 | |
--- a/include/linux/mm.h | |
+++ b/include/linux/mm.h | |
@@ -55,6 +55,10 @@ extern int sysctl_legacy_va_layout; | |
#include <asm/pgtable.h> | |
#include <asm/processor.h> | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#ifndef __pa_symbol | |
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) | |
#endif | |
@@ -2305,6 +2309,15 @@ static inline bool debug_guardpage_enabled(void) { return false; } | |
static inline bool page_is_guard(struct page *page) { return false; } | |
#endif /* CONFIG_DEBUG_PAGEALLOC */ | |
+#ifdef CONFIG_NEON_FACE | |
+struct page * | |
+neon_follow_page(struct vm_area_struct *vma, | |
+ unsigned long address); | |
+int neon_follow_pte(struct vm_area_struct *vma, | |
+ unsigned long address, | |
+ pte_t **ptep); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#if MAX_NUMNODES > 1 | |
void __init setup_nr_node_ids(void); | |
#else | |
diff --git a/include/linux/preempt.h b/include/linux/preempt.h | |
index 75e4e30..9767810 100644 | |
--- a/include/linux/preempt.h | |
+++ b/include/linux/preempt.h | |
@@ -228,6 +228,7 @@ do { \ | |
#endif /* CONFIG_PREEMPT_COUNT */ | |
+#ifndef CONFIG_NEON_FACE | |
#ifdef MODULE | |
/* | |
* Modules have no business playing preemption tricks. | |
@@ -237,6 +238,7 @@ do { \ | |
#undef preempt_enable_no_resched_notrace | |
#undef preempt_check_resched | |
#endif | |
+#endif // CONFIG_NEON_FACE | |
#define preempt_set_need_resched() \ | |
do { \ | |
diff --git a/include/linux/sched.h b/include/linux/sched.h | |
index 02a538e..2c1cfcf 100644 | |
--- a/include/linux/sched.h | |
+++ b/include/linux/sched.h | |
@@ -62,6 +62,9 @@ struct sched_param { | |
#include <asm/processor.h> | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
#define SCHED_ATTR_SIZE_VER0 48 /* sizeof first published struct */ | |
@@ -1823,6 +1826,13 @@ struct task_struct { | |
struct fw_task *fw_task; | |
unsigned int curr_cpu; | |
#endif | |
+#ifdef CONFIG_NEON_FACE | |
+ // neon_task created by this task or its parent; | |
+ // cast neon_task to neon_task_t; | |
+ // using void* to keep the interface clean | |
+ void *neon_task; | |
+ rwlock_t neon_task_rwlock; | |
+#endif // CONFIG_NEON_FACE | |
/* CPU-specific state of this task */ | |
struct thread_struct thread; | |
/* | |
diff --git a/include/neon/neon_face.h b/include/neon/neon_face.h | |
new file mode 100644 | |
index 0000000..69035c0 | |
--- /dev/null | |
+++ b/include/neon/neon_face.h | |
@@ -0,0 +1,66 @@ | |
+/***************************************************************************/ | |
+/*! | |
+ \author Konstantinos Menychtas --- [email protected] | |
+ \brief "Neon" module for black-box GPU kernel-level management | |
+*/ | |
+/***************************************************************************/ | |
+ | |
+#ifndef __NEON_FACE_H__ | |
+#define __NEON_FACE_H__ | |
+ | |
+struct task_struct; // linux/sched.h | |
+struct vm_area_struct; // linux/mm_types.h | |
+struct __wait_queue_head; // linux/wait.h | |
+struct pt_regs; // asm/ptrace.h | |
+ | |
+typedef enum { | |
+ NEON_REGISTER, | |
+ NEON_FRAMEBUFFER, | |
+ NEON_SYSTEM, | |
+ NEON_UNKNOWN | |
+} neon_map_area_t; | |
+ | |
+typedef struct { | |
+ // Interface: Neon/Driver | |
+ /*************************************************************************/ | |
+ // pass ioctl information to state machine | |
+ int (*ioctl) (int cmd_nr, | |
+ void *pre_cmd_val, | |
+ void *post_cmd_val); | |
+ // pass mmap requests to state machine | |
+ int (*map_pages)(struct vm_area_struct *vma, | |
+ unsigned long addr, | |
+ unsigned long offset, | |
+ unsigned long size, | |
+ neon_map_area_t area); | |
+ // pass lock_user_pages requests to state machine | |
+ int (*pin_pages)(void *user_address, | |
+ struct page **pinned_pages, | |
+ unsigned long long *pte_array, | |
+ unsigned long long nr_pages); | |
+ // pass unlock_user_pages requests to state machine | |
+ int (*unpin_pages)(struct page **pinned_pages, | |
+ unsigned long long *pte_array, | |
+ unsigned long long nr_pages); | |
+ // Interface: Neon/Linux | |
+ /*************************************************************************/ | |
+ // properly clean up as related vma gets unmapped | |
+ void (*unmap_vma)(struct vm_area_struct *vma); | |
+ // handle fault at guarded (channel-register-mapped) page | |
+ int (*fault_handler)(struct pt_regs *regs, | |
+ unsigned long addr); | |
+ // "copy" neon-related task-struct during new thread creation (do_fork) | |
+ int (*copy_task)(unsigned long clone_flags, | |
+ struct task_struct *tsk); | |
+ // clean-up function for task holding a context | |
+ void (*exit_task)(struct task_struct *tsk); | |
+ // Interface: Neon/Linux --- extras | |
+ /*************************************************************************/ | |
+ // tracing helper: associate a tracepoint to str | |
+ void (*tweet)(const char *str); | |
+} neon_face_t; | |
+ | |
+extern neon_face_t *neon_face; | |
+int neon_face_register(neon_face_t *face); | |
+ | |
+#endif // __NEON_FACE_H__ | |
diff --git a/include/trace/events/neon.h b/include/trace/events/neon.h | |
new file mode 100644 | |
index 0000000..465f63f | |
--- /dev/null | |
+++ b/include/trace/events/neon.h | |
@@ -0,0 +1,35 @@ | |
+/******************************************************************************/ | |
+/*! | |
+ \author Konstantinos Menychtas --- [email protected] | |
+ \brief "NEON interface for black-box GPU kernel-level management" | |
+*/ | |
+/******************************************************************************/ | |
+ | |
+#undef TRACE_SYSTEM | |
+#define TRACE_SYSTEM neon | |
+ | |
+#if !defined(__NEON_H__) || defined(TRACE_HEADER_MULTI_READ) | |
+#define __NEON_H__ | |
+ | |
+#include <linux/tracepoint.h> | |
+ | |
+TRACE_EVENT(neon_record, | |
+ | |
+ TP_PROTO(const char *in_str), | |
+ | |
+ TP_ARGS(in_str), | |
+ | |
+ TP_STRUCT__entry( | |
+ __string( str, in_str ) | |
+ ), | |
+ | |
+ TP_fast_assign( | |
+ __assign_str(str, in_str) | |
+ ), | |
+ | |
+ TP_printk("%s", __get_str(str)) | |
+) | |
+ | |
+#endif // __NEON_H___ | |
+ | |
+#include <trace/define_trace.h> | |
diff --git a/kernel/exit.c b/kernel/exit.c | |
index 07110c6..8dc3bdb 100644 | |
--- a/kernel/exit.c | |
+++ b/kernel/exit.c | |
@@ -59,6 +59,10 @@ | |
#include <asm/pgtable.h> | |
#include <asm/mmu_context.h> | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
static void exit_mm(struct task_struct *tsk); | |
static void __unhash_process(struct task_struct *p, bool group_dead) | |
@@ -734,6 +738,11 @@ void do_exit(long code) | |
exit_mm(tsk); | |
+#ifdef CONFIG_NEON_FACE | |
+ // exit_mm needs to go first, remove vmas | |
+ (*neon_face->exit_task)(tsk); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
if (group_dead) | |
acct_process(); | |
trace_sched_process_exit(tsk); | |
diff --git a/kernel/fork.c b/kernel/fork.c | |
index 1155eac..36f7ee0 100644 | |
--- a/kernel/fork.c | |
+++ b/kernel/fork.c | |
@@ -85,6 +85,10 @@ | |
#include <trace/events/sched.h> | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#define CREATE_TRACE_POINTS | |
#include <trace/events/task.h> | |
@@ -1416,6 +1420,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |
p->sequential_io_avg = 0; | |
#endif | |
+#ifdef CONFIG_NEON_FACE | |
+ p->neon_task = NULL; | |
+ rwlock_init(&p->neon_task_rwlock); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
/* Perform scheduler related setup. Assign this task to a CPU. */ | |
retval = sched_fork(clone_flags, p); | |
if (retval) | |
@@ -1465,6 +1474,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |
} | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+ if ((retval = (*neon_face->copy_task)(clone_flags, p))) | |
+ goto bad_fork_cleanup_neon; | |
+#endif // CONFIG_NEON_FACE | |
+ | |
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | |
/* | |
* Clear TID on mm_release()? | |
@@ -1618,6 +1632,10 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |
return p; | |
+#ifdef CONFIG_NEON_FACE | |
+bad_fork_cleanup_neon: | |
+ (*neon_face->exit_task)(p); | |
+#endif // CONFIG_NEON_FACEs | |
bad_fork_cancel_cgroup: | |
cgroup_cancel_fork(p, cgrp_ss_priv); | |
bad_fork_free_pid: | |
diff --git a/lib/bitmap.c b/lib/bitmap.c | |
index 8148143..7fa7075 100644 | |
--- a/lib/bitmap.c | |
+++ b/lib/bitmap.c | |
@@ -42,6 +42,21 @@ | |
* for the best explanations of this ordering. | |
*/ | |
+int __bitmap_empty(const unsigned long *bitmap, unsigned int bits) | |
+{ | |
+ unsigned int k, lim = bits/BITS_PER_LONG; | |
+ for (k = 0; k < lim; ++k) | |
+ if (bitmap[k]) | |
+ return 0; | |
+ | |
+ if (bits % BITS_PER_LONG) | |
+ if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) | |
+ return 0; | |
+ | |
+ return 1; | |
+} | |
+EXPORT_SYMBOL(__bitmap_empty); | |
+ | |
int __bitmap_equal(const unsigned long *bitmap1, | |
const unsigned long *bitmap2, unsigned int bits) | |
{ | |
diff --git a/mm/memory.c b/mm/memory.c | |
index c387430..3aa58f6 100644 | |
--- a/mm/memory.c | |
+++ b/mm/memory.c | |
@@ -72,6 +72,10 @@ | |
#include "internal.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS | |
#warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_cpupid. | |
#endif | |
@@ -1283,6 +1287,10 @@ static void unmap_single_vma(struct mmu_gather *tlb, | |
if (end <= vma->vm_start) | |
return; | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->unmap_vma)(vma); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
if (vma->vm_file) | |
uprobe_munmap(vma, start, end); | |
@@ -2621,6 +2629,16 @@ out_release: | |
return ret; | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+struct page * | |
+neon_follow_page(struct vm_area_struct *vma, | |
+ unsigned long address) | |
+{ | |
+ return follow_page(vma, address, 0); | |
+} | |
+EXPORT_SYMBOL(neon_follow_page); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
/* | |
* This is like a special single-page "expand_{down|up}wards()", | |
* except we must first make sure that 'address{-|+}PAGE_SIZE' | |
@@ -3590,6 +3608,109 @@ int follow_pfn(struct vm_area_struct *vma, unsigned long address, | |
} | |
EXPORT_SYMBOL(follow_pfn); | |
+#ifdef CONFIG_NEON_FACE | |
+static int | |
+__neon_follow_pte(struct mm_struct *mm, | |
+ unsigned long address, | |
+ pte_t **ptepp, | |
+ spinlock_t **ptlp) | |
+{ | |
+ pgd_t *pgd; | |
+ pud_t *pud; | |
+ pmd_t *pmd; | |
+ pte_t *ptep; | |
+ | |
+ pgd = pgd_offset(mm, address); | |
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | |
+ return 1; | |
+ | |
+ pud = pud_offset(pgd, address); | |
+ if (pud_none(*pud) || unlikely(pud_bad(*pud))) | |
+ return 2; | |
+ | |
+ pmd = pmd_offset(pud, address); | |
+ VM_BUG_ON(pmd_trans_huge(*pmd)); | |
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | |
+ return 3; | |
+ | |
+ /* We cannot handle huge page PFN maps. Luckily they don't exist. */ | |
+ if (pmd_huge(*pmd)) | |
+ return 4; | |
+ | |
+ ptep = pte_offset_map_lock(mm, pmd, address, ptlp); | |
+ if (!ptep) { | |
+ return 5; | |
+ } | |
+ // Present or not, I don't care, just give me the PTE | |
+ | |
+ *ptepp = ptep; | |
+ | |
+ return 0; | |
+} | |
+ | |
+static inline int | |
+_neon_follow_pte(struct mm_struct *mm, | |
+ unsigned long address, | |
+ pte_t **ptepp, | |
+ spinlock_t **ptlp) | |
+{ | |
+ int res = 0; | |
+ | |
+ /* (void) is needed to make gcc happy */ | |
+ (void) __cond_lock(*ptlp, | |
+ !(res = __neon_follow_pte(mm, address, ptepp, ptlp))); | |
+ return res; | |
+} | |
+ | |
+/** | |
+ * neon_follow_pte - look up PTE of a user virtual address | |
+ * @vma: memory mapping | |
+ * @address: user virtual address | |
+ * @pte: location to store found PTE | |
+ * | |
+ * Only IO mappings and raw PFN mappings are allowed. | |
+ * | |
+ * Returns zero and the pfn at @pte on success, -ve otherwise. | |
+ */ | |
+int neon_follow_pte(struct vm_area_struct *vma, | |
+ unsigned long address, | |
+ pte_t **ptep) | |
+{ | |
+ int ret = -EINVAL; | |
+ spinlock_t *ptl; | |
+ | |
+ ret = _neon_follow_pte(vma->vm_mm, address, ptep, &ptl); | |
+ if(ret) { | |
+ (*neon_face->tweet)("cannot FOLLOW : address not found in vma_mm"); | |
+ switch(ret) { | |
+ case 1: | |
+ (*neon_face->tweet)("(pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))"); | |
+ break; | |
+ case 2: | |
+ (*neon_face->tweet)("(pud_none(*pud) || unlikely(pud_bad(*pud)))"); | |
+ break; | |
+ case 3: | |
+ (*neon_face->tweet)("(pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))"); | |
+ break; | |
+ case 4: | |
+ (*neon_face->tweet)("(pmd_huge(*pmd))"); | |
+ break; | |
+ case 5: | |
+ (*neon_face->tweet)("(ptep = pte_offset_map_lock(mm, pmd, address, ptlp)) == NULL"); | |
+ break; | |
+ default: | |
+ (*neon_face->tweet)("cannot FOLLOW : dunno what happened"); | |
+ break; | |
+ } | |
+ return -EINVAL; | |
+ } | |
+ pte_unmap_unlock(*ptep, ptl); | |
+ | |
+ return 0; | |
+} | |
+EXPORT_SYMBOL(neon_follow_pte); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#ifdef CONFIG_HAVE_IOREMAP_PROT | |
int follow_phys(struct vm_area_struct *vma, | |
unsigned long address, unsigned int flags, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/kernel/nv-mlock.c b/kernel/nv-mlock.c | |
index 0f795a5..7b5a32a 100644 | |
--- a/kernel/nv-mlock.c | |
+++ b/kernel/nv-mlock.c | |
@@ -14,6 +14,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
RM_STATUS NV_API_CALL nv_lock_user_pages( | |
nv_state_t *nv, | |
void *address, | |
@@ -88,6 +92,15 @@ RM_STATUS NV_API_CALL nv_lock_user_pages( | |
} | |
*private = user_pages; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("PIN-PAGES"); | |
+ (*neon_face->pin_pages)(address, | |
+ user_pages, | |
+ pte_array, | |
+ page_count); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
return RM_OK; | |
#else | |
return RM_ERR_NOT_SUPPORTED; | |
@@ -108,6 +121,13 @@ RM_STATUS NV_API_CALL nv_unlock_user_pages( | |
struct page **user_pages = private; | |
NvU32 i; | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("UNPIN-PAGES"); | |
+ (*neon_face->unpin_pages)(user_pages, | |
+ pte_array, | |
+ page_count); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
for (i = 0; i < page_count; i++) | |
{ | |
pci_unmap_page(dev, pte_array[i], | |
diff --git a/kernel/nv-mmap.c b/kernel/nv-mmap.c | |
index 0c976f9..6239f8c 100644 | |
--- a/kernel/nv-mmap.c | |
+++ b/kernel/nv-mmap.c | |
@@ -14,6 +14,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
/* | |
* The 'struct vm_operations' open() callback is called by the Linux | |
* kernel when the parent VMA is split or copied, close() when the | |
@@ -293,6 +297,16 @@ int nv_kern_mmap( | |
} | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ // I/O space | |
+ (*neon_face->tweet)("MMAP-ISREG"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_REGISTER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
else if (IS_FB_OFFSET(nv, NV_VMA_OFFSET(vma), NV_VMA_SIZE(vma))) | |
{ | |
@@ -327,6 +341,15 @@ int nv_kern_mmap( | |
} | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISFB"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_FRAMEBUFFER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
#if defined(NVCPU_X86) || defined(NVCPU_X86_64) | |
else if (IS_AGP_OFFSET(nv, NV_VMA_OFFSET(vma), NV_VMA_SIZE(vma))) | |
@@ -378,6 +401,15 @@ int nv_kern_mmap( | |
nv_vm_list_page_count(&at->page_table[i], pages); | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISFB"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_FRAMEBUFFER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
#endif | |
else | |
@@ -466,6 +498,15 @@ int nv_kern_mmap( | |
vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED); | |
vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISMEM"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_SYSTEM); | |
+#endif // CONFIG_NEON_FACE | |
} | |
NV_VMA_FILE(vma) = file; | |
diff --git a/kernel/nv.c b/kernel/nv.c | |
index 7c9bb1f..4f67c9c 100644 | |
--- a/kernel/nv.c | |
+++ b/kernel/nv.c | |
@@ -17,6 +17,10 @@ | |
#include "rmil.h" | |
#include "nv-pat.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#if defined(MODULE_LICENSE) | |
MODULE_LICENSE("NVIDIA"); | |
#endif | |
@@ -1846,6 +1850,9 @@ int nv_kern_ioctl( | |
void *arg_copy = NULL; | |
size_t arg_size; | |
int arg_cmd; | |
+#ifdef CONFIG_NEON_FACE | |
+ void *neon_arg_pre = NULL; | |
+#endif // CONFIG_NEON_FACE | |
nv_printf(NV_DBG_INFO, "NVRM: ioctl(0x%x, 0x%x, 0x%x)\n", | |
_IOC_NR(cmd), (unsigned int) i_arg, _IOC_SIZE(cmd)); | |
@@ -1903,6 +1910,26 @@ int nv_kern_ioctl( | |
goto done; | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+ NV_KMALLOC(neon_arg_pre, arg_size); | |
+ if (neon_arg_pre == NULL) { | |
+ nv_printf(NV_DBG_ERRORS, "NVRM: failed to allocate ioctl memory\n"); | |
+ (*neon_face->tweet)("neon_arg_pre kmalloc failed"); | |
+ status = -ENOMEM; | |
+ goto done; | |
+ } else { | |
+ void *check = NULL; | |
+ check = memcpy(neon_arg_pre, arg_copy, arg_size); | |
+ if (check != neon_arg_pre) { | |
+ nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy kernel data\n"); | |
+ (*neon_face->tweet)("neon_arg_pre memcpy failed"); | |
+ status = -EFAULT; | |
+ goto done; | |
+ } | |
+ } | |
+ (*neon_face->ioctl)(arg_cmd, arg_copy, NULL); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
switch (arg_cmd) | |
{ | |
/* pass out info about the card */ | |
@@ -2002,6 +2029,11 @@ int nv_kern_ioctl( | |
} | |
done: | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->ioctl)(arg_cmd, neon_arg_pre, arg_copy); | |
+ NV_KFREE(neon_arg_pre, arg_size); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_IOCTL]); | |
if (arg_copy != NULL) | |
{ | |
@@ -3754,3 +3786,43 @@ RM_STATUS NV_API_CALL nv_log_error( | |
#endif | |
return status; | |
} | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+void | |
+neon_kern_probe(unsigned long long *buf) | |
+{ | |
+ unsigned int i = 0; | |
+ nv_linux_state_t *nvl = nv_linux_devices; | |
+ | |
+ while (nvl != NULL && i < 2 * NV_MAX_DEVICES) { | |
+ nv_state_t *nv = NV_STATE_PTR(nvl); | |
+ if(buf == NULL) { | |
+ // query-print mode | |
+ nv_printf(NV_DBG_INFO, | |
+ "NVRM: PCI:%04x:%02x:%02x (%04x:%04x%04x): BAR0 @ 0x%llx (%lluMB)\n", | |
+ nv->domain, nv->bus, nv->slot, | |
+ nv->vendor_id, nv->device_id, nv->subsystem_id, nv->regs->address, | |
+ (nv->regs->size >> 20)); | |
+ nv_printf(NV_DBG_INFO, | |
+ "NVRM: PCI:%04x:%02x:%02x (%04x:%04x:%04x): BAR1 @ 0x%llx (%lluMB)\n", | |
+ nv->domain, nv->bus, nv->slot, | |
+ nv->vendor_id, nv->device_id, nv->subsystem_id, nv->fb->address, | |
+ (nv->fb->size >> 20)); | |
+ } else { | |
+ // query-save mode | |
+ buf[i+0] = (unsigned long long) nv->bars[NV_GPU_BAR_INDEX_REGS].address; | |
+ buf[i+1] = (unsigned long long) nv->bars[NV_GPU_BAR_INDEX_REGS].size; | |
+ buf[i+2] = (unsigned long long) nv->fb->address; | |
+ buf[i+3] = (unsigned long long) nv->fb->size; | |
+ buf[i+4] = (unsigned long long) nv->vendor_id; | |
+ buf[i+5] = (unsigned long long) nv->device_id; | |
+ buf[i+6] = (unsigned long long) nv->subsystem_id; | |
+ } | |
+ nvl = nvl->next; | |
+ i+=7; | |
+ } | |
+ | |
+ return; | |
+} | |
+EXPORT_SYMBOL(neon_kern_probe); | |
+#endif // CONFIG_NEON_FACE | |
diff --git a/kernel/nv.h b/kernel/nv.h | |
index 2e2e197..625f745 100644 | |
--- a/kernel/nv.h | |
+++ b/kernel/nv.h | |
@@ -669,4 +669,8 @@ static inline int nv_count_bits(NvU64 word) | |
return (int)(bits); | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+void neon_kern_probe(unsigned long long *buf); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#endif | |
diff --git a/kernel/os-interface.c b/kernel/os-interface.c | |
index 12ac547..9b2364b 100644 | |
--- a/kernel/os-interface.c | |
+++ b/kernel/os-interface.c | |
@@ -25,6 +25,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
void NV_API_CALL os_disable_preemption(void) | |
{ | |
#if defined(preempt_disable) | |
@@ -845,9 +849,13 @@ RM_STATUS NV_API_CALL os_get_current_thread(NvU64 *threadId) | |
/* */ | |
/*******************************************************************************/ | |
- | |
+#ifndef CONFIG_NEON_FACE | |
// The current debug display level (default to maximum debug level) | |
NvU32 cur_debuglevel = 0xffffffff; | |
+# else // CONFIG_NEON_FACE | |
+NvU32 cur_debuglevel = DBG_LEVEL_INFO; | |
+// NvU32 cur_debuglevel = 0xffffffff; | |
+#endif // CONFIG_NEON_FACE | |
// | |
@@ -865,7 +873,12 @@ inline void NV_API_CALL out_string(const char *str) | |
} | |
else | |
#endif | |
+#ifdef CONFIG_NEON_FACE | |
+ // log this message | |
+ (*neon_face->tweet)(str); | |
+#else // !CONFIG_NEON_FACE | |
printk("%s", str); | |
+#endif // CONFIG_NEON_FACE | |
#if defined(DEBUG) | |
if (NV_NUM_CPUS() > 1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mlock.c b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mlock.c | |
index 0f795a5..7b5a32a 100644 | |
--- a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mlock.c | |
+++ b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mlock.c | |
@@ -14,6 +14,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
RM_STATUS NV_API_CALL nv_lock_user_pages( | |
nv_state_t *nv, | |
void *address, | |
@@ -88,6 +92,15 @@ RM_STATUS NV_API_CALL nv_lock_user_pages( | |
} | |
*private = user_pages; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("PIN-PAGES"); | |
+ (*neon_face->pin_pages)(address, | |
+ user_pages, | |
+ pte_array, | |
+ page_count); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
return RM_OK; | |
#else | |
return RM_ERR_NOT_SUPPORTED; | |
@@ -108,6 +121,13 @@ RM_STATUS NV_API_CALL nv_unlock_user_pages( | |
struct page **user_pages = private; | |
NvU32 i; | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("UNPIN-PAGES"); | |
+ (*neon_face->unpin_pages)(user_pages, | |
+ pte_array, | |
+ page_count); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
for (i = 0; i < page_count; i++) | |
{ | |
pci_unmap_page(dev, pte_array[i], | |
diff --git a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mmap.c b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mmap.c | |
index 0c976f9..6239f8c 100644 | |
--- a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mmap.c | |
+++ b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv-mmap.c | |
@@ -14,6 +14,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
/* | |
* The 'struct vm_operations' open() callback is called by the Linux | |
* kernel when the parent VMA is split or copied, close() when the | |
@@ -293,6 +297,16 @@ int nv_kern_mmap( | |
} | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ // I/O space | |
+ (*neon_face->tweet)("MMAP-ISREG"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_REGISTER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
else if (IS_FB_OFFSET(nv, NV_VMA_OFFSET(vma), NV_VMA_SIZE(vma))) | |
{ | |
@@ -327,6 +341,15 @@ int nv_kern_mmap( | |
} | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISFB"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_FRAMEBUFFER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
#if defined(NVCPU_X86) || defined(NVCPU_X86_64) | |
else if (IS_AGP_OFFSET(nv, NV_VMA_OFFSET(vma), NV_VMA_SIZE(vma))) | |
@@ -378,6 +401,15 @@ int nv_kern_mmap( | |
nv_vm_list_page_count(&at->page_table[i], pages); | |
vma->vm_flags |= VM_IO; | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISFB"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_FRAMEBUFFER); | |
+#endif // CONFIG_NEON_FACE | |
} | |
#endif | |
else | |
@@ -466,6 +498,15 @@ int nv_kern_mmap( | |
vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED); | |
vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->tweet)("MMAP-ISMEM"); | |
+ (*neon_face->map_pages)(vma, | |
+ vma->vm_start, | |
+ NV_VMA_OFFSET(vma), | |
+ NV_VMA_SIZE(vma), | |
+ NEON_SYSTEM); | |
+#endif // CONFIG_NEON_FACE | |
} | |
NV_VMA_FILE(vma) = file; | |
diff --git a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.c b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.c | |
index 7c9bb1f..4f67c9c 100644 | |
--- a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.c | |
+++ b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.c | |
@@ -17,6 +17,10 @@ | |
#include "rmil.h" | |
#include "nv-pat.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include "neon/neon_face.h" | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#if defined(MODULE_LICENSE) | |
MODULE_LICENSE("NVIDIA"); | |
#endif | |
@@ -1846,6 +1850,9 @@ int nv_kern_ioctl( | |
void *arg_copy = NULL; | |
size_t arg_size; | |
int arg_cmd; | |
+#ifdef CONFIG_NEON_FACE | |
+ void *neon_arg_pre = NULL; | |
+#endif // CONFIG_NEON_FACE | |
nv_printf(NV_DBG_INFO, "NVRM: ioctl(0x%x, 0x%x, 0x%x)\n", | |
_IOC_NR(cmd), (unsigned int) i_arg, _IOC_SIZE(cmd)); | |
@@ -1903,6 +1910,26 @@ int nv_kern_ioctl( | |
goto done; | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+ NV_KMALLOC(neon_arg_pre, arg_size); | |
+ if (neon_arg_pre == NULL) { | |
+ nv_printf(NV_DBG_ERRORS, "NVRM: failed to allocate ioctl memory\n"); | |
+ (*neon_face->tweet)("neon_arg_pre kmalloc failed"); | |
+ status = -ENOMEM; | |
+ goto done; | |
+ } else { | |
+ void *check = NULL; | |
+ check = memcpy(neon_arg_pre, arg_copy, arg_size); | |
+ if (check != neon_arg_pre) { | |
+ nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy kernel data\n"); | |
+ (*neon_face->tweet)("neon_arg_pre memcpy failed"); | |
+ status = -EFAULT; | |
+ goto done; | |
+ } | |
+ } | |
+ (*neon_face->ioctl)(arg_cmd, arg_copy, NULL); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
switch (arg_cmd) | |
{ | |
/* pass out info about the card */ | |
@@ -2002,6 +2029,11 @@ int nv_kern_ioctl( | |
} | |
done: | |
+#ifdef CONFIG_NEON_FACE | |
+ (*neon_face->ioctl)(arg_cmd, neon_arg_pre, arg_copy); | |
+ NV_KFREE(neon_arg_pre, arg_size); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_IOCTL]); | |
if (arg_copy != NULL) | |
{ | |
@@ -3754,3 +3786,43 @@ RM_STATUS NV_API_CALL nv_log_error( | |
#endif | |
return status; | |
} | |
+ | |
+#ifdef CONFIG_NEON_FACE | |
+void | |
+neon_kern_probe(unsigned long long *buf) | |
+{ | |
+ unsigned int i = 0; | |
+ nv_linux_state_t *nvl = nv_linux_devices; | |
+ | |
+ while (nvl != NULL && i < 2 * NV_MAX_DEVICES) { | |
+ nv_state_t *nv = NV_STATE_PTR(nvl); | |
+ if(buf == NULL) { | |
+ // query-print mode | |
+ nv_printf(NV_DBG_INFO, | |
+ "NVRM: PCI:%04x:%02x:%02x (%04x:%04x%04x): BAR0 @ 0x%llx (%lluMB)\n", | |
+ nv->domain, nv->bus, nv->slot, | |
+ nv->vendor_id, nv->device_id, nv->subsystem_id, nv->regs->address, | |
+ (nv->regs->size >> 20)); | |
+ nv_printf(NV_DBG_INFO, | |
+ "NVRM: PCI:%04x:%02x:%02x (%04x:%04x:%04x): BAR1 @ 0x%llx (%lluMB)\n", | |
+ nv->domain, nv->bus, nv->slot, | |
+ nv->vendor_id, nv->device_id, nv->subsystem_id, nv->fb->address, | |
+ (nv->fb->size >> 20)); | |
+ } else { | |
+ // query-save mode | |
+ buf[i+0] = (unsigned long long) nv->bars[NV_GPU_BAR_INDEX_REGS].address; | |
+ buf[i+1] = (unsigned long long) nv->bars[NV_GPU_BAR_INDEX_REGS].size; | |
+ buf[i+2] = (unsigned long long) nv->fb->address; | |
+ buf[i+3] = (unsigned long long) nv->fb->size; | |
+ buf[i+4] = (unsigned long long) nv->vendor_id; | |
+ buf[i+5] = (unsigned long long) nv->device_id; | |
+ buf[i+6] = (unsigned long long) nv->subsystem_id; | |
+ } | |
+ nvl = nvl->next; | |
+ i+=7; | |
+ } | |
+ | |
+ return; | |
+} | |
+EXPORT_SYMBOL(neon_kern_probe); | |
+#endif // CONFIG_NEON_FACE | |
diff --git a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.h b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.h | |
index 2e2e197..625f745 100644 | |
--- a/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.h | |
+++ b/linux/NVIDIA-Linux-x86_64-304.137/kernel/nv.h | |
@@ -669,4 +669,8 @@ static inline int nv_count_bits(NvU64 word) | |
return (int)(bits); | |
} | |
+#ifdef CONFIG_NEON_FACE | |
+void neon_kern_probe(unsigned long long *buf); | |
+#endif // CONFIG_NEON_FACE | |
+ | |
#endif | |
diff --git a/linux/NVIDIA-Linux-x86_64-304.137/kernel/os-interface.c b/linux/NVIDIA-Linux-x86_64-304.137/kernel/os-interface.c | |
index 12ac547..9b2364b 100644 | |
--- a/linux/NVIDIA-Linux-x86_64-304.137/kernel/os-interface.c | |
+++ b/linux/NVIDIA-Linux-x86_64-304.137/kernel/os-interface.c | |
@@ -25,6 +25,10 @@ | |
#include "os-interface.h" | |
#include "nv-linux.h" | |
+#ifdef CONFIG_NEON_FACE | |
+#include <neon/neon_face.h> | |
+#endif // CONFIG_NEON_FACE | |
+ | |
void NV_API_CALL os_disable_preemption(void) | |
{ | |
#if defined(preempt_disable) | |
@@ -845,9 +849,13 @@ RM_STATUS NV_API_CALL os_get_current_thread(NvU64 *threadId) | |
/* */ | |
/*******************************************************************************/ | |
- | |
+#ifndef CONFIG_NEON_FACE | |
// The current debug display level (default to maximum debug level) | |
NvU32 cur_debuglevel = 0xffffffff; | |
+# else // CONFIG_NEON_FACE | |
+NvU32 cur_debuglevel = DBG_LEVEL_INFO; | |
+// NvU32 cur_debuglevel = 0xffffffff; | |
+#endif // CONFIG_NEON_FACE | |
// | |
@@ -865,7 +873,12 @@ inline void NV_API_CALL out_string(const char *str) | |
} | |
else | |
#endif | |
+#ifdef CONFIG_NEON_FACE | |
+ // log this message | |
+ (*neon_face->tweet)(str); | |
+#else // !CONFIG_NEON_FACE | |
printk("%s", str); | |
+#endif // CONFIG_NEON_FACE | |
#if defined(DEBUG) | |
if (NV_NUM_CPUS() > 1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment