Skip to content

Instantly share code, notes, and snippets.

@pothos
Created January 3, 2018 04:52
Show Gist options
  • Save pothos/9f0b85abb15b7dd0600730ee3c693699 to your computer and use it in GitHub Desktop.
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)
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,
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)
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