From: Gary King Date: Wed, 25 Aug 2010 02:06:58 +0000 (-0700) Subject: [ARM] tegra: nvrm: remove AVP module relocation X-Git-Tag: firefly_0821_release~9834^2~627 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=31f9e3abebdcfeead74175b529ec2e0090bcfd0e;p=firefly-linux-kernel-4.4.55.git [ARM] tegra: nvrm: remove AVP module relocation Change-Id: I8ba0907f7c1dec77e7ca3f22874837cf044300a2 Signed-off-by: Dima Zavin --- diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index ee7c43588220..d79c6c89d056 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h @@ -102,6 +102,9 @@ #define TEGRA_APB_DMA_CH0_BASE 0x6000B000 #define TEGRA_APB_DMA_CH0_SIZE 32 +#define TEGRA_AVP_CACHE_BASE 0x6000C000 +#define TEGRA_AVP_CACHE_SIZE 4 + #define TEGRA_AHB_GIZMO_BASE 0x6000C004 #define TEGRA_AHB_GIZMO_SIZE 0x10C diff --git a/arch/arm/mach-tegra/nv/include/nvrm_moduleloader.h b/arch/arm/mach-tegra/nv/include/nvrm_moduleloader.h index ab8761c970c3..6214a1ac1413 100644 --- a/arch/arm/mach-tegra/nv/include/nvrm_moduleloader.h +++ b/arch/arm/mach-tegra/nv/include/nvrm_moduleloader.h @@ -50,6 +50,7 @@ typedef enum { NvRmModuleLoaderReason_Attach = 0, NvRmModuleLoaderReason_Detach, + NvRmModuleLoaderReason_AttachGreedy, NvRmModuleLoaderReason_Num, NvRmModuleLoaderReason_Force32 = 0x7FFFFFFF } NvRmModuleLoaderReason; diff --git a/arch/arm/mach-tegra/nv/nvrm/core/ap15/ap15rm_avp_service.c b/arch/arm/mach-tegra/nv/nvrm/core/ap15/ap15rm_avp_service.c index d4094aee63a5..f632410cd9a7 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/ap15/ap15rm_avp_service.c +++ b/arch/arm/mach-tegra/nv/nvrm/core/ap15/ap15rm_avp_service.c @@ -35,6 +35,7 @@ #include #include #include + #include #include #include @@ -56,22 +57,14 @@ #include "mach/io.h" #include "mach/iomap.h" -static NvU32 s_AvpInitialized = NV_FALSE; -static NvRmLibraryHandle s_hAvpLibrary = NULL; - -#define _TEGRA_AVP_RESET_VECTOR_ADDR \ - (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + EVP_COP_RESET_VECTOR_0) - #define NV_USE_AOS 1 -#define AVP_EXECUTABLE_NAME "nvrm_avp.axf" - void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int messageLength) { NvError Error = NvSuccess; NvRmMemHandle hMem; - switch ((NvRmMsg)*pRecvMessage) { + switch (*(NvRmMsg *)pRecvMessage) { case NvRmMsg_MemHandleCreate: { @@ -107,7 +100,7 @@ void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int me NvRmMessage_Response msgResponse; msgMemAlloc = (NvRmMessage_MemAlloc*)pRecvMessage; - Error = NvRmMemAlloc(msgMemAlloc->hMem, + Error = NvRmMemAlloc(msgMemAlloc->hMem, (msgMemAlloc->NumHeaps == 0) ? NULL : msgMemAlloc->Heaps, msgMemAlloc->NumHeaps, msgMemAlloc->Alignment, @@ -267,175 +260,15 @@ void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int me NvRmMessage_RemotePrintf *msg; msg = (NvRmMessage_RemotePrintf*)pRecvMessage; - NvOsDebugPrintf("AVP: %s", msg->string); + printk("AVP: %s", msg->string); } break; case NvRmMsg_AVP_Reset: NvOsDebugPrintf("AVP has been reset by WDT\n"); break; default: - NV_ASSERT( !"AVP Service::ProcessMessage: bad message" ); - break; + panic("AVP Service::ProcessMessage: bad message"); + break; } } -NvError -NvRmPrivInitAvp(NvRmDeviceHandle hDevice) -{ - NvError err = NvSuccess; - void* avpExecutionJumpAddress; - NvU32 RegVal, resetVector; - - // Do this only once. - if (s_AvpInitialized) return NvSuccess; - - NvOsDebugPrintf("%s : called\n", __func__); - - err = NvRmPrivLoadKernelLibrary(hDevice, AVP_EXECUTABLE_NAME, &s_hAvpLibrary); - if (err != NvSuccess) { - NV_DEBUG_PRINTF(("AVP executable file not found\n")); - NV_ASSERT(!"AVP executable file not found"); - } - - err = NvRmGetProcAddress(s_hAvpLibrary, "main", &avpExecutionJumpAddress); - NV_ASSERT(err == NvSuccess); - NvOsDebugPrintf("%s : avpExecutionJumpAddress=%x\n", __func__, avpExecutionJumpAddress); - - resetVector = (NvU32)avpExecutionJumpAddress & 0xFFFFFFFE; - - NV_WRITE32(_TEGRA_AVP_RESET_VECTOR_ADDR, resetVector); - RegVal = NV_READ32(_TEGRA_AVP_RESET_VECTOR_ADDR); - NV_ASSERT( RegVal == resetVector ); - - NvRmModuleReset(hDevice, NvRmModuleID_Avp); - - /// Resume AVP - RegVal = NV_DRF_DEF(FLOW_CTLR, HALT_COP_EVENTS, MODE, FLOW_MODE_NONE); - NV_WRITE32(IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTLR_HALT_COP_EVENTS_0, RegVal); - - s_AvpInitialized = NV_TRUE; - - err = NvRmPrivInitService(hDevice); - if (err) return err; - - err = NvRmPrivInitModuleLoaderRPC(hDevice); - if (err) return err; - - return err; -} - -static void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE); -static void __iomem *iram_backup; -static dma_addr_t iram_backup_addr; -static u32 iram_size = TEGRA_IRAM_SIZE; -static u32 iram_backup_size = TEGRA_IRAM_SIZE + 4; -static u32 avp_resume_addr; - -NvError -NvRmPrivSuspendAvp(NvRmRPCHandle hRPCHandle) -{ - NvError err = NvSuccess; - NvRmMessage_InitiateLP0 lp0_msg; - void *avp_suspend_done = iram_backup + iram_size; - unsigned long timeout; - - pr_info("%s()+\n", __func__); - - if (!s_AvpInitialized) - goto done; - else if (!iram_backup_addr) { - /* XXX: should we return error? */ - pr_warning("%s: iram backup ram missing, not suspending avp\n", - __func__); - goto done; - } - - NV_ASSERT(hRPCHandle->svcTransportHandle != NULL); - - lp0_msg.msg = NvRmMsg_InitiateLP0; - lp0_msg.sourceAddr = (u32)TEGRA_IRAM_BASE; - lp0_msg.bufferAddr = (u32)iram_backup_addr; - lp0_msg.bufferSize = (u32)iram_size; - - writel(0, avp_suspend_done); - - NvOsMutexLock(hRPCHandle->RecvLock); - err = NvRmTransportSendMsg(hRPCHandle->svcTransportHandle, &lp0_msg, - sizeof(lp0_msg), 1000); - NvOsMutexUnlock(hRPCHandle->RecvLock); - - if (err != NvSuccess) { - pr_err("%s: cannot send AVP LP0 message\n", __func__); - goto done; - } - - timeout = jiffies + msecs_to_jiffies(1000); - while (!readl(avp_suspend_done) && time_before(jiffies, timeout)) { - udelay(10); - cpu_relax(); - } - - if (!readl(avp_suspend_done)) { - pr_err("%s: AVP failed to suspend\n", __func__); - err = NvError_Timeout; - goto done; - } - - avp_resume_addr = readl(iram_base); - if (!avp_resume_addr) { - pr_err("%s: AVP failed to set it's resume address\n", __func__); - err = NvError_InvalidState; - goto done; - } - - pr_info("avp_suspend: resume_addr=%x\n", avp_resume_addr); - avp_resume_addr &= 0xFFFFFFFE; - - pr_info("%s()-\n", __func__); - -done: - return err; -} - -NvError -NvRmPrivResumeAvp(NvRmRPCHandle hRPCHandle) -{ - NvError ret = NvSuccess; - u32 tmp; - - pr_info("%s()+\n", __func__); - if (!s_AvpInitialized || !avp_resume_addr) - goto done; - - writel(avp_resume_addr, _TEGRA_AVP_RESET_VECTOR_ADDR); - tmp = readl(_TEGRA_AVP_RESET_VECTOR_ADDR); - NV_ASSERT(tmp == resetVector); - - NvRmModuleReset(hRPCHandle->hRmDevice, NvRmModuleID_Avp); - - /// Resume AVP - tmp = NV_DRF_DEF(FLOW_CTLR, HALT_COP_EVENTS, MODE, FLOW_MODE_NONE); - writel(tmp, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTLR_HALT_COP_EVENTS_0); - - /* clear the avp resume addr so that if suspend fails, we don't try to - * resume */ - avp_resume_addr = 0; - - pr_info("%s()-\n", __func__); - -done: - return ret; -} - -int __init _avp_suspend_resume_init(void) -{ - /* allocate an iram sized chunk of ram to give to the AVP */ - iram_backup = dma_alloc_coherent(NULL, iram_backup_size, - &iram_backup_addr, GFP_KERNEL); - if (!iram_backup) { - pr_err("%s: Unable to allocate iram backup mem\n", __func__); - return -ENOMEM; - } - - return 0; -} diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/Makefile b/arch/arm/mach-tegra/nv/nvrm/core/common/Makefile index eb84beed8bdd..4cec50329619 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/common/Makefile +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/Makefile @@ -10,6 +10,7 @@ ccflags-y += -Iarch/arm/mach-tegra/nv/include ccflags-y += -Iarch/arm/mach-tegra/nv/nvrm/core/common ccflags-y += -Iarch/arm/mach-tegra/nv/nvrm/core +obj-y += headavp.o obj-y += nvrm_avp_cpu_rpc.o obj-y += nvrm_moduleloader.o obj-y += nvrm_rmctrace.o diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.S b/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.S new file mode 100644 index 000000000000..fee956431af8 --- /dev/null +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.S @@ -0,0 +1,66 @@ +/* + * arch/arm/mach-tegra/headavp.S + * + * AVP kernel launcher stub; programs the AVP MMU and jumps to the + * kernel code. Must use ONLY ARMv4 instructions, and must be compiled + * in ARM mode. + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include "headavp.h" + +#define PTE0_COMPARE 0 +/* the default translation will translate any VA within + * 0x0010:0000..0x001f:ffff to the (megabyte-aligned) value written to + * _tegra_avp_launcher_stub_data[AVP_LAUNCHER_MMU_PHYSICAL] + */ + #define PTE0_DEFAULT (0x00100000 | 0x3ff0) + +#define PTE0_TRANSLATE 4 + + #define TRANSLATE_DATA (1 << 11) + #define TRANSLATE_CODE (1 << 10) + #define TRANSLATE_WR (1 << 9) + #define TRANSLATE_RD (1 << 8) + #define TRANSLATE_HIT (1 << 7) + #define TRANSLATE_EN (1 << 2) + +#define TRANSLATE_OPT (TRANSLATE_DATA | TRANSLATE_CODE | TRANSLATE_WR | \ + TRANSLATE_RD | TRANSLATE_HIT) + +ENTRY(_tegra_avp_launcher_stub) + adr r4, _tegra_avp_launcher_stub_data + ldmia r4, {r0-r3} + str r2, [r0, #PTE0_COMPARE] + bic r3, r3, #0xff0 + bic r3, r3, #0x00f + orr r3, r3, #TRANSLATE_OPT + orr r3, r3, #TRANSLATE_EN + str r3, [r0, #PTE0_TRANSLATE] + bx r1 + b . +ENDPROC(_tegra_avp_launcher_stub) + .type _tegra_avp_launcher_stub_data, %object +ENTRY(_tegra_avp_launcher_stub_data) + .long AVP_MMU_TLB_BASE + .long 0xdeadbeef + .long PTE0_DEFAULT + .long 0xdeadd00d + .size _tegra_avp_launcher_stub_data, . - _tegra_avp_launcher_stub_data diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.h b/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.h new file mode 100644 index 000000000000..a4121ee4144c --- /dev/null +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/headavp.h @@ -0,0 +1,39 @@ +/* + * arch/arm/mach-tegra/headavp.h + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _MACH_TEGRA_HEADAVP_H +#define _MACH_TEGRA_HEADAVP_H + +#define AVP_MMU_TLB_BASE 0xF000F000 + +#define AVP_LAUNCHER_START_VA 1 +#define AVP_LAUNCHER_MMU_VIRTUAL 2 +#define AVP_LAUNCHER_MMU_PHYSICAL 3 + +#define EVP_COP_RESET 0x200 +#define FLOW_CTRL_HALT_COP 0x4 + +#ifndef __ASSEMBLY__ +extern void _tegra_avp_launcher_stub(void); +extern u32 _tegra_avp_launcher_stub_data[]; + +#endif + +#endif diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_message.h b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_message.h index 0fe59dbf293a..28ead1029339 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_message.h +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_message.h @@ -121,7 +121,7 @@ typedef struct{ typedef struct{ NvRmMsg msg; NvRmMemHandle hMem; - NvRmHeap Heaps[NvRmHeap_Num]; + NvRmHeap Heaps[4]; NvU32 NumHeaps; NvU32 Alignment; NvOsMemAttribute Coherency; @@ -244,21 +244,23 @@ typedef struct{ typedef struct{ NvRmMsg msg; - NvU32 entryAddress; + NvU32 address; NvU32 size; + NvU32 filesize; char args[MAX_ARGS_SIZE]; NvU32 reason; }NvRmMessage_AttachModule; -typedef struct{ +typedef struct { NvRmMsg msg; NvError error; + NvU32 libraryId; }NvRmMessage_AttachModuleResponse; -typedef struct{ +typedef struct { NvRmMsg msg; NvU32 reason; - NvU32 entryAddress; + NvU32 libraryId; }NvRmMessage_DetachModule; typedef struct{ diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c index 2616fe009dff..5daf19cfd8a6 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,6 +34,7 @@ #include #include #include +#include #include #include "nvcommon.h" @@ -46,30 +49,45 @@ #include "nvrm_graphics_private.h" #include "nvrm_structure.h" #include "nvfw.h" +#include "ap15/arflow_ctlr.h" +#include "ap15/arevp.h" +#include "mach/io.h" +#include "mach/iomap.h" +#include "headavp.h" #define DEVICE_NAME "nvfw" +#define _TEGRA_AVP_RESET_VECTOR_ADDR \ + (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + EVP_COP_RESET_VECTOR_0) + static const struct firmware *s_FwEntry; static NvRmRPCHandle s_RPCHandle = NULL; +static NvRmMemHandle s_KernelImage = NULL; static NvError SendMsgDetachModule(NvRmLibraryHandle hLibHandle); -static NvError SendMsgAttachModule(NvRmLibraryHandle *hLibHandle, - void* pArgs, - NvU32 sizeOfArgs); +static NvError SendMsgAttachModule( + NvRmLibraryHandle hLibHandle, + void* pArgs, + NvU32 loadAddress, + NvU32 fileSize, + NvBool greedy, + NvU32 sizeOfArgs); NvU32 NvRmModuleGetChipId(NvRmDeviceHandle hDevice); NvError NvRmPrivInitModuleLoaderRPC(NvRmDeviceHandle hDevice); void NvRmPrivDeInitModuleLoaderRPC(void); +static NvError NvRmPrivInitAvp(NvRmDeviceHandle hDevice); + +#define AVP_KERNEL_SIZE_MAX SZ_1M #define ADD_MASK 0x00000001 #define SUB_MASK 0xFFFFFFFD -// For the elf to be relocatable, we need atleast 2 program segments -// Although even elfs with more than 1 program segment may not be relocatable. -#define MIN_SEGMENTS_FOR_DYNAMIC_LOADING 2 static int nvfw_open(struct inode *inode, struct file *file); static int nvfw_close(struct inode *inode, struct file *file); static long nvfw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); static ssize_t nvfw_write(struct file *, const char __user *, size_t, loff_t *); +static NvError NvRmPrivInitAvp(NvRmDeviceHandle hRm); + static const struct file_operations nvfw_fops = { .owner = THIS_MODULE, @@ -97,18 +115,15 @@ ssize_t nvfw_write(struct file *file, const char __user *buff, size_t count, lof printk(KERN_INFO "%s: entry\n", __func__); error = copy_from_user(filename, buff, count); - if (error) - panic("%s: line=%d\n", __func__, __LINE__); + if (error) panic("%s: line=%d\n", __func__, __LINE__); filename[count] = 0; printk(KERN_INFO "%s: filename=%s\n", __func__, filename); error = NvRmOpen( &hRmDevice, 0 ); - if (error) - panic("%s: line=%d\n", __func__, __LINE__); + if (error) panic("%s: line=%d\n", __func__, __LINE__); error = NvRmLoadLibrary(hRmDevice, filename, NULL, 0, &hRmLibHandle); - if (error) - panic("%s: line=%d\n", __func__, __LINE__); + if (error) panic("%s: line=%d\n", __func__, __LINE__); printk(KERN_INFO "%s: return\n", __func__); return count; @@ -135,31 +150,25 @@ static int nvfw_ioctl_load_library(struct file *filp, void __user *arg) error = copy_from_user(&op, arg, sizeof(op)); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; filename = NvOsAlloc(op.length + 1); error = copy_from_user(filename, op.filename, op.length + 1); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; printk(KERN_INFO "%s: filename=%s\n", __func__, filename); args = NvOsAlloc(op.argssize); error = copy_from_user(args, op.args, op.argssize); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmOpen( &hRmDevice, 0 ); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmLoadLibrary(hRmDevice, filename, args, op.argssize, &hRmLibHandle); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; op.handle = hRmLibHandle; error = copy_to_user(arg, &op, sizeof(op)); -error_exit: NvOsFree(filename); NvOsFree(args); return error; @@ -176,31 +185,25 @@ static int nvfw_ioctl_load_library_ex(struct file *filp, void __user *arg) error = copy_from_user(&op, arg, sizeof(op)); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; filename = NvOsAlloc(op.length + 1); error = copy_from_user(filename, op.filename, op.length + 1); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; printk(KERN_INFO "%s: filename=%s\n", __func__, filename); args = NvOsAlloc(op.argssize); error = copy_from_user(args, op.args, op.argssize); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmOpen( &hRmDevice, 0 ); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmLoadLibraryEx(hRmDevice, filename, args, op.argssize, op.greedy, &hRmLibHandle); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; op.handle = hRmLibHandle; error = copy_to_user(arg, &op, sizeof(op)); -error_exit: NvOsFree(filename); NvOsFree(args); return error; @@ -214,17 +217,13 @@ static int nvfw_ioctl_free_library(struct file *filp, void __user *arg) error = copy_from_user(&op, arg, sizeof(op)); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmOpen( &hRmDevice, 0 ); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmFreeLibrary(op.handle); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; -error_exit: return error; } @@ -237,25 +236,20 @@ static int nvfw_ioctl_get_proc_address(struct file *filp, void __user *arg) error = copy_from_user(&op, arg, sizeof(op)); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; symbolname = NvOsAlloc(op.length + 1); error = copy_from_user(symbolname, op.symbolname, op.length + 1); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; printk(KERN_INFO "%s: symbolname=%s\n", __func__, symbolname); error = NvRmOpen( &hRmDevice, 0 ); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = NvRmGetProcAddress(op.handle, symbolname, &op.address); if (error) panic("%s: line=%d\n", __func__, __LINE__); - if (error) goto error_exit; error = copy_to_user(arg, &op, sizeof(op)); -error_exit: NvOsFree(symbolname); return error; } @@ -285,1355 +279,433 @@ static long nvfw_ioctl(struct file *filp, return err; } -static NvError -PrivateOsFopen(const char *filename, NvU32 flags, PrivateOsFileHandle *file) +static NvError PrivateOsFopen( + const char *filename, + NvU32 flags, + PrivateOsFileHandle *file) { - PrivateOsFileHandle hFile; + PrivateOsFileHandle hFile; - hFile = NvOsAlloc(sizeof(PrivateOsFile)); - if (hFile == NULL) { - return NvError_InsufficientMemory; - } + hFile = NvOsAlloc(sizeof(PrivateOsFile)); + if (hFile == NULL) + return NvError_InsufficientMemory; - NvOsDebugPrintf("%s : file=%s\n", __func__, filename); - NvOsDebugPrintf("%s : calling request_firmware()\n", __func__); - if (request_firmware(&s_FwEntry, filename, nvfw_dev.this_device) != 0) { - printk(KERN_ERR "%s: Cannot read firmware '%s'\n", __func__, filename); - return NvError_FileReadFailed; - } - NvOsDebugPrintf("%s : back from request_firmware()\n", __func__); - hFile->pstart = s_FwEntry->data; - hFile->pread = s_FwEntry->data; - hFile->pend = s_FwEntry->data + s_FwEntry->size; + NvOsDebugPrintf("%s : file=%s\n", __func__, filename); + NvOsDebugPrintf("%s : calling request_firmware()\n", __func__); + if (request_firmware(&s_FwEntry, filename, nvfw_dev.this_device) != 0) + { + pr_err("%s: Cannot read firmware '%s'\n", __func__, filename); + return NvError_FileReadFailed; + } + NvOsDebugPrintf("%s : back from request_firmware()\n", __func__); + hFile->pstart = s_FwEntry->data; + hFile->pread = s_FwEntry->data; + hFile->pend = s_FwEntry->data + s_FwEntry->size; - *file = hFile; + *file = hFile; - return NvError_Success; + return NvError_Success; } -static void -PrivateOsFclose(PrivateOsFileHandle hFile) +static void PrivateOsFclose(PrivateOsFileHandle hFile) { - release_firmware(s_FwEntry); - NV_ASSERT(hFile); - NvOsFree(hFile); + release_firmware(s_FwEntry); + NV_ASSERT(hFile); + NvOsFree(hFile); } -static NvError -PrivateOsFread( - PrivateOsFileHandle hFile, - void *ptr, - size_t size, - size_t *bytes) +NvError NvRmLoadLibrary( + NvRmDeviceHandle hDevice, + const char *pLibName, + void* pArgs, + NvU32 sizeOfArgs, + NvRmLibraryHandle *hLibHandle) { - size_t nBytesRead = size; - NvError err = NvError_Success; + NvError Error = NvSuccess; + NV_ASSERT(sizeOfArgs <= MAX_ARGS_SIZE); - if (hFile->pread >= hFile->pend) { - nBytesRead = 0; - err = NvError_EndOfFile; - goto epilogue; - } + NvOsDebugPrintf("%s : file=%s\n", __func__, pLibName); + Error = NvRmLoadLibraryEx(hDevice, pLibName, pArgs, sizeOfArgs, NV_FALSE, + hLibHandle); + return Error; +} - else if (hFile->pread + size > hFile->pend) { - nBytesRead = hFile->pend - hFile->pread; - NvOsMemcpy(ptr, hFile->pread, nBytesRead); - err = NvError_EndOfFile; - goto epilogue; - } +NvError NvRmLoadLibraryEx( + NvRmDeviceHandle hDevice, + const char *pLibName, + void* pArgs, + NvU32 sizeOfArgs, + NvBool IsApproachGreedy, + NvRmLibraryHandle *hLibHandle) +{ + NvRmLibraryHandle library = NULL; + NvError e = NvSuccess; + PrivateOsFileHandle hFile = NULL; + NvRmMemHandle hMem = NULL; + NvRmHeap loadHeap = NvRmHeap_ExternalCarveOut; + void *loadAddr = NULL; + NvU32 len = 0; + NvU32 physAddr; - else { - NvOsMemcpy(ptr, hFile->pread, nBytesRead); - goto epilogue; - } + NV_ASSERT(sizeOfArgs <= MAX_ARGS_SIZE); -epilogue: - hFile->pread += nBytesRead; - *bytes = nBytesRead; - return err; -} + NvOsDebugPrintf("%s : file=%s\n", __func__, pLibName); -static NvError -PrivateOsFseek(PrivateOsFileHandle file, NvS64 offset, NvOsSeekEnum whence) -{ - NV_ASSERT(whence == NvOsSeek_Set); - file->pread = file->pstart + (NvU32)offset; + NV_CHECK_ERROR_CLEANUP(NvRmPrivInitAvp(hDevice)); - return NvError_Success; -} + e = NvRmPrivRPCConnect(s_RPCHandle); + if (e != NvSuccess) + { + NvOsDebugPrintf("RPCConnect timed out during NvRmLoadLibrary\n"); + goto fail; + } -NvError -NvRmPrivLoadKernelLibrary(NvRmDeviceHandle hDevice, - const char *pLibName, - NvRmLibraryHandle *hLibHandle) -{ - NvError Error = NvSuccess; + library = NvOsAlloc(sizeof(*library)); + if (!library) + { + e = NvError_InsufficientMemory; + goto fail; + } - NvOsDebugPrintf("%s : file=%s\n", __func__, pLibName); - if ((Error = NvRmPrivLoadLibrary(hDevice, pLibName, 0, NV_FALSE, - hLibHandle)) != NvSuccess) - { - return Error; - } - return Error; -} + NV_CHECK_ERROR_CLEANUP(PrivateOsFopen(pLibName, NVOS_OPEN_READ, &hFile)); + len = (NvU32)hFile->pend - (NvU32)hFile->pstart; -NvError -NvRmLoadLibrary(NvRmDeviceHandle hDevice, - const char *pLibName, - void* pArgs, - NvU32 sizeOfArgs, - NvRmLibraryHandle *hLibHandle) -{ - NvError Error = NvSuccess; - NV_ASSERT(sizeOfArgs <= MAX_ARGS_SIZE); + NV_CHECK_ERROR_CLEANUP(NvRmMemHandleCreate(hDevice, &hMem, len)); - NvOsDebugPrintf("%s : file=%s\n", __func__, pLibName); - Error = NvRmLoadLibraryEx(hDevice, pLibName, pArgs, sizeOfArgs, NV_FALSE, - hLibHandle); - return Error; -} + NV_CHECK_ERROR_CLEANUP(NvRmMemAlloc(hMem, &loadHeap, 1, L1_CACHE_BYTES, + NvOsMemAttribute_WriteCombined)); -NvError -NvRmLoadLibraryEx(NvRmDeviceHandle hDevice, - const char *pLibName, - void* pArgs, - NvU32 sizeOfArgs, - NvBool IsApproachGreedy, - NvRmLibraryHandle *hLibHandle) -{ - NvError Error = NvSuccess; - NV_ASSERT(sizeOfArgs <= MAX_ARGS_SIZE); + NV_CHECK_ERROR_CLEANUP(NvRmMemMap(hMem, 0, len, NVOS_MEM_READ_WRITE, &loadAddr)); - NvOsDebugPrintf("%s : file=%s\n", __func__, pLibName); + physAddr = NvRmMemPin(hMem); - /* NvRmPrivInitModuleLoaderRPC(hDevice); */ - if ((Error = NvRmPrivInitAvp(hDevice)) != NvSuccess) - { - return Error; - } + NvOsMemcpy(loadAddr, hFile->pstart, len); - if ((Error = NvRmPrivLoadLibrary(hDevice, pLibName, 0, IsApproachGreedy, - hLibHandle)) != NvSuccess) - { - return Error; - } + NvOsFlushWriteCombineBuffer(); - if ((Error = NvRmPrivRPCConnect(s_RPCHandle)) == NvSuccess) - { - Error = SendMsgAttachModule(hLibHandle, pArgs, sizeOfArgs); - } - else - { - NvOsDebugPrintf("RPCConnect timedout during NvRmLoadLibraryEx\r\n"); - } - if (Error) - { - NvRmPrivFreeLibrary(*hLibHandle); - } - return Error; + NV_CHECK_ERROR_CLEANUP(SendMsgAttachModule(library, pArgs, physAddr, len, + IsApproachGreedy, sizeOfArgs)); + +fail: + if (loadAddr) + { + NvRmMemUnpin(hMem); + NvRmMemUnmap(hMem, loadAddr, len); + } + + NvRmMemHandleFree(hMem); + if (hFile) + PrivateOsFclose(hFile); + + if (e != NvSuccess) + { + NvOsFree(library); + library = NULL; + } + + *hLibHandle = library; + return e; } -NvError -NvRmGetProcAddress(NvRmLibraryHandle Handle, - const char *pSymbol, - void **pSymAddress) +NvError NvRmGetProcAddress( + NvRmLibraryHandle Handle, + const char *pSymbol, + void **pSymAddress) { - NvError Error = NvSuccess; - NV_ASSERT(Handle); - Error = NvRmPrivGetProcAddress(Handle, pSymbol, pSymAddress); - return Error; + NvError Error = NvSuccess; + NV_ASSERT(Handle); + Error = NvRmPrivGetProcAddress(Handle, pSymbol, pSymAddress); + return Error; } NvError NvRmFreeLibrary(NvRmLibraryHandle hLibHandle) { - NvError Error = NvSuccess; - NV_ASSERT(hLibHandle); - if((Error = NvRmPrivRPCConnect(s_RPCHandle)) == NvSuccess) - { - Error = SendMsgDetachModule(hLibHandle); - } - if (Error == NvSuccess) - { - Error = NvRmPrivFreeLibrary(hLibHandle); - } + NvError e = NvSuccess; + NV_ASSERT(hLibHandle); - return Error; -} + e = NvRmPrivRPCConnect(s_RPCHandle); + if (e != NvSuccess) + return e; -NvU32 NvRmModuleGetChipId(NvRmDeviceHandle hDevice) -{ - typedef struct - { - NvU32 Id; - }Capabilities; - - NvError Error = NvSuccess; - NvRmModuleCapability caps[3]; - Capabilities Cap15, Cap20,Cap16,*capabilities; - - // for AP20 - Cap20.Id = 0x20; - caps[0].MajorVersion = 1; - caps[0].MinorVersion = 1; - caps[0].EcoLevel = 0; - caps[0].Capability = (void *)&Cap20; - - //for AP15 A01 - Cap15.Id = 0x15; - caps[1].MajorVersion = 1; - caps[1].MinorVersion = 0; - caps[1].EcoLevel = 0; - caps[1].Capability = (void *)&Cap15; - - //for AP15 A02 - Cap16.Id = 0x15; - caps[2].MajorVersion = 1; - caps[2].MinorVersion = 1; - caps[2].EcoLevel = 0; - caps[2].Capability = (void *)&Cap16; - - Error = NvRmModuleGetCapabilities(hDevice, NvRmModuleID_BseA, caps, 3, (void **)&capabilities); - - return capabilities->Id; + e = SendMsgDetachModule(hLibHandle); + if (e != NvSuccess) + return e; + + NvOsFree(hLibHandle); + return NvSuccess; } //before unloading loading send message to avp with args and entry point via transport static NvError SendMsgDetachModule(NvRmLibraryHandle hLibHandle) { - NvError Error = NvSuccess; - NvU32 RecvMsgSize; - NvRmMessage_DetachModule Msg; - NvRmMessage_DetachModuleResponse MsgR; - void *address = NULL; + NvU32 RecvMsgSize; + NvRmMessage_DetachModule Msg; + NvRmMessage_DetachModuleResponse MsgR; - Msg.msg = NvRmMsg_DetachModule; + Msg.msg = NvRmMsg_DetachModule; - if ((Error = NvRmGetProcAddress(hLibHandle, "main", &address)) != NvSuccess) - { - goto exit_gracefully; - } - Msg.msg = NvRmMsg_DetachModule; - Msg.reason = NvRmModuleLoaderReason_Detach; - Msg.entryAddress = (NvU32)address; - RecvMsgSize = sizeof(NvRmMessage_DetachModuleResponse); - NvRmPrivRPCSendMsgWithResponse(s_RPCHandle, - &MsgR, - RecvMsgSize, - &RecvMsgSize, - &Msg, - sizeof(Msg)); - - Error = MsgR.error; - if (Error) - { - goto exit_gracefully; - } -exit_gracefully: - return Error; + Msg.msg = NvRmMsg_DetachModule; + Msg.reason = NvRmModuleLoaderReason_Detach; + Msg.libraryId = hLibHandle->libraryId; + RecvMsgSize = sizeof(NvRmMessage_DetachModuleResponse); + NvRmPrivRPCSendMsgWithResponse(s_RPCHandle, &MsgR, RecvMsgSize, + &RecvMsgSize, &Msg, sizeof(Msg)); + + return MsgR.error; } //after successful loading send message to avp with args and entry point via transport -static NvError SendMsgAttachModule(NvRmLibraryHandle *hLibHandle, - void* pArgs, - NvU32 sizeOfArgs) +static NvError SendMsgAttachModule( + NvRmLibraryHandle hLibHandle, + void* pArgs, + NvU32 loadAddress, + NvU32 fileSize, + NvBool greedy, + NvU32 sizeOfArgs) { - NvError Error = NvSuccess; - NvU32 RecvMsgSize; - NvRmMessage_AttachModule *MsgPtr=NULL; - NvRmMessage_AttachModuleResponse MsgR; - void *address = NULL; - - MsgPtr = NvOsAlloc(sizeof(*MsgPtr)); - if(MsgPtr==NULL) - { - Error = NvError_InsufficientMemory; - goto exit_gracefully; - } - MsgPtr->msg = NvRmMsg_AttachModule; + NvU32 RecvMsgSize; + NvRmMessage_AttachModule Msg; + NvRmMessage_AttachModuleResponse MsgR; - if(pArgs) - { - NvOsMemcpy(MsgPtr->args, pArgs, sizeOfArgs); - } + NvOsMemset(&Msg, 0, sizeof(Msg)); + Msg.msg = NvRmMsg_AttachModule; - MsgPtr->size = sizeOfArgs; - if ((Error = NvRmGetProcAddress(*hLibHandle, "main", &address)) != NvSuccess) - { - goto exit_gracefully; - } - MsgPtr->entryAddress = (NvU32)address; - MsgPtr->reason = NvRmModuleLoaderReason_Attach; - RecvMsgSize = sizeof(NvRmMessage_AttachModuleResponse); - NvRmPrivRPCSendMsgWithResponse(s_RPCHandle, - &MsgR, - RecvMsgSize, - &RecvMsgSize, - MsgPtr, - sizeof(*MsgPtr)); - - Error = MsgR.error; - if (Error) - { - goto exit_gracefully; - } -exit_gracefully: - NvOsFree(MsgPtr); - return Error; + if(pArgs) + NvOsMemcpy(Msg.args, pArgs, sizeOfArgs); + + Msg.size = sizeOfArgs; + Msg.address = loadAddress; + Msg.filesize = fileSize; + if (greedy) + Msg.reason = NvRmModuleLoaderReason_AttachGreedy; + else + Msg.reason = NvRmModuleLoaderReason_Attach; + + RecvMsgSize = sizeof(NvRmMessage_AttachModuleResponse); + + NvRmPrivRPCSendMsgWithResponse(s_RPCHandle, &MsgR, RecvMsgSize, + &RecvMsgSize, &Msg, sizeof(Msg)); + + hLibHandle->libraryId = MsgR.libraryId; + return MsgR.error; } NvError NvRmPrivInitModuleLoaderRPC(NvRmDeviceHandle hDevice) { - NvError err = NvSuccess; + NvError err = NvSuccess; - // Run only once. - if (s_RPCHandle) return NvError_Success; + if (s_RPCHandle) + return NvError_Success; - NvOsDebugPrintf("%s : NvRmPrivRPCInit(RPC_AVP_PORT)\n", __func__); - err = NvRmPrivRPCInit(hDevice, "RPC_AVP_PORT", &s_RPCHandle); - if (err) panic("%s: NvRmPrivRPCInit FAILED\n", __func__); + NvOsDebugPrintf("%s : NvRmPrivRPCInit(RPC_AVP_PORT)\n", __func__); + err = NvRmPrivRPCInit(hDevice, "RPC_AVP_PORT", &s_RPCHandle); + if (err) panic("%s: NvRmPrivRPCInit FAILED\n", __func__); - return err; + return err; } void NvRmPrivDeInitModuleLoaderRPC() { - NvRmPrivRPCDeInit(s_RPCHandle); + NvRmPrivRPCDeInit(s_RPCHandle); } -SegmentNode* AddToSegmentList(SegmentNode *pList, - NvRmMemHandle pRegion, - Elf32_Phdr Phdr, - NvU32 Idx, - NvU32 PhysAddr, - void* MapAddress) +NvError NvRmPrivGetProcAddress( + NvRmLibraryHandle Handle, + const char *pSymbol, + void **pSymAddress) { - SegmentNode *TempRec = NULL; - SegmentNode *CurrentRec = NULL; - - TempRec = NvOsAlloc(sizeof(SegmentNode)); - if (TempRec != NULL) - { - TempRec->pLoadRegion = pRegion; - TempRec->Index = Idx; - TempRec->VirtualAddr = Phdr.p_vaddr; - TempRec->MemorySize = Phdr.p_memsz; - TempRec->FileOffset = Phdr.p_offset; - TempRec->FileSize = Phdr.p_filesz; - TempRec->LoadAddress = PhysAddr; - TempRec->MapAddr = MapAddress; - TempRec->Next = NULL; - - CurrentRec = pList; - if (CurrentRec == NULL) - { - pList = TempRec; - } - else - { - while (CurrentRec->Next != NULL) - { - CurrentRec = CurrentRec->Next; - } - CurrentRec->Next = TempRec; - } - } - return pList; -} -void RemoveRegion(SegmentNode *pList) -{ - if (pList != NULL) - { - SegmentNode *pCurrentRec; - SegmentNode *pTmpRec; - pCurrentRec = pList; - while (pCurrentRec != NULL) - { - NvRmMemUnpin(pCurrentRec->pLoadRegion); - NvRmMemHandleFree(pCurrentRec->pLoadRegion); - pCurrentRec->pLoadRegion = NULL; - pTmpRec = pCurrentRec; - pCurrentRec = pCurrentRec->Next; - NvOsFree( pTmpRec ); - } - pList = NULL; - } -} + NvRmLibHandle *hHandle = Handle; -void UnMapRegion(SegmentNode *pList) -{ - if (pList != NULL) - { - SegmentNode *pCurrentRec; - pCurrentRec = pList; - while (pCurrentRec != NULL && pCurrentRec->MapAddr ) - { - NvRmMemUnmap(pCurrentRec->pLoadRegion, pCurrentRec->MapAddr, - pCurrentRec->MemorySize); - pCurrentRec = pCurrentRec->Next; - } - } -} + if (hHandle->libraryId == 0) + return NvError_SymbolNotFound; -NvError -ApplyRelocation(SegmentNode *pList, - NvU32 FileOffset, - NvU32 SegmentOffset, - NvRmMemHandle pRegion, - const Elf32_Rel *pRel) -{ - NvError Error = NvSuccess; - NvU8 Type = 0; - NvU32 SymIndex = 0; - Elf32_Word Word = 0; - SegmentNode *pCur; - NvU32 TargetVirtualAddr = 0; - NvU32 LoadAddress = 0; - NV_ASSERT(NULL != pRel); - - NvRmMemRead(pRegion, SegmentOffset,&Word, sizeof(Word)); - NV_DEBUG_PRINTF(("NvRmMemRead: SegmentOffset 0x%04x, word %p\r\n", - SegmentOffset, Word)); - Type = ELF32_R_TYPE(pRel->r_info); - - switch (Type) - { - case R_ARM_NONE: - break; - case R_ARM_CALL: - break; - case R_ARM_RABS32: - SymIndex = ELF32_R_SYM(pRel->r_info); - if (pList != NULL) - { - pCur = pList; - while (pCur != NULL) - { - if (pCur->Index == (SymIndex - 1)) - { - TargetVirtualAddr = pCur->VirtualAddr; - LoadAddress = pCur->LoadAddress; - } - pCur = pCur->Next; - } - if (LoadAddress > TargetVirtualAddr) - { - Word = Word + (LoadAddress - TargetVirtualAddr); - } - else //handle negative displacement - { - Word = Word - (TargetVirtualAddr - LoadAddress); - } - NV_DEBUG_PRINTF(("NvRmMemWrite: SegmentOffset 0x%04x, word %p\r\n", - SegmentOffset, Word)); - NvRmMemWrite(pRegion, SegmentOffset, &Word, sizeof(Word)); - } - break; - default: - Error = NvError_NotSupported; - NV_DEBUG_PRINTF(("This relocation type is not handled = %d\r\n", Type)); - break; - } - return Error; + *pSymAddress = (void *)hHandle->libraryId; + return NvSuccess; } -NvError -GetSpecialSectionName(Elf32_Word SectionType, - Elf32_Word SectionFlags, - const char** SpecialSectionName) +static void NvRmPrivResetAvp(NvRmDeviceHandle hRm, unsigned long reset_va) { - const char *unknownSection = "Unknown\r\n"; - *SpecialSectionName = unknownSection; - /// Mask off the high 16 bits for now - switch (SectionFlags & 0xffff) - { - case SHF_ALLOC|SHF_WRITE: - if (SectionType == SHT_NOBITS) - *SpecialSectionName = ".bss\r\n"; - else if (SectionType == SHT_PROGBITS) - *SpecialSectionName = ".data\r\n"; - else if (SectionType == SHT_FINI_ARRAY) - *SpecialSectionName = ".fini_array\r\n"; - else if (SectionType == SHT_INIT_ARRAY) - *SpecialSectionName = ".init_array\r\n"; - break; - case SHF_ALLOC|SHF_EXECINSTR: - if (SectionType == SHT_PROGBITS) - *SpecialSectionName = ".init or fini \r\n"; + u32 *stub_va = &_tegra_avp_launcher_stub_data[AVP_LAUNCHER_START_VA]; + unsigned long stub_addr = virt_to_phys(_tegra_avp_launcher_stub); + unsigned int tmp; - break; - case SHF_ALLOC: - if (SectionType == SHT_STRTAB) - *SpecialSectionName = ".dynstr\r\n"; - else if (SectionType == SHT_DYNSYM) - *SpecialSectionName = ".dynsym\r\n"; - else if (SectionType == SHT_HASH) - *SpecialSectionName = ".hash\r\n"; - else if (SectionType == SHT_PROGBITS) - *SpecialSectionName = ".rodata\r\n"; - else - *SpecialSectionName = unknownSection; - break; - default: - if (SectionType == SHT_PROGBITS) - *SpecialSectionName = ".comment\r\n"; - else - *SpecialSectionName = unknownSection; - break; - } - return NvSuccess; + *stub_va = reset_va; + __cpuc_flush_dcache_area(stub_va, sizeof(*stub_va)); + outer_clean_range(__pa(stub_va), __pa(stub_va+1)); + + tmp = readl(_TEGRA_AVP_RESET_VECTOR_ADDR); + writel(stub_addr, _TEGRA_AVP_RESET_VECTOR_ADDR); + barrier(); + NvRmModuleReset(hRm, NvRmModuleID_Avp); + writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTRL_HALT_COP); + barrier(); + writel(tmp, _TEGRA_AVP_RESET_VECTOR_ADDR); } -NvError -ParseDynamicSegment(SegmentNode *pList, - const char* pSegmentData, - size_t SegmentSize, - NvU32 DynamicSegmentOffset) +static NvError NvRmPrivInitAvp(NvRmDeviceHandle hRm) { - NvError Error = NvSuccess; - Elf32_Dyn* pDynSeg = NULL; - NvU32 Counter = 0; - NvU32 RelocationTableAddressOffset = 0; - NvU32 RelocationTableSize = 0; - NvU32 RelocationEntrySize = 0; - const Elf32_Rel* RelocationTablePtr = NULL; - NvU32 SymbolTableAddressOffset = 0; - NvU32 SymbolTableEntrySize = 0; - NvU32 SymbolTableSize = 0; - NvU32 SegmentOffset = 0; - NvU32 FileOffset = 0; - SegmentNode *node; -#if NV_ENABLE_DEBUG_PRINTS - // Strings for interpreting ELF header e_type field. - static const char * s_DynSecTypeText[] = - { - "DT_NULL", - "DT_NEEDED", - "DT_PLTRELSZ", - "DT_PLTGOT", - "DT_HASH", -// "DT_STRTAB", - "String Table Address", -// "DT_SYMTAB", - "Symbol Table Address", -// "DT_RELA", - "Relocation Table Address", -// "DT_RELASZ", - "Relocation Table Size", -// "DT_RELAENT", - "Relocation Entry Size", -// "DT_STRSZ", - "String Table Size", -// "DT_SYMENT", - "Symbol Table Entry Size", - "DT_INIT", - "DT_FINI", - "DT_SONAME", - "DT_RPATH", - "DT_SYMBOLIC", -// "DT_REL", - "Relocation Table Address", -// "DT_RELSZ", - "Relocation Table Size", -// "DT_RELENT", - "Relocation Entry Size", - "DT_PLTREL", - "DT_DEBUG", - "DT_TEXTREL", - "DT_JMPREL", - "DT_BIND_NOW", - "DT_INIT_ARRAY", - "DT_FINI_ARRAY", - "DT_INIT_ARRAYSZ", - "DT_FINI_ARRAYSZ", - "DT_RUNPATH", - "DT_FLAGS", - "DT_ENCODING", - "DT_PREINIT_ARRAY", - "DT_PREINIT_ARRAYSZ", - "DT_NUM", - "DT_OS-specific", - "DT_PROC-specific", - "" - }; -#else -#define s_DynSecTypeText ((char**)0) -#endif - - pDynSeg = (Elf32_Dyn*)pSegmentData; - do - { - if (pDynSeg->d_tag < DT_NUM) - { - NV_DEBUG_PRINTF(("Entry %d with Tag %s %d\r\n", - Counter++, s_DynSecTypeText[pDynSeg->d_tag], pDynSeg->d_val)); - } - else - { - NV_DEBUG_PRINTF(("Entry %d Special Compatibility Range %x %d\r\n", - Counter++, pDynSeg->d_tag, pDynSeg->d_val)); - } - if (pDynSeg->d_tag == DT_NULL) - break; - if ((pDynSeg->d_tag == DT_REL) || (pDynSeg->d_tag == DT_RELA)) - RelocationTableAddressOffset = pDynSeg->d_un.d_val; - if ((pDynSeg->d_tag == DT_RELENT) || (pDynSeg->d_tag == DT_RELAENT)) - RelocationEntrySize = pDynSeg->d_un.d_val; - if ((pDynSeg->d_tag == DT_RELSZ) || (pDynSeg->d_tag == DT_RELASZ)) - RelocationTableSize = pDynSeg->d_un.d_val; - if (pDynSeg->d_tag == DT_SYMTAB) - SymbolTableAddressOffset = pDynSeg->d_un.d_val; - if (pDynSeg->d_tag == DT_SYMENT) - SymbolTableEntrySize = pDynSeg->d_un.d_val; - if (pDynSeg->d_tag == DT_ARM_RESERVED1) - SymbolTableSize = pDynSeg->d_un.d_val; - pDynSeg++; - - }while ((Counter*sizeof(Elf32_Dyn)) < SegmentSize); - - if (RelocationTableAddressOffset && RelocationTableSize && RelocationEntrySize) - { - RelocationTablePtr = (const Elf32_Rel*)&pSegmentData[RelocationTableAddressOffset]; - - for (Counter = 0; Counter < (RelocationTableSize/RelocationEntrySize); Counter++) - { - //calculate the actual offset of the reloc entry - NV_DEBUG_PRINTF(("Reloc %d offset is %x RType %d SymIdx %d \r\n", - Counter, RelocationTablePtr->r_offset, - ELF32_R_TYPE(RelocationTablePtr->r_info), - ELF32_R_SYM(RelocationTablePtr->r_info))); - - node = pList; - while (node != NULL) - { - if ( (RelocationTablePtr->r_offset > node->VirtualAddr) && - (RelocationTablePtr->r_offset <= - (node->VirtualAddr + node->MemorySize))) - { - FileOffset = node->FileOffset + - (RelocationTablePtr->r_offset - node->VirtualAddr); - - NV_DEBUG_PRINTF(("File offset to be relocated %d \r\n", FileOffset)); - - SegmentOffset = (RelocationTablePtr->r_offset - node->VirtualAddr); - - NV_DEBUG_PRINTF(("Segment offset to be relocated %d \r\n", SegmentOffset)); - - Error = ApplyRelocation(pList, FileOffset, SegmentOffset, - node->pLoadRegion, RelocationTablePtr); - - } - node = node->Next; - } - RelocationTablePtr++; - } + u32 *stub_phys = &_tegra_avp_launcher_stub_data[AVP_LAUNCHER_MMU_PHYSICAL]; + NvRmHeap heaps[] = { NvRmHeap_External, NvRmHeap_ExternalCarveOut }; + PrivateOsFileHandle kernel; + void *map = NULL; + NvError e; + NvU32 len; + NvU32 phys; - } - if (SymbolTableAddressOffset && SymbolTableSize && SymbolTableEntrySize) - { -#if 0 - const Elf32_Sym* SymbolTablePtr = NULL; - SymbolTablePtr = (const Elf32_Sym*)&pSegmentData[SymbolTableAddressOffset]; - for (Counter = 0; Counter st_name, SymbolTablePtr->st_value, - SymbolTablePtr->st_size, SymbolTablePtr->st_info, - SymbolTablePtr->st_other, SymbolTablePtr->st_shndx); - NV_DEBUG_PRINTF(("Symbol name %x, value %x, size %x, info %x, other %x, shndx %x\r\n", - SymbolTablePtr->st_name, SymbolTablePtr->st_value, - SymbolTablePtr->st_size, SymbolTablePtr->st_info, - SymbolTablePtr->st_other, SymbolTablePtr->st_shndx)); - - SymbolTablePtr++; - } -#endif - } - return Error; -} + if (s_KernelImage) + return NvSuccess; -NvError -LoadLoadableProgramSegment(PrivateOsFileHandle elfSourceHandle, - NvRmDeviceHandle hDevice, - NvRmLibraryHandle hLibHandle, - Elf32_Phdr Phdr, - Elf32_Ehdr Ehdr, - const NvRmHeap * Heaps, - NvU32 NumHeaps, - NvU32 loop, - const char *Filename, - SegmentNode **segmentList) -{ - NvError Error = NvSuccess; - NvRmMemHandle pLoadRegion = NULL; - void* pLoadAddress = NULL; - NvU32 offset = 0; - NvU32 addr; // address of pLoadRegion - size_t bytesRead = 0; - - Error = NvRmMemHandleCreate(hDevice, - &pLoadRegion, - Phdr.p_memsz); - - if (Error != NvSuccess) - goto CleanUpExit; - - Error = NvRmMemAlloc(pLoadRegion, - Heaps, - NumHeaps, - NV_MAX(16, Phdr.p_align), - NvOsMemAttribute_Uncached); - - if (Error != NvSuccess) - { - NV_DEBUG_PRINTF(("Memory Allocation %d Failed\r\n",Error)); - NvRmMemHandleFree(pLoadRegion); - pLoadRegion = NULL; - goto CleanUpExit; - } - addr = NvRmMemPin(pLoadRegion); + NV_CHECK_ERROR_CLEANUP(NvRmMemHandleCreate(hRm, &s_KernelImage, SZ_1M)); + NV_CHECK_ERROR_CLEANUP(NvRmMemAlloc(s_KernelImage, heaps, + NV_ARRAY_SIZE(heaps), SZ_1M, + NvOsMemAttribute_WriteCombined)); + NV_CHECK_ERROR_CLEANUP(NvRmMemMap(s_KernelImage, 0, SZ_1M, + NVOS_MEM_READ_WRITE, &map)); + + phys = NvRmMemPin(s_KernelImage); - Error = NvRmMemMap(pLoadRegion, 0, Phdr.p_memsz, - NVOS_MEM_READ_WRITE, &pLoadAddress); - if (Error != NvSuccess) - { - pLoadAddress = NULL; - } + NV_CHECK_ERROR_CLEANUP(PrivateOsFopen("nvrm_avp.bin", + NVOS_OPEN_READ, &kernel)); - // This will initialize ZI to zero - if( pLoadAddress ) - { - NvOsMemset(pLoadAddress, 0, Phdr.p_memsz); - } - else - { - NvU8 *tmp = NvOsAlloc( Phdr.p_memsz ); - if( !tmp ) - { - goto CleanUpExit; - } - NvOsMemset( tmp, 0, Phdr.p_memsz ); - NvRmMemWrite( pLoadRegion, 0, tmp, Phdr.p_memsz ); - NvOsFree( tmp ); - } + NvOsMemset(map, 0, SZ_1M); + len = (NvU32)kernel->pend - (NvU32)kernel->pstart; + NvOsMemcpy(map, kernel->pstart, len); - if(Phdr.p_filesz) - { - if( pLoadAddress ) - { - if ((Error = PrivateOsFread(elfSourceHandle, pLoadAddress, - Phdr.p_filesz, &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - } - else - { - NvU8 *tmp = NvOsAlloc( Phdr.p_filesz ); - if( !tmp ) - { - goto CleanUpExit; - } - - Error = PrivateOsFread( elfSourceHandle, tmp, Phdr.p_filesz, - &bytesRead ); - if( Error != NvSuccess ) - { - NvOsFree( tmp ); - goto CleanUpExit; - } - - NvRmMemWrite( pLoadRegion, 0, tmp, Phdr.p_filesz ); - - NvOsFree( tmp ); - } - } - if ((Ehdr.e_entry >= Phdr.p_vaddr) - && (Ehdr.e_entry < (Phdr.p_vaddr + Phdr.p_memsz))) - { - // Odd address indicates entry point is Thumb code. - // The address needs to be masked with LSB before being invoked. - if (addr > Phdr.p_vaddr) - { - offset = (addr - Phdr.p_vaddr) | ADD_MASK; - hLibHandle->EntryAddress = (void*)(Ehdr.e_entry + offset); - } - else - { - offset = ((Phdr.p_vaddr - addr) | (ADD_MASK)) & (SUB_MASK); - hLibHandle->EntryAddress = (void*)(Ehdr.e_entry - offset); - } - NV_DEBUG_PRINTF(("Load Address for %s segment %d:%x\r\n", - Filename, loop, addr)); - NvOsDebugPrintf("Load Address for %s segment %d:%x\r\n", - Filename, loop, addr); - } + PrivateOsFclose(kernel); - *segmentList = AddToSegmentList((*segmentList), pLoadRegion, Phdr, loop, - addr, pLoadAddress); - -CleanUpExit: - if (Error != NvSuccess) - { - if(pLoadRegion != NULL) - { - if( pLoadAddress ) - { - NvRmMemUnmap(pLoadRegion, pLoadAddress, Phdr.p_memsz); - } - - NvRmMemUnpin(pLoadRegion); - NvRmMemHandleFree(pLoadRegion); - } - } - return Error; -} + *stub_phys = phys; + __cpuc_flush_dcache_area(stub_phys, sizeof(*stub_phys)); + outer_clean_range(__pa(stub_phys), __pa(stub_phys+1)); -NvError -NvRmPrivLoadLibrary(NvRmDeviceHandle hDevice, - const char *Filename, - NvU32 Address, - NvBool IsApproachGreedy, - NvRmLibraryHandle *hLibHandle) -{ - NvError Error = NvSuccess; - PrivateOsFileHandle elfSourceHandle = 0; - size_t bytesRead = 0; - Elf32_Ehdr elf; - Elf32_Phdr progHeader; - NvU32 loop = 0; - char *dynamicSegementBuffer = NULL; - int dynamicSegmentOffset = 0; - int lastFileOffset = 0; - SegmentNode *segmentList = NULL; - NvRmHeap HeapProperty[2]; - NvU32 HeapSize = 0; - - NV_ASSERT(NULL != Filename); - *hLibHandle = NULL; - - NvOsDebugPrintf("%s : file=%s\n", __func__, Filename); - if ((Error = PrivateOsFopen(Filename, NVOS_OPEN_READ, - &elfSourceHandle)) != NvSuccess) - { - NV_DEBUG_PRINTF(("Elf source file Not found Error = %d\r\n", Error)); - NvOsDebugPrintf("Failed to load library %s, NvError=%d." - " Make sure it is present on the device\r\n", Filename, Error); - return Error; - } - if ((Error = PrivateOsFread(elfSourceHandle, &elf, - sizeof(elf), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read size mismatch %d\r\n", bytesRead)); - goto CleanUpExit; - } - // Parse the elf headers and display information - parseElfHeader(&elf); - /// Parse the Program Segment Headers and display information - if ((Error = parseProgramSegmentHeaders(elfSourceHandle, elf.e_phoff, elf.e_phnum)) != NvSuccess) - { - NV_DEBUG_PRINTF(("parseProgramSegmentHeaders failed %d\r\n", Error)); - goto CleanUpExit; - } - /// Parse the section Headers and display information - if ((Error = parseSectionHeaders(elfSourceHandle, &elf)) != NvSuccess) - { - NV_DEBUG_PRINTF(("parseSectionHeaders failed %d\r\n", Error)); - goto CleanUpExit; - } - // allocate memory for handle.... - *hLibHandle = NvOsAlloc(sizeof(NvRmLibHandle)); - if (!*hLibHandle) - { - Error = NvError_InsufficientMemory; - goto CleanUpExit; - } + NvRmPrivResetAvp(hRm, 0x00100000ul); - if (elf.e_phnum && elf.e_phnum < MIN_SEGMENTS_FOR_DYNAMIC_LOADING) - { - if ((Error = loadSegmentsInFixedMemory(elfSourceHandle, - &elf, 0, &(*hLibHandle)->pLibBaseAddress)) != NvSuccess) - { - NV_DEBUG_PRINTF(("LoadSegmentsInFixedMemory Failed %d\r\n", Error)); - goto CleanUpExit; - } - (*hLibHandle)->EntryAddress = (*hLibHandle)->pLibBaseAddress; - return Error; - } - else if (elf.e_phnum) - { - if ((Error = PrivateOsFseek(elfSourceHandle, - elf.e_phoff, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - lastFileOffset = elf.e_phoff; - // load the IRAM mandatory and DRAM mandatory sections first... - for (loop = 0; loop < elf.e_phnum; loop++) - { - if ((Error = PrivateOsFread(elfSourceHandle, &progHeader, - sizeof(Elf32_Phdr), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - lastFileOffset += bytesRead; - if (progHeader.p_type == PT_LOAD) - { - NV_DEBUG_PRINTF(("Found load segment %d\r\n",loop)); - if ((Error = PrivateOsFseek(elfSourceHandle, - progHeader.p_offset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - if (progHeader.p_vaddr >= DRAM_MAND_ADDRESS && progHeader.p_vaddr < IRAM_PREF_EXT_ADDRESS) - { - - - if (progHeader.p_vaddr >= DRAM_MAND_ADDRESS && progHeader.p_vaddr < IRAM_MAND_ADDRESS) - { - HeapProperty[0] = NvRmHeap_ExternalCarveOut; - } - else if (progHeader.p_vaddr >= IRAM_MAND_ADDRESS) - { - HeapProperty[0] = NvRmHeap_IRam; - } - Error = LoadLoadableProgramSegment(elfSourceHandle, hDevice, (*hLibHandle), - progHeader, elf, HeapProperty, 1, loop, - Filename, &segmentList); - if (Error != NvSuccess) - { - NV_DEBUG_PRINTF(("Unable to load segment %d \r\n", loop)); - goto CleanUpExit; - } - } - if ((Error = PrivateOsFseek(elfSourceHandle, - lastFileOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - } - } - - // now load the preferred and dynamic sections - if ((Error = PrivateOsFseek(elfSourceHandle, - elf.e_phoff, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - lastFileOffset = elf.e_phoff; - for (loop = 0; loop < elf.e_phnum; loop++) - { - if ((Error = PrivateOsFread(elfSourceHandle, &progHeader, - sizeof(Elf32_Phdr), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - lastFileOffset += bytesRead; - if (progHeader.p_type == PT_LOAD) - { - NV_DEBUG_PRINTF(("Found load segment %d\r\n",loop)); - if ((Error = PrivateOsFseek(elfSourceHandle, - progHeader.p_offset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - if (progHeader.p_vaddr < DRAM_MAND_ADDRESS) - { - if (IsApproachGreedy == NV_FALSE) - { - HeapSize = 1; - //conservative allocation - IRAM_PREF sections in DRAM. - HeapProperty[0] = NvRmHeap_ExternalCarveOut; - } - else - { - // greedy allocation - IRAM_PREF sections in IRAM, otherwise fallback to DRAM - HeapSize = 2; - HeapProperty[0] = NvRmHeap_IRam; - HeapProperty[1] = NvRmHeap_ExternalCarveOut; - } - Error = LoadLoadableProgramSegment(elfSourceHandle, hDevice, - (*hLibHandle), progHeader, elf, - HeapProperty, HeapSize, loop, - Filename, &segmentList); - if (Error != NvSuccess) - { - NV_DEBUG_PRINTF(("Unable to load segment %d \r\n", loop)); - goto CleanUpExit; - } - } - else if (progHeader.p_vaddr >= IRAM_PREF_EXT_ADDRESS) - { - NvU32 Chipid = NvRmModuleGetChipId(hDevice); - if(Chipid == 0x15 || Chipid == 0x16) - { - HeapSize = 1; - //conservative allocation - IRAM_PREF_EXT sections in DRAM for AP15. - HeapProperty[0] = NvRmHeap_ExternalCarveOut; - } - else if(Chipid >= 0x20) - { - if (IsApproachGreedy == NV_FALSE) - { - HeapSize = 1; - //conservative allocation - IRAM_PREF sections in DRAM. - HeapProperty[0] = NvRmHeap_ExternalCarveOut; - } - else - { - // greedy allocation - IRAM_PREF sections in IRAM, otherwise fallback to DRAM - HeapSize = 2; - HeapProperty[0] = NvRmHeap_IRam; - HeapProperty[1] = NvRmHeap_ExternalCarveOut; - } - } - Error = LoadLoadableProgramSegment(elfSourceHandle, hDevice, - (*hLibHandle), progHeader, elf, - HeapProperty, HeapSize, loop, - Filename, &segmentList); - if (Error != NvSuccess) - { - NV_DEBUG_PRINTF(("Unable to load segment %d \r\n", loop)); - goto CleanUpExit; - } - } - if ((Error = PrivateOsFseek(elfSourceHandle, - lastFileOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - } - if (progHeader.p_type != PT_DYNAMIC) - continue; - dynamicSegmentOffset = progHeader.p_offset; - if ((Error = PrivateOsFseek(elfSourceHandle, - dynamicSegmentOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - dynamicSegementBuffer = NvOsAlloc(progHeader.p_filesz); - if (dynamicSegementBuffer == NULL) - { - NV_DEBUG_PRINTF(("Memory Allocation %d Failed\r\n", progHeader.p_filesz)); - goto CleanUpExit; - } - if ((Error = PrivateOsFread(elfSourceHandle, dynamicSegementBuffer, - progHeader.p_filesz, &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - if ((Error = ParseDynamicSegment( - segmentList, - dynamicSegementBuffer, - progHeader.p_filesz, - dynamicSegmentOffset)) != NvSuccess) - { - NV_DEBUG_PRINTF(("Parsing and relocation of segment failed \r\n")); - goto CleanUpExit; - } - (*hLibHandle)->pList = segmentList; - if ((Error = PrivateOsFseek(elfSourceHandle, - lastFileOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit; - } - } - } + NV_CHECK_ERROR_CLEANUP(NvRmPrivInitService(hRm)); + e = NvRmPrivInitModuleLoaderRPC(hRm); + if (e != NvSuccess) + { + NvRmPrivServiceDeInit(); + goto fail; + } -CleanUpExit: - { - if (Error == NvSuccess) - { - UnMapRegion(segmentList); - NvOsFree(dynamicSegementBuffer); - PrivateOsFclose(elfSourceHandle); - } - else - { - RemoveRegion(segmentList); - NvOsFree(dynamicSegementBuffer); - PrivateOsFclose(elfSourceHandle); - NvOsFree(*hLibHandle); - } - } - return Error; -} + NvRmMemUnmap(s_KernelImage, map, SZ_1M); -NvError NvRmPrivFreeLibrary(NvRmLibHandle *hLibHandle) -{ - NvError Error = NvSuccess; - RemoveRegion(hLibHandle->pList); - NvOsFree(hLibHandle); - return Error; -} + return NvSuccess; -void parseElfHeader(Elf32_Ehdr *elf) -{ - if (elf->e_ident[0] == ELF_MAG0) - { - NV_DEBUG_PRINTF(("File is elf Object File with Identification %c%c%c\r\n", - elf->e_ident[1], elf->e_ident[2], elf->e_ident[3])); - NV_DEBUG_PRINTF(("Type of ELF is %x\r\n", elf->e_type)); - //An object file conforming to this specification must have - //the value EM_ARM (40, 0x28). - NV_DEBUG_PRINTF(("Machine type of the file is %x\r\n", elf->e_machine)); - //Address of entry point for this file. bit 1:0 - //indicates if entry point is ARM or thum mode - NV_DEBUG_PRINTF(("Entry point for this axf is %x\r\n", elf->e_entry)); - NV_DEBUG_PRINTF(("Version of the ELF is %d\r\n", elf->e_version)); - NV_DEBUG_PRINTF(("Program Table Header Offset %d\r\n", elf->e_phoff)); - NV_DEBUG_PRINTF(("Section Table Header Offset %d\r\n", elf->e_shoff)); - NV_DEBUG_PRINTF(("Elf Header size %d\r\n", elf->e_ehsize)); - NV_DEBUG_PRINTF(("Section Header's Size %d\r\n", elf->e_shentsize)); - NV_DEBUG_PRINTF(("Number of Section Headers %d\r\n", elf->e_shnum)); - NV_DEBUG_PRINTF(("String Table Section Header Index %d\r\n", elf->e_shstrndx)); - NV_DEBUG_PRINTF(("\r\n")); - } +fail: + writel(2 << 29, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTRL_HALT_COP); + if (map) + { + NvRmMemUnpin(s_KernelImage); + NvRmMemUnmap(s_KernelImage, map, SZ_1M); + } + NvRmMemHandleFree(s_KernelImage); + s_KernelImage = NULL; + return e; } -NvError parseProgramSegmentHeaders(PrivateOsFileHandle elfSourceHandle, - NvU32 segmentHeaderOffset, - NvU32 segmentCount) -{ - Elf32_Phdr progHeader; - size_t bytesRead = 0; - NvU32 loop = 0; - NvError Error = NvSuccess; - if (segmentCount) - { - NV_DEBUG_PRINTF(("Program Headers Found %d\r\n", segmentCount)); - if ((Error = PrivateOsFseek(elfSourceHandle, - segmentHeaderOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", Error)); - return Error; - } - - for (loop = 0; loop < segmentCount; loop++) - { - if ((Error = PrivateOsFread(elfSourceHandle, &progHeader, - sizeof(progHeader), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - return Error; - } - - NV_DEBUG_PRINTF(("Program %d Header type %d\r\n", - loop, progHeader.p_type)); - NV_DEBUG_PRINTF(("Program %d Header offset %d\r\n", - loop, progHeader.p_offset)); - NV_DEBUG_PRINTF(("Program %d Header Virtual Address %x\r\n", - loop, progHeader.p_vaddr)); - NV_DEBUG_PRINTF(("Program %d Header Physical Address %x\r\n", - loop, progHeader.p_paddr)); - NV_DEBUG_PRINTF(("Program %d Header Filesize %d\r\n", - loop, progHeader.p_filesz)); - NV_DEBUG_PRINTF(("Program %d Header Memory Size %d\r\n", - loop, progHeader.p_memsz)); - NV_DEBUG_PRINTF(("Program %d Header Flags %x\r\n", - loop, progHeader.p_flags)); - NV_DEBUG_PRINTF(("Program %d Header alignment %d\r\n", - loop, progHeader.p_align)); - NV_DEBUG_PRINTF(("\r\n")); - } - } - return NvSuccess; -} +static void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE); +static void __iomem *iram_backup; +static dma_addr_t iram_backup_addr; +static u32 iram_size = TEGRA_IRAM_SIZE; +static u32 iram_backup_size = TEGRA_IRAM_SIZE + 4; +static u32 avp_resume_addr; -NvError -parseSectionHeaders(PrivateOsFileHandle elfSourceHandle, Elf32_Ehdr *elf) +static NvError NvRmPrivSuspendAvp(NvRmRPCHandle hRPCHandle) { - NvError Error = NvSuccess; - NvU32 stringTableOffset = 0; - Elf32_Shdr sectionHeader; - size_t bytesRead = 0; - NvU32 loop = 0; - char* stringTable = NULL; - const char *specialNamePtr = NULL; - - // Try to get to the string table so that we can get section names - stringTableOffset = elf->e_shoff + (elf->e_shentsize * elf->e_shstrndx); - - NV_DEBUG_PRINTF(("String Table File Offset is %d\r\n", stringTableOffset)); - - if ((Error = PrivateOsFseek(elfSourceHandle, - stringTableOffset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - return Error; - } - if ((Error = PrivateOsFread(elfSourceHandle, §ionHeader, - sizeof(sectionHeader), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - return Error; - } - if (sectionHeader.sh_type == SHT_STRTAB) - { - NV_DEBUG_PRINTF(("Found Section is string Table\r\n")); - if (sectionHeader.sh_size) - { - stringTable = NvOsAlloc(sectionHeader.sh_size); - if (stringTable == NULL) - { - NV_DEBUG_PRINTF(("String table mem allocation failed for %d\r\n", - sectionHeader.sh_size)); - return NvError_InsufficientMemory; - } - if ((Error = PrivateOsFseek(elfSourceHandle, - sectionHeader.sh_offset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit_parseSectionHeaders; - } - if ((Error = PrivateOsFread(elfSourceHandle, stringTable, - sectionHeader.sh_size, &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit_parseSectionHeaders; - } - } - } - if ((Error = PrivateOsFseek(elfSourceHandle, - elf->e_shoff, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Seek failed %d\r\n", bytesRead)); - goto CleanUpExit_parseSectionHeaders; - } - for (loop = 0; loop < elf->e_shnum; loop++) - { - if ((Error = PrivateOsFread(elfSourceHandle, §ionHeader, - sizeof(sectionHeader), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("File Read failed %d\r\n", bytesRead)); - goto CleanUpExit_parseSectionHeaders; - } - - NV_DEBUG_PRINTF(("Section %d is named %s\r\n", - loop, &stringTable[sectionHeader.sh_name])); - NV_DEBUG_PRINTF(("Section %d Type %d\r\n", - loop, sectionHeader.sh_type)); - NV_DEBUG_PRINTF(("Section %d Flags %x\r\n", - loop, sectionHeader.sh_flags)); - - GetSpecialSectionName(sectionHeader.sh_type, - sectionHeader.sh_flags, &specialNamePtr); - - NV_DEBUG_PRINTF(("Section %d Special Name is %s", - loop, specialNamePtr)); - NV_DEBUG_PRINTF(("Section %d Address %x\r\n", - loop, sectionHeader.sh_addr)); - NV_DEBUG_PRINTF(("Section %d File Offset %d\r\n", - loop, sectionHeader.sh_offset)); - NV_DEBUG_PRINTF(("Section %d Size %d \r\n", - loop, sectionHeader.sh_size)); - NV_DEBUG_PRINTF(("Section %d Link %d \r\n", - loop, sectionHeader.sh_link)); - NV_DEBUG_PRINTF(("Section %d Info %d\r\n", - loop, sectionHeader.sh_info)); - NV_DEBUG_PRINTF(("Section %d alignment %d\r\n", - loop, sectionHeader.sh_addralign)); - NV_DEBUG_PRINTF(("Section %d Fixed Entry Size %d\r\n", - loop, sectionHeader.sh_entsize)); - NV_DEBUG_PRINTF(("\r\n")); + NvError err = NvSuccess; + NvRmMessage_InitiateLP0 lp0_msg; + void *avp_suspend_done = iram_backup + iram_size; + unsigned long timeout; - } -CleanUpExit_parseSectionHeaders: - if (stringTable) - NvOsFree(stringTable); - return Error; -} + pr_info("%s()+\n", __func__); + if (!s_KernelImage) + goto done; + else if (!iram_backup_addr) { + /* XXX: should we return error? */ + pr_warning("%s: iram backup ram missing, not suspending avp\n", + __func__); + goto done; + } -NvError -loadSegmentsInFixedMemory(PrivateOsFileHandle elfSourceHandle, - Elf32_Ehdr *elf, NvU32 segmentIndex, void **loadaddress) -{ - NvError Error = NvSuccess; - size_t bytesRead = 0; - Elf32_Phdr progHeader; - - if ((Error = PrivateOsFseek(elfSourceHandle, - elf->e_phoff + (segmentIndex * sizeof(progHeader)), NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("loadSegmentsInFixedMemory File Seek failed %d\r\n", bytesRead)); - return Error; - } + NV_ASSERT(hRPCHandle->svcTransportHandle != NULL); - if ((Error = PrivateOsFread(elfSourceHandle, &progHeader, - sizeof(Elf32_Phdr), &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF((" loadSegmentsInFixedMemory File Read failed %d\r\n", bytesRead)); - return Error; - } - NV_ASSERT(progHeader.p_type == PT_LOAD); - if ((Error = PrivateOsFseek(elfSourceHandle, - progHeader.p_offset, NvOsSeek_Set)) != NvSuccess) - { - NV_DEBUG_PRINTF(("loadSegmentsInFixedMemory File Seek failed %d\r\n", Error)); - return Error; - } + lp0_msg.msg = NvRmMsg_InitiateLP0; + lp0_msg.sourceAddr = (u32)TEGRA_IRAM_BASE; + lp0_msg.bufferAddr = (u32)iram_backup_addr; + lp0_msg.bufferSize = (u32)iram_size; - /* if((Error = NvRmPhysicalMemMap(progHeader.p_vaddr, */ - /* progHeader.p_memsz, NVOS_MEM_READ_WRITE, */ - /* NvOsMemAttribute_Uncached, loadaddress)) != NvSuccess) */ - /* { */ - /* NV_DEBUG_PRINTF(("loadSegmentsInFixedMemory Failed trying to Mem Map %x\r\n", progHeader.p_vaddr)); */ - /* return Error; */ - /* } */ - // This will initialize ZI to zero - *loadaddress = ioremap_nocache(progHeader.p_vaddr, progHeader.p_memsz); - - NvOsMemset(*loadaddress, 0, progHeader.p_memsz); - if ((Error = PrivateOsFread(elfSourceHandle, *loadaddress, - progHeader.p_filesz, &bytesRead)) != NvSuccess) - { - NV_DEBUG_PRINTF(("loadSegmentsInFixedMemory File Read failed %d\r\n", bytesRead)); - return Error; - } - // Load address need to be reset to the physical address as this is passed to the AVP as the entry point. - *loadaddress = (void *)progHeader.p_vaddr; + writel(0, avp_suspend_done); + + NvOsMutexLock(hRPCHandle->RecvLock); + err = NvRmTransportSendMsg(hRPCHandle->svcTransportHandle, &lp0_msg, + sizeof(lp0_msg), 1000); + NvOsMutexUnlock(hRPCHandle->RecvLock); + + if (err != NvSuccess) { + pr_err("%s: cannot send AVP LP0 message\n", __func__); + goto done; + } + + timeout = jiffies + msecs_to_jiffies(1000); + while (!readl(avp_suspend_done) && time_before(jiffies, timeout)) { + udelay(10); + cpu_relax(); + } + + if (!readl(avp_suspend_done)) { + pr_err("%s: AVP failed to suspend\n", __func__); + err = NvError_Timeout; + goto done; + } - return Error; + avp_resume_addr = readl(iram_base); + if (!avp_resume_addr) { + pr_err("%s: AVP failed to set it's resume address\n", __func__); + err = NvError_InvalidState; + goto done; + } + + pr_info("avp_suspend: resume_addr=%x\n", avp_resume_addr); + avp_resume_addr &= 0xFFFFFFFE; + + pr_info("%s()-\n", __func__); + +done: + return err; } -NvError NvRmPrivGetProcAddress(NvRmLibraryHandle Handle, - const char *pSymbol, - void **pSymAddress) +static NvError NvRmPrivResumeAvp(NvRmRPCHandle hRPCHandle) { - NvError Error = NvSuccess; - // In phase 1, this API will just return the load address as entry address - NvRmLibHandle *hHandle = Handle; - - //NOTE: The EntryAddress is pointing to a THUMB function - //(LSB is set). The Entry Function must be in THUMB mode. - if (hHandle->EntryAddress != NULL) - { - *pSymAddress = hHandle->EntryAddress; - } - else - { - Error = NvError_SymbolNotFound; - } - return Error; + NvError ret = NvSuccess; + + pr_info("%s()+\n", __func__); + if (!s_KernelImage || !avp_resume_addr) + goto done; + + NvRmPrivResetAvp(hRPCHandle->hRmDevice, avp_resume_addr); + avp_resume_addr = 0; + + pr_info("%s()-\n", __func__); + +done: + return ret; } -NvError NvRmPrivSuspendAvp(NvRmRPCHandle hRPCHandle); -NvError NvRmPrivResumeAvp(NvRmRPCHandle hRPCHandle); +int __init _avp_suspend_resume_init(void) +{ + /* allocate an iram sized chunk of ram to give to the AVP */ + iram_backup = dma_alloc_coherent(NULL, iram_backup_size, + &iram_backup_addr, GFP_KERNEL); + if (!iram_backup) + { + pr_err("%s: Unable to allocate iram backup mem\n", __func__); + return -ENOMEM; + } + + return 0; +} static int avp_suspend(struct platform_device *pdev, pm_message_t state) { @@ -1668,34 +740,35 @@ int __init _avp_suspend_resume_init(void); static int __init nvfw_init(void) { - int ret = 0; - struct platform_device *pdev; - - NvOsDebugPrintf("%s: called\n", __func__); - ret = misc_register(&nvfw_dev); - if (ret) panic("%s: misc_register FAILED\n", __func__); - - ret = _avp_suspend_resume_init(); - if (ret) - goto err; - pdev = platform_create_bundle(&avp_nvfw_driver, NULL, NULL, 0, NULL, 0); - if (!pdev) { - pr_err("%s: Can't reg platform driver\n", __func__); - ret = -EINVAL; - goto err; - } + int ret = 0; + struct platform_device *pdev; - pr_info("avp driver initialized\n"); + NvOsDebugPrintf("%s: called\n", __func__); + ret = misc_register(&nvfw_dev); + s_KernelImage = NULL; + if (ret) panic("%s: misc_register FAILED\n", __func__); - return 0; + ret = _avp_suspend_resume_init(); + if (ret) + goto err; + pdev = platform_create_bundle(&avp_nvfw_driver, NULL, NULL, 0, NULL, 0); + if (!pdev) { + pr_err("%s: Can't reg platform driver\n", __func__); + ret = -EINVAL; + goto err; + } + + pr_info("avp driver initialized\n"); + + return 0; err: - return ret; + return ret; } static void __exit nvfw_deinit(void) { - misc_deregister(&nvfw_dev); + misc_deregister(&nvfw_dev); } module_init(nvfw_init); diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader_private.h b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader_private.h index becb53c978f3..5f607b07e3ac 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader_private.h +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader_private.h @@ -93,9 +93,7 @@ struct SegmentRec /// ModuleLoader handle structure typedef struct NvRmLibraryRec { - void* pLibBaseAddress; - void* EntryAddress; - SegmentNode *pList; + NvU32 libraryId; } NvRmLibHandle; NvError @@ -148,7 +146,6 @@ NvRmPrivGetProcAddress(NvRmLibraryHandle Handle, NvError NvRmPrivFreeLibrary(NvRmLibHandle *hLibHandle); NvError NvRmPrivInitModuleLoaderRPC(NvRmDeviceHandle hDevice); -NvError NvRmPrivInitAvp(NvRmDeviceHandle hDevice); /// Unmap memory segments void UnMapRegion(SegmentNode *pList);