515.43.04

This commit is contained in:
Andy Ritger
2022-05-09 13:18:59 -07:00
commit 1739a20efc
2519 changed files with 1060036 additions and 0 deletions

View File

@@ -0,0 +1,187 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2017-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef NVRM
# include <nvport/nvport.h>
# define memcpy(d, s, l) portMemCopy(d, l, s, l)
# define strcmp(str1, str2) portStringCompare(str1, str2, 0x1000)
#else // NVRM
# include <memory.h>
# include <stdio.h>
# include <string.h>
#endif // NVRM
#include "elf.h"
#include "nvtypes.h"
/**
*
* @brief Find the start and end of the ELF section in memory
* from the section name.
*
* @param[in] elf
* @param[in] sectionName
* The section to find such as .text or .data
* @param[out] start, end
* The start and end of the section in the loaded ELF file
* e.g validPtr >= start && validPtr < end
* @param[out] va_baase
* The virtual address this section is loaded at
*/
NvBool
libosElfFindSectionByName(elf64_header *elf, const char *targetName, NvU8 **start, NvU8 **end, NvU64 *va_base)
{
elf64_shdr *shdr = (elf64_shdr *)(((char *)elf) + elf->shoff);
const char *string_base = ((char *)elf) + shdr[elf->shstrndx].offset;
NvU32 i;
for (i = 0; i < elf->shnum; i++, shdr++)
{
const char *name = string_base + shdr->name;
if (strcmp(name, targetName) == 0)
{
*start = (NvU8 *)elf + shdr->offset;
*end = (NvU8 *)elf + shdr->offset + shdr->size;
*va_base = shdr->addr;
return NV_TRUE;
}
}
return NV_FALSE;
}
/**
*
* @brief Find the start and end of the ELF section in memory
* from the section name.
*
* @param[in] elf
* @param[in] sectionName
* The section to find such as .text or .data
* @param[out] start, end
* The start and end of the section in the loaded ELF file
* e.g validPtr >= start && validPtr < end
* @param[out] va_base
* The virtual address this section is loaded at
*/
NvBool
libosElfFindSectionByAddress(elf64_header *elf, NvU64 address, NvU8 **start, NvU8 **end, NvU64 *va_base)
{
elf64_shdr *shdr = (elf64_shdr *)(((char *)elf) + elf->shoff);
NvU32 i;
for (i = 0; i < elf->shnum; i++, shdr++)
{
if (address >= shdr->addr && address < (shdr->addr + shdr->size))
{
*start = (NvU8 *)elf + shdr->offset;
*end = (NvU8 *)elf + shdr->offset + shdr->size;
*va_base = shdr->addr;
return NV_TRUE;
}
}
return NV_FALSE;
}
/**
*
* @brief Reads an arbitrary sized block of memory by loaded VA through
* the ELF. This can be used to read data from the perspective
* of a processor who has loaded the ELF.
*
* @param[in] elf
* @param[in] address
* The absolute virtual address to read
* @param[out] size
* The number of bytes that must be valid.
* @returns
* The pointer to the data in question, or NULL if the operation failed)
*/
void *libosElfReadVirtual(elf64_header *elf, NvU64 address, NvU64 size)
{
NvU8 *start, *end;
NvU64 va_base;
NvU64 section_offset;
NvU64 section_offset_tail;
// @todo This really should be using the PHDR as theoretically section headers
// might be stripped
if (!libosElfFindSectionByAddress(elf, address, &start, &end, &va_base))
return 0;
section_offset = address - va_base;
// Compute section offset (overflow check)
section_offset_tail = section_offset + size;
if (section_offset_tail < section_offset)
return 0;
// Bounds check the tail
if (section_offset_tail > (NvLength)(end - start))
return 0;
return (address - va_base) + start;
}
/**
*
* @brief Reads an arbitrary length string by loaded VA through
* the ELF. This can be used to read data from the perspective
* of a processor who has loaded the ELF.
*
* @param[in] elf
* @param[in] address
* The absolute virtual address to read
* @returns
* The pointer to the data in question, or NULL if the operation failed)
* Ensures that all bytes of the string lie within the ELF same section.
*/
const char *libosElfReadStringVirtual(elf64_header *elf, NvU64 address)
{
NvU8 *start, *end;
NvU64 base;
NvU8 *region;
NvU8 *i;
// @todo This really should be using the PHDR as theoretically section headers
// might be stripped
if (!libosElfFindSectionByAddress(elf, address, &start, &end, &base))
return 0;
region = (address - base) + start;
i = region;
while (i >= start && i < end)
{
if (!*i)
return (const char *)region;
i++;
}
return 0;
}

View File

@@ -0,0 +1,107 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef GSP_ELF_H_
#define GSP_ELF_H_
#include <nvtypes.h>
#ifdef __cplusplus
extern "C" {
#endif
// Structures for Loader
typedef struct
{
NvU8 ident[16];
NvU16 type;
NvU16 machine;
NvU32 version;
NvU64 entry;
NvU64 phoff;
NvU64 shoff;
NvU32 flags;
NvU16 ehsize;
NvU16 phentsize;
NvU16 phnum;
NvU16 shentsize;
NvU16 shnum;
NvU16 shstrndx;
} elf64_header;
typedef struct
{
NvU32 type;
NvU32 flags;
NvU64 offset;
NvU64 vaddr;
NvU64 paddr;
NvU64 filesz;
NvU64 memsz;
NvU64 align;
} elf64_phdr;
#define PF_X 1
#define PF_W 2
#define PF_R 4
#define PT_LOAD 1
// Structures for finding Symbols
typedef struct
{
NvU32 name;
NvU32 type;
NvU64 flags;
NvU64 addr;
NvU64 offset;
NvU64 size;
NvU32 link;
NvU32 info;
NvU64 addralign;
NvU64 entsize;
} elf64_shdr;
typedef struct
{
NvU32 name;
NvU8 info;
NvU8 other;
NvU16 shndx;
NvU64 value;
NvU64 size;
} elf64_sym;
// Core ELF API
NvBool libosElfFindSectionByName(
elf64_header *elf, const char *sectionName, NvU8 **start, NvU8 **end, NvU64 *va_base);
NvBool
libosElfFindSectionByAddress(elf64_header *elf, NvU64 address, NvU8 **start, NvU8 **end, NvU64 *va_base);
void *libosElfReadVirtual(elf64_header *elf, NvU64 address, NvU64 size);
const char *libosElfReadStringVirtual(elf64_header *elf, NvU64 address);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,885 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2017-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef NVRM
# include <stddef.h>
# include <nvport/nvport.h>
# define printf(fmt, ...) nv_printf(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#else // NVRM
# include <memory.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define portMemCopy(d, l, s, m) memcpy(d, s, l)
# define portMemSet(d, v, l) memset(d, v, l)
# define portStringCompare(str1, str2, l) strcmp(str1, str2)
# define portMemAllocNonPaged(l) malloc(l);
# define portMemFree(p) free(p);
#endif // NVRM
#include "nvtypes.h"
#include "lines.h"
typedef struct
{
const NvU8 *buffer;
NvU64 offset;
NvU64 size;
} DwarfStream;
static void libosDwarfBuildTables(libosDebugResolver *pThis);
static void dwarfBuildARangeTable(libosDebugResolver *pThis);
static void dwarfSetARangeTableLineUnit(libosDebugResolver *pThis, DwarfStream unit, NvU64 address);
// http://www.dwarfstd.org/doc/dwarf-2.0.0.pdf
// Debug Line information related structures
// (for branch history and call stacks)
enum
{
DW_LNS_extended_operation = 0,
DW_LNS_copy = 1,
DW_LNS_advance_pc = 2,
DW_LNS_advance_line = 3,
DW_LNS_set_file = 4,
DW_LNS_set_column = 5,
DW_LNS_negate_stmt = 6,
DW_LNS_set_basic_block = 7,
DW_LNS_const_add_pc = 8,
DW_LNS_fixed_advance_pc = 9,
DW_LNS_set_prologue_end = 10,
DW_LNS_set_epilogue_begin = 11,
};
enum
{
DW_LNE_end_sequence = 1,
DW_LNE_set_address = 2,
DW_LNE_define_file = 3,
DW_LNE_set_discriminator = 4,
};
/**
*
* @brief Creates a resolver object for a given ELF.
* No resources or memory are retained by this call.
*
* @param[in] elf
* An elf containing .debug_line and or .symtab data
* @param[in] pThis
* An uninitialized resolver object.
*/
void libosDebugResolverConstruct(libosDebugResolver *pThis, elf64_header *elf)
{
NvU64 vabase;
libosElfFindSectionByName(elf, ".debug_line", &pThis->debugLineStart, &pThis->debugLineEnd, &vabase);
libosElfFindSectionByName(
elf, ".debug_aranges", &pThis->debugARangesStart, &pThis->debugARangesEnd, &vabase);
libosElfFindSectionByName(elf, ".symtab", &pThis->symtabStart, &pThis->symtabEnd, &vabase);
libosElfFindSectionByName(elf, ".strtab", &pThis->strtabStart, &pThis->strtabEnd, &vabase);
libosDwarfBuildTables(pThis);
}
void libosDebugResolverDestroy(libosDebugResolver *pThis)
{
if (pThis->arangeTable != NULL)
{
portMemFree(pThis->arangeTable);
pThis->arangeTable = NULL;
}
}
/**
*
* @brief Helper method to resolve symbol name to VA
*
* @param[in] pThis
* An initialized resolver object.
* @param[in] symbolName
* Name of a symbol (code or data) for lookup.
* @param[out] address
* The virtual address for the given symbol.\
*/
NvBool libosDebugResolveSymbolToVA(libosDebugResolver *pThis, const char *symbolName, NvU64 *address)
{
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
NvU64 count = (pThis->symtabEnd - pThis->symtabStart) / sizeof(elf64_sym);
while (count--)
{
if (i->name != 0)
{
if (!portStringCompare(i->name + (const char *)pThis->strtabStart, symbolName, 0x1000))
{
*address = i->value;
return NV_TRUE;
}
}
i++;
}
return NV_FALSE;
}
/**
*
* @brief Helper method to resolve symbol VA back to name
* @note This will match on addresses within a sized symbol (!)
*
* @param[in] pThis
* An initialized resolver object.
* @param[in] symbolAddress
* An address for which we want either
* (1) The symbol that exactly resolves to this address
* (2) The symbol that contains this address
* @param[out] offset
* Offsets are returned if the match is within a symbol.
* @param[out] name
* The symbol name containing or matching the search address
*/
NvBool libosDebugResolveSymbolToName(
libosDebugResolver *pThis, NvU64 symbolAddress, const char **name, NvU64 *offset)
{
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
NvU64 count = (pThis->symtabEnd - pThis->symtabStart) / sizeof(elf64_sym);
while (count--)
{
if (symbolAddress == i->value || (symbolAddress >= i->value && symbolAddress < i->value + i->size))
{
if (i->name)
*name = i->name + (const char *)pThis->strtabStart;
else
*name = "";
*offset = symbolAddress - i->value;
return NV_TRUE;
}
i++;
}
return NV_FALSE;
}
/**
*
* @brief Helper method to look up the symbol for a VA and return the VA range
* that symbol covers.
* @note This will match on addresses within a sized symbol (!)
*
* @param[in] pThis
* An initialized resolver object.
* @param[in] symbolAddress
* An address for which we want either
* (1) The symbol that exactly resolves to this address
* (2) The symbol that contains this address
* @param[out] symStart
* First address covered by the symbol..
* @param[out] symEnd
* One past the last address covered by the symbol.
*/
NvBool libosDebugGetSymbolRange(
libosDebugResolver *pThis, NvU64 symbolAddress, NvU64 *symStart, NvU64 *symEnd)
{
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
elf64_sym *symtabEnd = (elf64_sym *)pThis->symtabEnd;
for (; i < symtabEnd; i++)
{
if (symbolAddress == i->value ||
((symbolAddress >= i->value) && (symbolAddress < i->value + i->size)))
{
*symStart = i->value;
*symEnd = i->value + i->size;
return NV_TRUE;
}
}
return NV_FALSE;
}
static NvBool libosDwarfReadRaw(DwarfStream *stream, void *buffer, NvU64 size)
{
NvU64 newOffset = stream->offset + size;
if (newOffset > stream->size)
return NV_FALSE;
portMemCopy(buffer, (size_t)size, stream->buffer + stream->offset, size);
stream->offset = newOffset;
return NV_TRUE;
}
static NvBool libosDwarfExtractString(DwarfStream *stream, const char **string)
{
NvU64 offsetEnd = stream->offset;
while (1)
{
if (offsetEnd >= stream->size)
return NV_FALSE;
if (!stream->buffer[offsetEnd])
break;
offsetEnd++;
}
*string = (const char *)stream->buffer + stream->offset;
stream->offset = offsetEnd + 1;
return NV_TRUE;
}
#define DWARF_READ(stream, ptr) libosDwarfReadRaw(stream, ptr, sizeof(*ptr))
static NvBool dwarfReadLeb128Generic(DwarfStream *stream, NvU64 *presult, NvBool sextension)
{
NvU8 byte;
NvU64 bitsRead = 0, result = 0;
while (bitsRead < 64 && DWARF_READ(stream, &byte))
{
// Read 7 bits
result |= (NvU64)(byte & 0x7f) << bitsRead;
bitsRead += 7;
// Was this the last byte?
if (!(byte & 0x80))
{
// Sign extend based on the top bit we just read
if (sextension && bitsRead < 64 && (byte & 0x40))
result |= 0xFFFFFFFFFFFFFFFFULL << bitsRead;
// Return result
*presult = result;
return NV_TRUE;
}
}
return NV_FALSE;
}
static NvBool dwarfReadSleb128(DwarfStream *stream, NvS64 *result)
{
return dwarfReadLeb128Generic(stream, (NvU64 *)result, NV_TRUE /* sign extend */);
}
static NvBool dwarfReadUleb128(DwarfStream *stream, NvU64 *result)
{
return dwarfReadLeb128Generic(stream, result, NV_FALSE);
}
static NvBool dwarfReadFilename(DwarfStream *names, const char **directory, const char **filename, NvU64 file)
{
// Skip the directory names stream
DwarfStream dirnames = *names;
const char *name;
NvU64 directoryEntryId = 0;
NvU64 i;
*directory = "";
*filename = "";
if (!file)
return NV_FALSE;
do
{
if (!libosDwarfExtractString(names, &name))
return (NV_FALSE);
} while (*name);
// Walk through the file entries
for (i = 0; i < file; i++)
{
NvU64 mtime, size;
if (!libosDwarfExtractString(names, filename) || !dwarfReadUleb128(names, &directoryEntryId) ||
!dwarfReadUleb128(names, &mtime) || !dwarfReadUleb128(names, &size))
return NV_FALSE;
}
// Walk the directory table up until the required point
for (i = 0; i < directoryEntryId; i++)
if (!libosDwarfExtractString(&dirnames, directory))
return NV_FALSE;
return NV_TRUE;
}
/**
*
* @brief DWARF-2 Virtual machine interpreter for debug data
*
* @param[in] pThis
* An initialized resolver object.
* @param[in/out] unit
* A dwarf stream object initialized to the start of a unit in the
* .debug_lines elf section.
* @param[in] pc
* Virtual address of the code to resolve.
* @param[out] directory
* The source file directory for this line of code. Requires a .debug_line section.
* @param[out] filename
* The source file for this line of code. Requires a .debug_line section.
* @param[out] outputLine
* The source line for address. Requires a .debug_line section.
* @param[out] outputColumn
* The source column for this address. Requires additional debug info -g3.
* @param[in] matchedAddress
* Returns the virtual address to the start of the matched line/col.
* @param[in] bBuildTable
* Set to true when building the aranges index table.
*/
static NvBool dwarfParseUnitLines(
libosDebugResolver *pThis, DwarfStream unit, NvU64 pc, const char **directory, const char **filename,
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress, NvBool bBuildTable)
{
NvU16 version;
NvU32 prologueLength;
DwarfStream saveUnit = unit;
NvU64 headerOffset;
NvU8 minimumInstructionLength, defaultIsStmt, lineRange, opcodeBase;
NvS8 line_base;
NvU64 i;
DwarfStream names;
// Initial state of virtual machine
NvU64 previousAddress = 0, previousLine = 0, previousColumn = 0, previousFile = 0;
NvU64 address = 0, file = 1, line = 1, column = 0;
NvU8 isStmt;
//NvBool basicBlock = NV_FALSE
NvBool postEmitResetState = NV_FALSE;
//NvBool prologueEnd = NV_FALSE;
//NvBool epilogueBegin = NV_FALSE;
NvBool postEmitResetStateIsStmt = NV_FALSE;
//NvBool endSequence = NV_FALSE;
NvU8 opcode;
if (!DWARF_READ(&unit, &version) || version > 2 || !DWARF_READ(&unit, &prologueLength))
{
return NV_FALSE;
}
headerOffset = unit.offset;
if (!DWARF_READ(&unit, &minimumInstructionLength) || !DWARF_READ(&unit, &defaultIsStmt) ||
!DWARF_READ(&unit, &line_base) || !DWARF_READ(&unit, &lineRange) || !DWARF_READ(&unit, &opcodeBase))
{
return NV_FALSE;
}
// Skip over the opcode lengths
for (i = 1; i < opcodeBase; i++)
{
NvU64 dummy;
if (!dwarfReadUleb128(&unit, &dummy))
{
return NV_FALSE;
}
}
// Names section starts here inside after the prologue
names = unit;
// Skip prologue
unit.offset = headerOffset;
if (unit.size - unit.offset < prologueLength)
{
//printf("Bailing 3...\n");
return NV_FALSE;
}
unit.offset += prologueLength;
isStmt = defaultIsStmt;
// Run the line number information program for this unit
while (NV_TRUE)
{
NvBool emit_row = NV_FALSE;
//NvU64 offset = unit.offset;
if (!DWARF_READ(&unit, &opcode))
break;
//NvBool reset_basic_block = NV_FALSE;
// 6.2.5.1 Special Opcodes
if (opcode >= opcodeBase)
{
NvU8 normalizedOpcode = opcode - opcodeBase;
address += (normalizedOpcode / lineRange) * minimumInstructionLength;
line += line_base + normalizedOpcode % lineRange;
//reset_basic_block = NV_TRUE;
emit_row = NV_TRUE;
//printf(" [0x%08llx] Special opcode\n", offset);
}
// 6.2.5.3 Extended Opcodes
else if (opcode == DW_LNS_extended_operation)
{
NvU64 extBaseOffset = unit.offset, extraSize;
DwarfStream extra;
if (!dwarfReadUleb128(&unit, &extraSize))
return NV_FALSE;
if (unit.size - unit.offset < extraSize)
return NV_FALSE;
extra.buffer = unit.buffer + extBaseOffset;
extra.offset = unit.offset - extBaseOffset;
extra.size = extraSize + unit.offset - extBaseOffset;
unit.offset += extraSize;
if (!DWARF_READ(&extra, &opcode))
return NV_FALSE;
switch (opcode)
{
case DW_LNE_end_sequence:
emit_row = NV_TRUE;
postEmitResetStateIsStmt = isStmt;
postEmitResetState = NV_TRUE;
//printf(" [0x%08llx] Extended opcode 1: End of Sequence\n", offset);
break;
case DW_LNE_set_address:
switch (extra.size - extra.offset)
{
case 8:
if (!DWARF_READ(&extra, &address))
return NV_FALSE;
break;
case 4: {
NvU32 address32;
if (!DWARF_READ(&extra, &address32))
return NV_FALSE;
address = address32;
break;
}
default:
//printf("unexpected address length: %zu", extra.size - extra.offset);
return NV_FALSE;
}
//printf(" [0x%08llx] Extended opcode 2: set Address to 0x%llx\n", offset, address);
break;
case DW_LNE_define_file: {
const char *fname = "";
NvU64 dir, time, size;
libosDwarfExtractString(&unit, &fname);
//printf(" [0x%08x] Define file: %s\n", fname, offset);
dwarfReadUleb128(&unit, &dir);
dwarfReadUleb128(&unit, &time);
dwarfReadUleb128(&unit, &size);
}
break;
case DW_LNE_set_discriminator: // For profilers, how many code paths pass through this insn
{
NvU64 discriminator;
dwarfReadUleb128(&extra, &discriminator);
//printf(" [0x%08llx] Extended opcode 4: set Discriminator to %lld\n", offset, discriminator);
break;
}
default:
//printf(" [0x%08llx] unknown extended opcode: %d\n", offset, opcode);
return NV_FALSE;
}
}
else
{
/* "Standard" opcodes. */
switch (opcode)
{
case DW_LNS_copy:
emit_row = NV_TRUE;
//reset_basic_block = NV_TRUE;
//printf(" [0x%08llx] Copy\n", offset);
break;
case DW_LNS_advance_pc: {
NvU64 delta;
if (!dwarfReadUleb128(&unit, &delta))
return NV_FALSE;
address += delta * minimumInstructionLength;
//printf(" [0x%08llx] Advance PC by %lld to 0x%llx\n", offset, delta, address);
break;
}
case DW_LNS_fixed_advance_pc: {
NvU16 delta = 0;
DWARF_READ(&unit, &delta);
address += delta * minimumInstructionLength;
//printf(" [0x%08llx] Advance PC by fixed size amount %d to 0x%llx\n",offset , delta, address);
break;
}
case DW_LNS_advance_line: {
NvS64 delta;
if (!dwarfReadSleb128(&unit, &delta))
return NV_FALSE;
line += delta;
//printf(" [0x%08llx] Advance Line by %lld to %lld\n", offset, delta, line);
break;
}
case DW_LNS_set_file:
if (!dwarfReadUleb128(&unit, &file))
return NV_FALSE;
//printf(" [0x%08llx] Set File Name to entry %lld in the File Name Table\n", offset, file);
break;
case DW_LNS_set_column:
if (!dwarfReadUleb128(&unit, &column))
return NV_FALSE;
//printf(" [0x%08llx] Set column to %lld\n", offset, column);
break;
case DW_LNS_negate_stmt:
isStmt = !isStmt;
//printf(" [0x%08llx] Set isStmt to %d\n", offset, isStmt);
break;
case DW_LNS_set_basic_block:
//basicBlock = NV_TRUE;
//printf(" [0x%08llx] Set basic block\n", offset);
break;
case DW_LNS_const_add_pc: {
NvU64 delta = ((255 - opcodeBase) / lineRange) * minimumInstructionLength;
address += delta;
//printf(" [0x%08llx] Add pc by %lld to %08llx\n", offset, delta, address);
break;
}
case DW_LNS_set_prologue_end:
//printf(" [0x%08llx] Set prologue end\n", offset);
//prologueEnd = NV_TRUE;
break;
case DW_LNS_set_epilogue_begin:
//printf(" [0x%08llx] Set epilogie begin\n", offset);
//epilogueBegin = NV_TRUE;
break;
default:
//printf(" [0x%08llx] unknown standard opcode: %d\n", offset, opcode);
return NV_FALSE;
}
}
if (emit_row)
{
if (bBuildTable)
{
dwarfSetARangeTableLineUnit(pThis, saveUnit, address);
return NV_FALSE;
}
if ((previousAddress && (pc >= previousAddress && pc < address)))
{
dwarfReadFilename(&names, directory, filename, previousFile);
*outputLine = previousLine;
*outputColumn = previousColumn;
*matchedAddress = pc;
return NV_TRUE;
}
previousAddress = address;
previousFile = file;
previousLine = line;
previousColumn = column;
}
if (postEmitResetState)
{
address = 0;
file = 1;
line = 1;
column = 0;
isStmt = postEmitResetStateIsStmt;
//basicBlock = NV_FALSE;
postEmitResetState = NV_FALSE;
//endSequence = NV_FALSE;
//prologueEnd = NV_FALSE;
//epilogueBegin = NV_FALSE;
}
//if (reset_basic_block)
// basicBlock = NV_FALSE;
}
return NV_FALSE;
}
/**
*
* @brief Resolve an address to source file and line location for DWARF-2
*
* @param[in] pThis
* An initialized resolver object.
* @param[in] address
* Virtual address of the code to resolve.
* @param[out] filename
* The source file for this line of code. Requires a .debug_line section.
* @param[out] outputLine
* The source line for address. Requires a .debug_line section.
* @param[out] outputColumn
* The source column for this address. Requires additional debug info -g3.
* @param[in] matchedAddress
* Returns the virtual address to the start of the matched line/col.
*/
NvBool libosDwarfResolveLine(
libosDebugResolver *pThis, NvU64 address, const char **directory, const char **filename,
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress)
{
ARangeTupple *pFoundARange = NULL;
DwarfStream unit;
NvU32 i;
// Find entry in aranges table
for (i = 0; i < pThis->nARangeEntries; i++)
{
if ((address >= pThis->arangeTable[i].address) &&
(address < pThis->arangeTable[i].address + pThis->arangeTable[i].length))
{
pFoundARange = &pThis->arangeTable[i];
if (pFoundARange->lineUnitBuffer != NULL)
{
// Found cached line into in ARange table.
unit.buffer = pFoundARange->lineUnitBuffer;
unit.offset = 0;
unit.size = pFoundARange->lineUnitSize;
if (dwarfParseUnitLines(
pThis, unit, address, directory, filename, outputLine, outputColumn, matchedAddress,
NV_FALSE))
{
return NV_TRUE;
}
}
break;
}
}
return NV_FALSE;
}
/**
*
* @brief Create a table indexing the units in .debug_line elf section
*
*
* @param[in/out] pThis
* An initialized resolver object.
*/
static void libosDwarfBuildTables(libosDebugResolver *pThis)
{
NvU32 tableSize;
DwarfStream debugLines;
DwarfStream unit;
NvU32 currentUnit = 1;
NvU32 unitSize;
pThis->arangeTable = NULL;
pThis->nARangeEntries = 0;
// Run through the .debug_aranges elf section to get a count of consolidated ranges.
dwarfBuildARangeTable(pThis);
tableSize = (pThis->nARangeEntries + 1) * sizeof(ARangeTupple);
// Allocate the table.
pThis->arangeTable = portMemAllocNonPaged(tableSize);
portMemSet(pThis->arangeTable, 0, tableSize);
// Run through the .debug_aranges elf section again to populate the table.
dwarfBuildARangeTable(pThis);
debugLines.buffer = pThis->debugLineStart; debugLines.offset = 0; debugLines.size = pThis->debugLineEnd - pThis->debugLineStart;
// Run through the .debug_line elf section to match units to the arange table.
for (currentUnit = 1;; currentUnit++)
{
if (!DWARF_READ(&debugLines, &unitSize) || unitSize >= 0xfffffff0)
{
break;
}
if (debugLines.size - debugLines.offset < unitSize)
{
break;
}
unit.buffer = debugLines.buffer + debugLines.offset;
unit.offset = 0;
unit.size = unitSize;
dwarfParseUnitLines(pThis, unit, 0, NULL, NULL, NULL, NULL, NULL, NV_TRUE);
debugLines.offset += unitSize;
}
}
/**
*
* @brief Walk the .debug_aranges elf section, consolidate adjacent ranges,
* and create a table with an entry for each range.
*
* @param[in/out] pThis
* An initialized resolver object.
*/
static void dwarfBuildARangeTable(libosDebugResolver *pThis)
{
DwarfStream debugARanges = {
pThis->debugARangesStart, 0, pThis->debugARangesEnd - pThis->debugARangesStart};
DwarfStream unit;
NvU32 nUnit = 0;
NvU32 nARangeEntries = 0;
for (nUnit = 1;; nUnit++)
{
NvU32 unit_size = 0xffffffff;
NvU32 debugInfoOffset = 0xffffffff;
NvU16 version = 0xffff;
NvU8 addressSize = 0xff;
NvU8 selectorSize = 0xff;
NvU32 nUnitTupples;
NvU64 combAddress = 0;
NvU64 combLength = 0;
if (!DWARF_READ(&debugARanges, &unit_size) || unit_size >= 0xfffffff0)
{
break;
}
if (debugARanges.size - debugARanges.offset < unit_size)
{
break;
}
unit.buffer = debugARanges.buffer + debugARanges.offset - sizeof unit_size;
unit.offset = sizeof unit_size;
unit.size = unit_size + sizeof unit_size;
debugARanges.offset += unit_size;
if (!DWARF_READ(&unit, &version) || version != 2 || !DWARF_READ(&unit, &debugInfoOffset) ||
!DWARF_READ(&unit, &addressSize) || !DWARF_READ(&unit, &selectorSize) || addressSize != 8 ||
selectorSize != 0)
{
break;
}
// Pad to natural alignment
unit.offset = (unit.offset + 15) & ~15;
for (nUnitTupples = 0;; nUnitTupples++)
{
NvU64 address;
NvU64 length;
if (!DWARF_READ(&unit, &address) || !DWARF_READ(&unit, &length))
{
address = 0;
length = 0;
}
if (address == combAddress + combLength)
{
combLength += length;
}
else
{
if (combAddress != 0 && combLength != 0)
{
if (pThis->arangeTable != NULL && nARangeEntries < pThis->nARangeEntries)
{
// Table has been allocated -- fill it in.
ARangeTupple *pEntry = &pThis->arangeTable[nARangeEntries];
pEntry->address = combAddress;
pEntry->length = (NvU32)combLength;
pEntry->arangeUnit = nUnit;
}
nARangeEntries++;
}
combAddress = address;
combLength = length;
}
if (address == 0 && length == 0)
break;
}
}
pThis->nARangeEntries = nARangeEntries;
}
/**
*
* @brief Set a .debug_line reference in the table of consolidated aranges.
*
* @param[in] pThis
* An initialized resolver object.
* @param[in/out] unit
* A dwarf stream object initialized to the start of a unit in the
* .debug_lines elf section.
* @param[in] address
* Any virtual address contained in teh above .debug_lines unit.
*/
static void dwarfSetARangeTableLineUnit(libosDebugResolver *pThis, DwarfStream unit, NvU64 address)
{
NvU32 foundUnit = 0;
NvU32 i;
// Find entry in aranges table
for (i = 0; i < pThis->nARangeEntries; i++)
{
if ((address >= pThis->arangeTable[i].address) &&
(address < pThis->arangeTable[i].address + pThis->arangeTable[i].length))
{
foundUnit = pThis->arangeTable[i].arangeUnit;
break;
}
}
if (foundUnit == 0)
{
return;
}
//
// Walk backwards to first table entry with the same areange unit.
// Just in case -- I think i should always point to the first unit entry.
//
while ((i > 0) && (foundUnit == pThis->arangeTable[i - 1].arangeUnit))
{
i--;
}
// Walk forwards setting the line unit info for all entries with the same arange unit.
for (; (foundUnit == pThis->arangeTable[i].arangeUnit); i++)
{
pThis->arangeTable[i].lineUnitBuffer = unit.buffer;
pThis->arangeTable[i].lineUnitSize = (NvU32)unit.size;
}
}

View File

@@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2017-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LINES_H_
#define LINES_H_
#include "elf.h"
typedef struct
{
NvU64 address;
NvU32 length;
NvU32 arangeUnit;
const NvU8 *lineUnitBuffer;
NvU32 lineUnitSize;
} ARangeTupple;
typedef struct
{
NvU8 *debugLineStart, *debugLineEnd;
NvU8 *debugARangesStart, *debugARangesEnd;
NvU8 *symtabStart, *symtabEnd;
NvU8 *strtabStart, *strtabEnd;
ARangeTupple *arangeTable;
NvU32 nARangeEntries;
} libosDebugResolver;
void libosDebugResolverConstruct(libosDebugResolver *pThis, elf64_header *elf);
void libosDebugResolverDestroy(libosDebugResolver *pThis);
// @note Optimized for single lookup (no search structures are created)
NvBool libosDebugResolveSymbolToVA(libosDebugResolver *pThis, const char *symbol, NvU64 *address);
NvBool libosDebugResolveSymbolToName(
libosDebugResolver *pThis, NvU64 symbolAddress, const char **name, NvU64 *offset);
NvBool libosDwarfResolveLine(
libosDebugResolver *pThis, NvU64 address, const char **directory, const char **filename,
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress);
NvBool libosDebugGetSymbolRange(
libosDebugResolver *pThis, NvU64 symbolAddress, NvU64 *symStart, NvU64 *symEnd);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LOGDECODE_H_
#define LOGDECODE_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef NVRM
# define LIBOS_LOG_DECODE_ENABLE 1
# define LIBOS_LOG_TO_NVLOG 1
# define LIBOS_LOG_MAX_LOGS 5 // Max logs per GPU
#else // NVRM
# include <stdio.h>
# define LIBOS_LOG_DECODE_ENABLE 1
# define LIBOS_LOG_TO_NVLOG 0
# define LIBOS_LOG_MAX_LOGS 160 // Max logs for all GPUs for offline decoder
#endif // NVRM
#define LIBOS_LOG_ENABLE (LIBOS_LOG_TO_NVLOG || LIBOS_LOG_DECODE_ENABLE)
#if LIBOS_LOG_DECODE_ENABLE
# include "../include/libos_log.h"
# include "lines.h"
#endif
// Forward declarations.
struct LIBOS_LOG_DECODE_LOG;
typedef struct LIBOS_LOG_DECODE_LOG LIBOS_LOG_DECODE_LOG;
#define LIBOS_LOG_LINE_BUFFER_SIZE 128
#define LIBOS_LOG_MAX_ARGS 20
#if LIBOS_LOG_DECODE_ENABLE
# include "nvctassert.h"
typedef struct
{
NV_DECLARE_ALIGNED(LIBOS_LOG_DECODE_LOG *log, 8);
NV_DECLARE_ALIGNED(libosLogMetadata *meta, 8);
NV_DECLARE_ALIGNED(NvU64 timeStamp, 8);
NvU64 args[LIBOS_LOG_MAX_ARGS];
} LIBOS_LOG_DECODE_RECORD;
// Size of LIBOS_LOG_DECODE_RECORD without args, in number of NvU64 entries.
# define LIBOS_LOG_DECODE_RECORD_BASE 3
// Ensure that the size matches up (no padding in the struct)
ct_assert((LIBOS_LOG_DECODE_RECORD_BASE * sizeof(NvU64)) == (sizeof(LIBOS_LOG_DECODE_RECORD) - sizeof(((LIBOS_LOG_DECODE_RECORD*)NULL)->args)));
#endif // LIBOS_LOG_DECODE_ENABLE
#define TASK_NAME_MAX_LENGTH (8)
#define SOURCE_NAME_MAX_LENGTH (4)
// NvLog buffer
typedef struct
{
NvU32 gpuArch;
NvU32 gpuImpl;
NvU32 rsvd1;
NvU32 rsvd2;
char taskPrefix[TASK_NAME_MAX_LENGTH]; // Prefix string printed before each line.
NvU8 data[0];
} LIBOS_LOG_NVLOG_BUFFER;
struct LIBOS_LOG_DECODE_LOG
{
volatile NvU64 *physicLogBuffer;
NvU64 logBufferSize; // Includes put pointer located in first 8 bytes.
NvU64 previousPut; // Keeps track of records already printed.
NvU64 putCopy; // End pointer for this batch.
NvU64 putIter; // Iterator for this batch.
NvU32 gpuInstance; // GPU that this log is associated with.
char taskPrefix[TASK_NAME_MAX_LENGTH]; // Prefix string printed before each line.
#if LIBOS_LOG_TO_NVLOG
NvU32 hNvLogNoWrap; // No wrap buffer captures first records.
NvU32 hNvLogWrap; // Wrap buffer captures last records.
NvBool bNvLogNoWrap; // NV_TRUE if no wrap buffer not full.
#endif
#if LIBOS_LOG_DECODE_ENABLE
LIBOS_LOG_DECODE_RECORD record;
#endif
};
typedef struct
{
char sourceName[SOURCE_NAME_MAX_LENGTH]; // GSP, PMU etc
NvU64 numLogBuffers;
LIBOS_LOG_DECODE_LOG log[LIBOS_LOG_MAX_LOGS];
#if LIBOS_LOG_DECODE_ENABLE
elf64_header *elf;
libosDebugResolver resolver;
NvU64 *scratchBuffer; // Sorted by timestamp.
NvU64 scratchBufferSize; // Sum of logBufferSize.
char *curLineBufPtr; // Current position in lineBuffer.
// Decodes into lineBuffer, then prints as a string.
char lineBuffer[LIBOS_LOG_LINE_BUFFER_SIZE];
NvBool bSynchronousBuffer;
NvBool bPtrSymbolResolve;
#endif // LIBOS_LOG_DECODE_ENABLE
#if defined(NVSYM_STANDALONE) && !defined(PROTODMP_BUILD)
FILE *fout; // nvlog_decoder outputs to FILE descriptors
#elif defined(NVWATCH)
char *dest; // nvwatch dumps data into a string
#endif
} LIBOS_LOG_DECODE;
#if defined(NVSYM_STANDALONE) && !defined(PROTODMP_BUILD)
void libosLogCreate(LIBOS_LOG_DECODE *logDecode, FILE *fout);
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName, FILE *fout);
#elif defined(NVWATCH)
void libosLogCreate(LIBOS_LOG_DECODE *logDecode, char *dest);
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName, char *dest);
#else
void libosLogCreate(LIBOS_LOG_DECODE *logDecode);
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName);
#endif
void libosLogAddLogEx(LIBOS_LOG_DECODE *logDecode, void *buffer, NvU64 bufferSize, NvU32 gpuInstance, NvU32 gpuArch, NvU32 gpuImpl, const char *name);
void libosLogAddLog(LIBOS_LOG_DECODE *logDecode, void *buffer, NvU64 bufferSize, NvU32 gpuInstance, const char *name);
#if LIBOS_LOG_DECODE_ENABLE
void libosLogInit(LIBOS_LOG_DECODE *logDecode, elf64_header *elf);
void libosLogInitEx(
LIBOS_LOG_DECODE *logDecode, elf64_header *elf, NvBool bSynchronousBuffer, NvBool bPtrSymbolResolve);
#else
void libosLogInit(LIBOS_LOG_DECODE *logDecode, void *elf);
void libosLogInitEx(
LIBOS_LOG_DECODE *logDecode, void *elf, NvBool bSynchronousBuffer, NvBool bPtrSymbolResolve);
#endif // LIBOS_LOG_DECODE_ENABLE
void libosLogDestroy(LIBOS_LOG_DECODE *logDecode);
void libosExtractLogs(LIBOS_LOG_DECODE *logDecode, NvBool bSyncNvLog);
#ifdef __cplusplus
}
#endif
#endif // LOGDECODE_H_

View File

@@ -0,0 +1,154 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// TODO: This file is is not libos specific, so it really does not belong under
// uproc/os/libos-v2.0.0. It is used by booter, bootloader, libos, GSP-RM,
// and kernel RM. An appropriate location might be uproc/common/inc, but
// that directory is not currently synced by DVS for driver builds.
#pragma once
#ifndef GSP_FW_WPR_META_H_
#define GSP_FW_WPR_META_H_
/*!
* GSP firmware WPR metadata
*
* Initialized by CPU-RM and DMA'd to FB, at the end of what will be WPR2.
* Verified, and locked in WPR2 by Booter.
*
* Firmware scrubs the last 256mb of FB, no memory outside of this region
* may be used until the FW RM has scrubbed the remainder of memory.
*
* ---------------------------- <- fbSize (end of FB, 1M aligned)
* | VGA WORKSPACE |
* ---------------------------- <- vbiosReservedOffset (64K? aligned)
* | (potential align. gap) |
* ---------------------------- <- gspFwWprEnd (128K aligned)
* | FRTS data | (frtsSize is 0 on GA100)
* | ------------------------ | <- frtsOffset
* | BOOT BIN (e.g. SK + BL) |
* ---------------------------- <- bootBinOffset
* | GSP FW ELF |
* ---------------------------- <- gspFwOffset
* | GSP FW (WPR) HEAP |
* ---------------------------- <- gspFwHeapOffset
* | Booter-placed metadata |
* | (struct GspFwWprMeta) |
* ---------------------------- <- gspFwWprStart (128K aligned)
* | GSP FW (non-WPR) HEAP |
* ---------------------------- <- nonWprHeapOffset, gspFwRsvdStart
* (GSP_CARVEOUT_SIZE bytes from end of FB)
*/
typedef struct
{
// Magic
// BL to use for verification (i.e. Booter locked it in WPR2)
NvU64 magic; // = 0xdc3aae21371a60b3;
// Revision number of Booter-BL-Sequencer handoff interface
// Bumped up when we change this interface so it is not backward compatible.
// Bumped up when we revoke GSP-RM ucode
NvU64 revision; // = 1;
// ---- Members regarding data in SYSMEM ----------------------------
// Consumed by Booter for DMA
NvU64 sysmemAddrOfRadix3Elf;
NvU64 sizeOfRadix3Elf;
NvU64 sysmemAddrOfBootloader;
NvU64 sizeOfBootloader;
// Offsets inside bootloader image needed by Booter
NvU64 bootloaderCodeOffset;
NvU64 bootloaderDataOffset;
NvU64 bootloaderManifestOffset;
NvU64 sysmemAddrOfSignature;
NvU64 sizeOfSignature;
// ---- Members describing FB layout --------------------------------
NvU64 gspFwRsvdStart;
NvU64 nonWprHeapOffset;
NvU64 nonWprHeapSize;
NvU64 gspFwWprStart;
// GSP-RM to use to setup heap.
NvU64 gspFwHeapOffset;
NvU64 gspFwHeapSize;
// BL to use to find ELF for jump
NvU64 gspFwOffset;
// Size is sizeOfRadix3Elf above.
NvU64 bootBinOffset;
// Size is sizeOfBootloader above.
NvU64 frtsOffset;
NvU64 frtsSize;
NvU64 gspFwWprEnd;
// GSP-RM to use for fbRegionInfo?
NvU64 fbSize;
// ---- Other members -----------------------------------------------
// GSP-RM to use for fbRegionInfo?
NvU64 vgaWorkspaceOffset;
NvU64 vgaWorkspaceSize;
// Boot count. Used to determine whether to load the firmware image.
NvU64 bootCount;
// TODO: the partitionRpc* fields below do not really belong in this
// structure. The values are patched in by the partition bootstrapper
// when GSP-RM is booted in a partition, and this structure was a
// convenient place for the bootstrapper to access them. These should
// be moved to a different comm. mechanism between the bootstrapper
// and the GSP-RM tasks.
// Shared partition RPC memory (physical address)
NvU64 partitionRpcAddr;
// Offsets relative to partitionRpcAddr
NvU16 partitionRpcRequestOffset;
NvU16 partitionRpcReplyOffset;
// Pad structure to exactly 256 bytes. Can replace padding with additional
// fields without incrementing revision. Padding initialized to 0.
NvU32 padding[7];
// BL to use for verification (i.e. Booter says OK to boot)
NvU64 verified; // 0x0 -> unverified, 0xa0a0a0a0a0a0a0a0 -> verified
} GspFwWprMeta;
#define GSP_FW_WPR_META_VERIFIED 0xa0a0a0a0a0a0a0a0ULL
#define GSP_FW_WPR_META_REVISION 1
#define GSP_FW_WPR_META_MAGIC 0xdc3aae21371a60b3ULL
#endif // GSP_FW_WPR_META_H_

View File

@@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2018-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
// @todo: Remove this once chips_a/drivers/resman/arch/nvalloc/common/inc/riscvifriscv.h has been
// switched to directly include this file.
#if !defined(RISCVIFRISCV_H) && !defined(LIBOS_INIT_H_)
#define LIBOS_INIT_H_
#define LIBOS_MEMORY_REGION_INIT_ARGUMENTS_MAX 4096
typedef NvU64 LibosAddress;
typedef enum {
LIBOS_MEMORY_REGION_NONE,
LIBOS_MEMORY_REGION_CONTIGUOUS,
LIBOS_MEMORY_REGION_RADIX3
} LibosMemoryRegionKind;
typedef enum {
LIBOS_MEMORY_REGION_LOC_NONE,
LIBOS_MEMORY_REGION_LOC_SYSMEM,
LIBOS_MEMORY_REGION_LOC_FB
} LibosMemoryRegionLoc;
#define LIBOS_MEMORY_REGION_RADIX_PAGE_SIZE 4096
#define LIBOS_MEMORY_REGION_RADIX_PAGE_LOG2 12
typedef struct
{
LibosAddress id8; // Id tag.
LibosAddress pa; // Physical address.
LibosAddress size; // Size of memory area.
NvU8 kind; // See LibosMemoryRegionKind above.
NvU8 loc; // See LibosMemoryRegionLoc above.
} LibosMemoryRegionInitArgument;
#endif

View File

@@ -0,0 +1,195 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2018-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBOS_LOGGER_H_
#define LIBOS_LOGGER_H_
#include "nvtypes.h"
/**
* @brief The log metadata structures and format strings are stripped
* These structures are emitted into the .logging section
* which is stripped from the image as the final build step.
*
*/
typedef struct
{
NV_DECLARE_ALIGNED(const char *filename, 8);
NV_DECLARE_ALIGNED(const char *format, 8);
NV_DECLARE_ALIGNED(NvU32 lineNumber, 8);
NvU8 argumentCount; //! Count of arguments not including format string.
NvU8 printLevel;
} libosLogMetadata;
/*!
* Count arguments
*
*/
#define LIBOS_MACRO_GET_COUNT(...) \
LIBOS_MACRO_GET_19TH(__VA_ARGS__, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define LIBOS_MACRO_GET_19TH( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, N, ...) \
N
/*!
* Utility
*
*/
#define LIBOS_MACRO_PASTE(fmt, b) fmt##b
#define LIBOS_MACRO_PASTE_EVAL(fmt, b) LIBOS_MACRO_PASTE(fmt, b)
#define LIBOS_MACRO_FIRST(format_string, ...) format_string
/*!
* Cast remaining log arguments to integers for storage
*
*/
#define LIBOS_LOG_BUILD_ARG(a) (NvU64)(a),
#define LIBOS_LOG_BUILD_1(fmt)
#define LIBOS_LOG_BUILD_2(fmt, b) LIBOS_LOG_BUILD_ARG(b)
#define LIBOS_LOG_BUILD_3(fmt, b, c) LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c)
#define LIBOS_LOG_BUILD_4(fmt, b, c, d) LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d)
#define LIBOS_LOG_BUILD_5(fmt, b, c, d, e) \
LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e)
#define LIBOS_LOG_BUILD_6(fmt, b, c, d, e, f) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f)
#define LIBOS_LOG_BUILD_7(fmt, b, c, d, e, f, g) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g)
#define LIBOS_LOG_BUILD_8(fmt, b, c, d, e, f, g, h) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h)
#define LIBOS_LOG_BUILD_9(fmt, b, c, d, e, f, g, h, i) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i)
#define LIBOS_LOG_BUILD_10(fmt, b, c, d, e, f, g, h, i, j) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j)
#define LIBOS_LOG_BUILD_11(fmt, b, c, d, e, f, g, h, i, j, k) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k)
#define LIBOS_LOG_BUILD_12(fmt, b, c, d, e, f, g, h, i, j, k, l) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l)
#define LIBOS_LOG_BUILD_13(fmt, b, c, d, e, f, g, h, i, j, k, l, m) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m)
#define LIBOS_LOG_BUILD_14(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n)
#define LIBOS_LOG_BUILD_15(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
LIBOS_LOG_BUILD_ARG(o)
#define LIBOS_LOG_BUILD_16(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p)
#define LIBOS_LOG_BUILD_17(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p) LIBOS_LOG_BUILD_ARG(q)
#define LIBOS_LOG_BUILD_18(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) \
LIBOS_LOG_BUILD_ARG(b) \
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p) LIBOS_LOG_BUILD_ARG(q) LIBOS_LOG_BUILD_ARG(r)
#define LIBOS_LOG_BUILD_APPLY(F, ...) F(__VA_ARGS__)
#define APPLY_REMAINDER(...) \
LIBOS_LOG_BUILD_APPLY( \
LIBOS_MACRO_PASTE_EVAL(LIBOS_LOG_BUILD_, LIBOS_MACRO_GET_COUNT(__VA_ARGS__)), __VA_ARGS__)
#define LOG_LEVEL_INFO 0
#define LOG_LEVEL_ERROR 1
# define LIBOS_SECTION_LOGGING __attribute__((section(".logging")))
#ifdef LIBOS_LOGGING_METADATA_SPLIT
/*!
* When the METADATA_SPLIT feature is enabled, libos print data is split between 4 input sections (all of which
* must be dropped from the final image). The default .logging is used for str literals and custom strings which
* are directly referenced by pointer (for %s substitution); .logging_const is used for format strings and the
* aux metadata; and .logging_metadata is used for metadata vars.
*
* The idea is to have a split where metadata-only changes (i.e. changing what data gets printed, line number changes
* in file with prints, file renames) will usually not affect the main image, and can be bundled together and
* relied upon to trigger custom ucode build release behavior.
* The only exception is renaming headers with prints inside static inline functions; since these don't overlap
* with basenames, and we can't reliably get a nonvolatile version of a header file name here, such name changes
* alone won't be able to trigger ucode releases.
*/
# define LIBOS_SECTION_LOGGING_CONST __attribute__((section(".logging_const")))
# define LIBOS_SECTION_LOGGING_METADATA __attribute__((section(".logging_metadata")))
# define LIBOS_LOGGING_AUX_METADATA_DUMP \
static const LIBOS_SECTION_LOGGING_CONST int libos_dummy_line[] LIBOS_ATTR_USED = {__LINE__};
#else // LIBOS_LOGGING_VOLATILE_METADATA_SPLIT
# define LIBOS_SECTION_LOGGING_CONST LIBOS_SECTION_LOGGING
# define LIBOS_SECTION_LOGGING_METADATA LIBOS_SECTION_LOGGING
# define LIBOS_LOGGING_AUX_METADATA_DUMP
#endif // LIBOS_LOGGING_VOLATILE_METADATA_SPLIT
/*!
* Used for log variables which we want to dump; clients may want to pick these up to check for metadata changes
*/
#define LIBOS_ATTR_USED __attribute__((used))
/*!
* Cast remaining log arguments to integers for storage
*/
#define LIBOS_LOG_INTERNAL(dispatcher, level, ...) \
do \
{ \
static const LIBOS_SECTION_LOGGING_CONST char libos_pvt_format[] = {LIBOS_MACRO_FIRST(__VA_ARGS__)}; \
static const LIBOS_SECTION_LOGGING_CONST char libos_pvt_file[] = {__FILE__}; \
LIBOS_LOGGING_AUX_METADATA_DUMP; \
static const LIBOS_SECTION_LOGGING_METADATA libosLogMetadata libos_pvt_meta = { \
.filename = &libos_pvt_file[0], \
.format = &libos_pvt_format[0], \
.lineNumber = __LINE__, \
.argumentCount = LIBOS_MACRO_GET_COUNT(__VA_ARGS__) - 1, \
.printLevel = level}; \
const NvU64 tokens[] = {APPLY_REMAINDER(__VA_ARGS__)(NvU64) & libos_pvt_meta}; \
dispatcher(sizeof(tokens) / sizeof(*tokens), &tokens[0]); \
} while (0)
#endif