Skip to content

WIP: Function overlay #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: upmem_release_120
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lld/ELF/LinkerScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ void LinkerScript::switchTo(OutputSection *sec) {
// ctx->outSec->alignment is the max of ALIGN and the maximum of input
// section alignments.
ctx->outSec->addr = advance(0, ctx->outSec->alignment);
expandMemoryRegions(ctx->outSec->addr - pos);
expandMemoryRegions(ctx->outSec->addr - pos);// TODO : check if this doesn't require some modification for overlay case
}
}

Expand Down Expand Up @@ -908,6 +908,10 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
ctx->memRegion = sec->memRegion;
ctx->lmaRegion = sec->lmaRegion;

if (sec->inOverlay && ctx->inOverlay && sec->addrExpr().getValue() == ctx->outSec->addrExpr().getValue())
ctx->memRegion->curPos -= ctx->outSec->size;
ctx->inOverlay = sec->inOverlay;

if (sec->flags & SHF_ALLOC) {
if (ctx->memRegion)
dot = ctx->memRegion->curPos;
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/LinkerScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ class LinkerScript final {
MemoryRegion *memRegion = nullptr;
MemoryRegion *lmaRegion = nullptr;
uint64_t lmaOffset = 0;
bool inOverlay = false;
};

llvm::DenseMap<StringRef, OutputSection *> nameToOutputSection;
Expand Down
7 changes: 6 additions & 1 deletion lld/ELF/ScriptParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,13 +526,18 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
OutputSection *os = readOverlaySectionDescription();
os->addrExpr = addrExpr;
if (prev)
os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
os->lmaExpr = [=] { return prev->size? prev->getLMA() + prev->size : prev->lmaExpr(); };
else
os->lmaExpr = lmaExpr;
v.push_back(os);
prev = os;
// TODO : make sure os->name is sanitized ("." -> "_") before being used in symbols
v.push_back(make<SymbolAssignment>(saver.save("__load_start_" + os->name), os->lmaExpr, getCurrentLocation()));
Expr load_stop = [=] { return os->size? os->getLMA() + os->size : os->lmaExpr(); };
v.push_back(make<SymbolAssignment>(saver.save("__load_stop_" + os->name), load_stop, getCurrentLocation()));
}


// According to the specification, at the end of the overlay, the location
// counter should be equal to the overlay base address plus size of the
// largest section seen in the overlay.
Expand Down
9 changes: 9 additions & 0 deletions lldb/source/Plugins/Process/Dpu/Dpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,15 @@ bool Dpu::ReadMRAM(uint32_t offset, void *buf, size_t size) {
return ret == DPU_OK;
}

bool Dpu::GetSymbol(const char *symbol_name, dpu_symbol_t *symbol) {
dpu_program_t *runtime = dpu_get_program(m_dpu);
lldbassert(runtime);
if (!runtime)
return false;
if (dpu_get_symbol(runtime, symbol_name, symbol) == DPU_OK) return true;
return false;
}

bool Dpu::AllocIRAMBuffer(uint8_t **iram, uint32_t *iram_size) {
dpu_description_t description = dpu_get_description(dpu_get_rank(m_dpu));
uint32_t nb_instructions = description->hw.memories.iram_size;
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/Dpu/Dpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class Dpu {
bool WriteMRAM(uint32_t offset, const void *buf, size_t size);
bool ReadMRAM(uint32_t offset, void *buf, size_t size);

bool GetSymbol(const char *symbol_name, dpu_symbol_t *symbol);

bool AllocIRAMBuffer(uint8_t **iram, uint32_t *iram_size);
bool FreeIRAMBuffer(uint8_t *iram);
bool GenerateSaveCore(const char *exe_path, const char *core_file_path,
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Process/Dpu/DpuContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ unsigned int DpuContext::GetExitStatus() {
}

lldb::addr_t DpuContext::GetPcOfThread(dpu_thread_t thread) {
return InstIdx2InstAddr(m_context->pcs[thread]);
uint32_t raw_pc = m_context->pcs[thread];
return InstIdx2InstAddr(raw_pc);
}

bool DpuContext::ScheduledThread(uint32_t thread) {
Expand Down
94 changes: 91 additions & 3 deletions lldb/source/Plugins/Process/Dpu/ProcessDpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "ThreadDpu.h"

extern "C" {
#include <dpu_program.h>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readjust header includes.
have together the backends includes, (dpu_types.h above)

}

#include <linux/unistd.h>
#include <sys/timerfd.h> /* TODO only exists on Linux */
#include <sys/types.h>
Expand Down Expand Up @@ -351,7 +355,7 @@ ProcessDpu::ProcessDpu(::pid_t pid, int terminal_fd, NativeDelegate &delegate,
SetState(StateType::eStateStopped, false);

m_iram_region.GetRange().SetRangeBase(k_dpu_iram_base);
m_iram_region.GetRange().SetRangeEnd(k_dpu_iram_base + m_iram_size);
m_iram_region.GetRange().SetRangeEnd(k_dpu_iram_base + k_dpu_viram_offset*6 + m_iram_size);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

operand space operand

m_iram_region.SetReadable(MemoryRegionInfo::eYes);
m_iram_region.SetWritable(MemoryRegionInfo::eYes);
m_iram_region.SetExecutable(MemoryRegionInfo::eYes);
Expand All @@ -374,6 +378,8 @@ ProcessDpu::ProcessDpu(::pid_t pid, int terminal_fd, NativeDelegate &delegate,

void ProcessDpu::InterfaceTimerCallback() {
unsigned int exit_status;
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "========= this is a log test ===========");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please cleanup when you're done with your experiment.

StateType current_state = m_dpu->PollStatus(&exit_status);
if (current_state != StateType::eStateInvalid) {
if (current_state == StateType::eStateExited) {
Expand Down Expand Up @@ -546,6 +552,7 @@ Status ProcessDpu::GetMemoryRegionInfo(lldb::addr_t load_addr,
range_info = m_mram_region;
} else if (m_iram_region.GetRange().Contains(load_addr)) {
range_info = m_iram_region;
// FIXME : add viram ranges

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do if necessary

} else {
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
Expand Down Expand Up @@ -578,8 +585,10 @@ size_t ProcessDpu::UpdateThreads() { return m_threads.size(); }

Status ProcessDpu::SetBreakpoint(lldb::addr_t addr, uint32_t size,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does function_group feature works with breakpoint now?
No worries if not and WIP status.
if it's not working yet, maybe return a failure if we try to breakpoint in such section would make sense for now?

same apply to unwinding.
it's a very experimental feature we understand.

bool hardware) {
size_t bytes_read;
Log *log(GetLogIfAnyCategoriesSet(POSIX_LOG_BREAKPOINTS));
if (hardware)
return SetHardwareBreakpoint(addr, size);
return SetHardwareBreakpoint(addr, size);
else
return SetSoftwareBreakpoint(addr, size);
}
Expand All @@ -593,7 +602,9 @@ Status ProcessDpu::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {

ProcessDpu::eMemoryAddressSpace
ProcessDpu::ComputeMemoryAddressSpace(lldb::addr_t addr, size_t size) {
if (addr >= k_dpu_iram_base &&
if (addr >= k_dpu_iram_base + k_dpu_viram_offset && ((addr & (~k_dpu_viram_msb_mask)) + size) <= (k_dpu_iram_base + m_iram_size)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't hesitate to \n to be more readable.
group your logical test with ( )
negate ?

return eMemoryAddressSpaceVIRAM;
} else if (addr >= k_dpu_iram_base &&
(addr + size) <= (k_dpu_iram_base + m_iram_size)) {
return eMemoryAddressSpaceIRAM;
} else if (addr >= k_dpu_mram_base &&
Expand All @@ -610,10 +621,20 @@ ProcessDpu::ComputeMemoryAddressSpace(lldb::addr_t addr, size_t size) {
Status ProcessDpu::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
Status error;
LLDB_LOG(log, "addr = {0:X}, buf = {1}, size = {2}", addr, buf, size);

bytes_read = 0;
switch (ComputeMemoryAddressSpace(addr, size)) {
case eMemoryAddressSpaceVIRAM:
// expected behaviour : if can fetch symbols, read correct mram location. Otherwise, read iram

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand your logic here.
how is that possible?

lldb::addr_t mram_addr;
error = ViramAddressToMramPhysicalAddress(addr, &mram_addr);
if (error.Fail())
return Status("ReadMemory: cannot convert viram to mram physical address");
if (!m_dpu->ReadMRAM(mram_addr - k_dpu_mram_base, buf, size))
return Status("ReadMemory: Cannot copy from MRAM");
break;
case eMemoryAddressSpaceIRAM:
if (!m_dpu->ReadIRAM(addr - k_dpu_iram_base, buf, size))
return Status("ReadMemory: Cannot copy from IRAM");
Expand All @@ -640,10 +661,26 @@ Status ProcessDpu::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status ProcessDpu::WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
size_t &bytes_written) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
Status error;
LLDB_LOG(log, "addr = {0:X}, buf = {1}, size = {2}", addr, buf, size);

bytes_written = 0;
switch (ComputeMemoryAddressSpace(addr, size)) {
case eMemoryAddressSpaceVIRAM:
// expected behaviour : if can fetch symbols, write to correct mram location and if fg is loaded, write to iram. Otherwise, only write to iram

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

lldb::addr_t mram_addr;
lldb::addr_t iram_addr;
error = ViramAddressToMramPhysicalAddress(addr, &mram_addr);
if (error.Fail())
return Status("WriteMemory: cannot convert viram to mram physical address");
if (!m_dpu->WriteMRAM(mram_addr - k_dpu_mram_base, buf, size))
return Status("WriteMemory: Cannot copy to MRAM");
error = ViramAddressToLoadedIramAddress(addr, &iram_addr);
if (error.Fail()) {
LLDB_LOG(log, "WriteMemory: Could not write viram to iram as this function group is not currently loaded");
} else if (!m_dpu->WriteIRAM(iram_addr - k_dpu_iram_base, buf, size))
return Status("WriteMemory: Cannot copy to IRAM");
break;
case eMemoryAddressSpaceIRAM:
if (!m_dpu->WriteIRAM(addr - k_dpu_iram_base, buf, size))
return Status("WriteMemory: Cannot copy to IRAM");
Expand All @@ -667,6 +704,57 @@ Status ProcessDpu::WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
return Status();
}

Status ProcessDpu::ViramAddressToMramPhysicalAddress(lldb::addr_t viram_addr, lldb::addr_t *mram_addr) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't hesitate to use \n in the two functions below :)

Status error;
size_t bytes_read;
lldb::addr_t overlay_start_address = 0;
lldb::addr_t load_starts_table_address = 0;
lldb::addr_t load_start_address = 0;
size_t fg_id = ((viram_addr & k_dpu_viram_msb_mask)/k_dpu_viram_offset) - 1;
const char *using_function_groups = std::getenv("USING_FUNCTION_GROUPS");
if (using_function_groups == NULL || using_function_groups[0] == '\0')
return Status("Could not find USING_FUNCTION_GROUPS env variable\n");
error = ReadMemory(ADDR_FG_IRAM_OVERLAY_START, &overlay_start_address, 4, bytes_read);
if(error.Fail() || bytes_read != 4)
return Status("could not read load start address\n");
overlay_start_address <<= 3;
lldbassert(viram_addr >= overlay_start_address);
error = ReadMemory(ADDR_FG_LOAD_STARTS_ADDR, &load_starts_table_address, 4, bytes_read);
if(error.Fail() || bytes_read != 4)
return Status("could not read load starts table address\n");
if (load_starts_table_address == 0)
return Status("function groups not properly initialized");
error = ReadMemory(load_starts_table_address+4*fg_id, &load_start_address, 4, bytes_read);
if(error.Fail() || bytes_read != 4)
return Status("could not read load start address\n");
*mram_addr = (viram_addr & ~k_dpu_viram_msb_mask) + load_start_address - overlay_start_address - k_dpu_iram_base + k_dpu_mram_base;
return Status();
}

Status ProcessDpu::ViramAddressToLoadedIramAddress(lldb::addr_t viram_addr, lldb::addr_t *iram_addr) {
Status error;
size_t bytes_read;
lldb::addr_t overlay_start_address;
// FIXME : try and fetch symbol instead of trusting overlay_start_address will always be stored at the same address in the elf
error = ReadMemory(ADDR_FG_IRAM_OVERLAY_START, &overlay_start_address, 4, bytes_read);
if(!error.Fail() && bytes_read == 4) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (fail)
   bail;

reduce the indentation

overlay_start_address <<= 3;
overlay_start_address += 0x80000000;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k_dpu_iram_base

if (viram_addr >= overlay_start_address && overlay_start_address != 0x80000000) {
uint32_t loaded_group_value;
// FIXME : try and fetch symbol instead of trusting the loaded_group will always be stored at the same address in the elf
error = ReadMemory(ADDR_FG_CURRENTLY_LOADED_GROUP, &loaded_group_value, 4, bytes_read);
if(!error.Fail() && bytes_read == 4) {
if ((viram_addr & k_dpu_viram_msb_mask) == k_dpu_viram_offset*(loaded_group_value+1)) {
*iram_addr = viram_addr & ~k_dpu_viram_msb_mask;
return Status();
}
}
}
}
return Status("This function group is not currently loaded in iram\n");
}

Status ProcessDpu::GetLoadedModuleFileSpec(const char *module_path,
FileSpec &file_spec) {
return DpuErrorStatus("GetLoadedModuleFileSpec: Not Implemented");
Expand Down
12 changes: 12 additions & 0 deletions lldb/source/Plugins/Process/Dpu/ProcessDpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
#include "ThreadDpu.h"
#include "lldb/Host/common/NativeProcessProtocol.h"

#define ADDR_FG_IRAM_OVERLAY_START 0x8

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constexpr maybe ?
and tolower

#define ADDR_FG_CURRENTLY_LOADED_GROUP 0x10
#define ADDR_FG_LOAD_STARTS_ADDR 0x18
#define ADDR_FG_INITIALIZED 0x20

namespace lldb_private {
class Status;
class Scalar;
Expand All @@ -39,6 +44,8 @@ const ArchSpec k_dpu_arch("dpu-upmem-dpurte");
constexpr lldb::addr_t k_dpu_wram_base = 0x00000000;
constexpr lldb::addr_t k_dpu_mram_base = 0x08000000;
constexpr lldb::addr_t k_dpu_iram_base = 0x80000000;
constexpr lldb::addr_t k_dpu_viram_offset = 0x00100000;
constexpr lldb::addr_t k_dpu_viram_msb_mask = k_dpu_viram_offset*0xf;
} // namespace dpu

namespace process_dpu {
Expand Down Expand Up @@ -96,6 +103,10 @@ class ProcessDpu : public NativeProcessProtocol {
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
size_t &bytes_written) override;

Status ViramAddressToMramPhysicalAddress(lldb::addr_t viram_addr, lldb::addr_t *mram_addr);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private function


Status ViramAddressToLoadedIramAddress(lldb::addr_t viram_addr, lldb::addr_t *iram_addr);

virtual llvm::Expected<lldb::addr_t>
AllocateMemory(size_t size, uint32_t permissions) override;

Expand Down Expand Up @@ -167,6 +178,7 @@ class ProcessDpu : public NativeProcessProtocol {
Status DpuErrorStatus(const char *message);

enum eMemoryAddressSpace {
eMemoryAddressSpaceVIRAM,
eMemoryAddressSpaceIRAM,
eMemoryAddressSpaceMRAM,
eMemoryAddressSpaceWRAM,
Expand Down
35 changes: 35 additions & 0 deletions lldb/source/Plugins/Process/Dpu/RegisterContextDpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ using namespace lldb_private::process_dpu;
namespace {

constexpr lldb::addr_t k_dpu_iram_base = 0x80000000;
constexpr lldb::addr_t k_dpu_viram_offset = 0x00100000;

} // end of anonymous namespace

Expand Down Expand Up @@ -78,6 +79,7 @@ RegisterContextDpu::RegisterContextDpu(ThreadDpu &thread, ProcessDpu &process)
process.GetThreadContext(thread.GetIndex(), m_context_reg, m_context_pc,
m_context_zf, m_context_cf,
m_registers_has_been_modified);
m_process = &process;
}

uint32_t RegisterContextDpu::GetRegisterSetCount() const { return 1; }
Expand All @@ -94,6 +96,38 @@ RegisterContextDpu::GetRegisterSet(uint32_t set_index) const {
return &g_reg_sets_dpu;
}

Status FixPc(ProcessDpu *process, uint32_t *pc) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abuse \n :)

Status error;
size_t bytes_read;
// uint64_t magic_value;
uint32_t initialized = 0;
lldb::addr_t overlay_start_address = 0;
uint32_t fg_id;

const char *using_function_groups = std::getenv("USING_FUNCTION_GROUPS");
if (using_function_groups == NULL || using_function_groups[0] == '\0')
return Status("Could not find USING_FUNCTION_GROUPS env variable\n");

error = process->ReadMemory(ADDR_FG_INITIALIZED, &initialized, 4, bytes_read);
if(error.Fail() || bytes_read != 4 || initialized == 0)
return Status("fg groups not initialized\n");

error = process->ReadMemory(ADDR_FG_IRAM_OVERLAY_START, &overlay_start_address, 4, bytes_read);
if(error.Fail() || bytes_read != 4)
return Status("could not read load start address\n");

overlay_start_address <<= 3;
if((*pc) < k_dpu_iram_base + overlay_start_address)
return Status("pc below overlay_start_address\n");

error = process->ReadMemory(ADDR_FG_CURRENTLY_LOADED_GROUP, &fg_id, 4, bytes_read);
if(error.Fail() || bytes_read != 4)
return Status("could not read load start address\n");

*pc |= k_dpu_viram_offset * (1 + fg_id);
return Status();
}

Status RegisterContextDpu::ReadRegister(const RegisterInfo *info,
RegisterValue &value) {
if (!info)
Expand All @@ -106,6 +140,7 @@ Status RegisterContextDpu::ReadRegister(const RegisterInfo *info,
*m_context_pc * 8 /*sizeof(iram_instruction_t)*/ + k_dpu_iram_base;
if (m_thread.GetState() == eStateSuspended)
pc++;
FixPc(m_process, &pc);
value.SetUInt32(pc);
} else if (reg == zf_dpu)
value.SetUInt32(*m_context_zf ? 1 : 0);
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/Dpu/RegisterContextDpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class RegisterContextDpu : public NativeRegisterContextRegisterInfo {
bool *m_context_zf;
bool *m_context_cf;
bool *m_registers_has_been_modified;
ProcessDpu *m_process;
};

} // namespace process_dpu
Expand Down
Loading