Extending Graphite. Adding new system calls and configuration parameters

Extending Graphite Adding new system calls and configuration parameters Session Overview • Adding new configuration parameters • Supporting new syst...
Author: Elizabeth Rose
3 downloads 0 Views 374KB Size
Extending Graphite Adding new system calls and configuration parameters

Session Overview • Adding new configuration parameters • Supporting new system calls – Handling system calls locally – Handling system call remotely

Configuring Graphite Configuration File

class config::Config

class Config

• Defaults to carbon_sim.cfg

• Declared in common/config/config.hpp • Parses parameters into a configuration tree

• Declared in common/misc/config.h • Caches parameter values • Used when parameter value needed at runtime

Configuration File • Arranged into sections and subsections – [perf_model] – [perf_model/l1_dcache/T1]

• Each parameter belongs to a section – [perf_model/l1_dcache/T1] cache_size = 32

• Add new sections and parameters here as needed

Adding New Parameters • Parser parses the parameters into a configuration tree • Parameter values can be searched by name • For each new parameter – Create a variable in the configuration cache to store its value – Create a function to retrieve this value – Fill in the value at initialization

Adding New Parameters /common/misc/config.h

class Config { private: int m_l1_dcache_size; public: int getL1DCacheSize() {return m_l1_dcache_size;} }

• For each new parameter – Create a variable in the configuration cache to store its value – Create a function to retrieve this value – Fill in the value at initialization

Adding New Parameters /common/misc/config.h

class Config { private: int m_l1_dcache_size; public: int getL1DCacheSize() {return m_l1_dcache_size;} }

• For each new parameter – Create a variable in the configuration cache to store its value – Create a function to retrieve this value – Fill in the value at initialization

Adding New Parameters /common/misc/config.cc

Config::Config() { m_l1_dcache_size = Sim()->getCfg()->getInt(“perf_model/l1_dcache/T1/cache_size”); }

• For each new parameter – Create a variable in the configuration cache to store its value – Create a function to retrieve this value – Fill in the value at initialization

Session Overview • Adding new configuration parameters • Supporting new system calls – Handling system calls locally – Handling system call remotely

Supporting new system calls • Application and OS have different views of the world • Simulated application: single process – Single address space – Single file descriptor table – Single pid, resource limits etc

• OS: multiple processes – Each host process has its own address space, file descriptor table etc

System Calls File Management

Memory Management

Synchronization/ Communication

open, access, read, write

mmap, munmap, brk

sigprocmask, sigsuspend, sigaction

getrlimit, nanosleep, gettid

Signal Management

Other syscalls

kill, waitpid, futex 11

Syscall Handling Machinery pin/handle_syscalls.h

• Syscall entry and exit callback functions

• syscallEnterRunModel() • thread id • Execution context • syscall standard

•syscallExitRunModel() • thread id • Execution context • syscall standard • Context modification for locally handled syscalls

Common/tile/ syscall_model.h

• Per tile syscall handling on client side • class SyscallMdl • runEnter() • runExit() • Syscall data • syscall number • scratchpads for arguments • Marshalling functions for remote syscalls

common/system/ syscall_server.h

• Part of the MCP • Handles all remote system calls

Session Overview • Adding new configuration parameters • Supporting new system calls – Handling system calls locally – Handling system call remotely

System Calls File Management

Memory Management

Synchronization/ Communication

open, access, read, write

mmap, munmap, brk

kill, waitpid, futex

sigprocmask, sigsuspend, sigaction

Signal Management

getrlimit, nanosleep, gettid

Other syscalls

Handled locally 14

Syscalls Handled Locally Core

Arguments are copied into a local buffer (if needed) On Syscall Entry

… … mov eax, 1 int $0x80 … …

Syscall Executed

On Syscall Exit

Arguments copied back into simulated memory (if needed)

Mechanism - Syscalls Handled Locally 15

Handling syscalls locally • Example: nanosleep – Two of its arguments are pointers to structures in memory – struct timespec *req (IN) • Specifies the time to sleep

– Struct timespec *rem (OUT) • Specifies remaining time if the call returns early

• Add callback functions at syscall entry and exit

Syscall Handling Machinery

pin/handle_syscalls.h

• Pin front end

common/tile/ syscall_model.h

• Client back end (per tile)

common/system/ syscall_server.h

• Server back end (MCP)

Handling syscall nanosleep pin/handle_syscall.cc void modifyNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std); void restoreNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std); void syscallEnterRunModel(CONTEXT *ctx, THREADID tid, SYSCALL_STANDARD std, VOID *v) { if(syscall_number == SYS_nanosleep) modifyNanosleepContext(ctx, std); }

// Code to handle other syscalls

void syscallExitRunModel(CONTEXT *ctx, THREADID tid, SYSCALL_STANDARD std, VOID *v) { if(syscall_number == SYS_nanosleep) restoreNanosleepContext(ctx, std); }

// Code to handle other syscalls

• Modify context at syscall entry

Handling syscall nanosleep pin/handle_syscall.cc void modifyNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std); void restoreNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std); void syscallEnterRunModel(CONTEXT *ctx, THREADID tid, SYSCALL_STANDARD std, VOID *v) { if(syscall_number == SYS_nanosleep) modifyNanosleepContext(ctx, std); }

// Code to handle other syscalls

void syscallExitRunModel(CONTEXT *ctx, THREADID tid, SYSCALL_STANDARD std, VOID *v) { if(syscall_number == SYS_nanosleep) restoreNanosleepContext(ctx, std); }

// Code to handle other syscalls

• Copy output and restore context at syscall exit

Modifying syscall context pin/handle_syscall.cc void modifyNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std) { Tile *tile = Sim()->getTileManager()->getCurrentTile(); SyscallMdl::syscall_args_t args = syscallArgs(ctx, std); struct timesepc *req = (struct timespec*) args.arg0; struct timesepc *rem = (struct timespec*) args.arg1; if(req){ struct timespec *req_arg = (struct timespec*) tile->getSyscallMdl()-> copyArgtoBuffer(0, (IntPtr)req, sizeof(struct timespec)); PIN_SetSyscallArgument(ctx, std, 0, (ADDRINT) req_arg); } if(rem){ struct timespec *rem_arg = (struct timespec*) tile->getSyscallMdl()->copyArgtoBuffer(1, (IntPtr)rem, sizeof(struct timespec)); PIN_SetSyscallArgument(ctx, std, 1, (ADDRINT) rem_arg); } }

• Modify memory arguments to point to buffers in host address space – Copy input arguments from simulated address space to buffers

Restoring syscall context pin/handle_syscall.cc void restoreNanosleepContext(CONTEXT *ctx, SYSCALL_STANDARD std) { Tile *tile = Sim()->getTileManager()->getCurrentTile(); SyscallMdl::syscall_args_t args; tile->getSyscallMdl()->retrieveSyscallArgs(args); struct timespec *req = (struct timespec*) args.arg0; struct timespec *rem = (struct timespec*) args.arg1; if(rem) { tile->getSyscallMdl()->copyArgFromBuffer(1, (IntPtr) rem, sizeof(struct timespec)); }

}

PIN_SetSyscallArgument(ctx, std, 0, (ADDRINT)req); PIN_SetSyscallArgument(ctx, std, 1, (ADDRINT)rem);

• Restore original context

– Copy output data to the simulated address space

Session Overview • Adding new configuration parameters • Supporting new system calls – Handling system calls locally – Handling system call remotely

System Calls File Management

open, access, read, write

sigprocmask, sigsuspend, sigaction

Signal Management

Memory Management

mmap, munmap, brk

gettimeofday, uname, getrlimit, nanosleep

Other syscalls

Synchronization/ Communication

kill, waitpid, futex

Handled at the MCP 23

Syscalls Handled Centrally Core

On Syscall Entry

… … mov eax, 1 int $0x80 … …

1) Arguments are copied from simulated memory into a local buffer 2) Syscall is changed to “NOP” (getpid)

Sent to MCP

MCP Syscall Executed On Syscall Exit

1) Syscall return value received from MCP 2) Arguments copied back to simulated memory

Mechanism - Syscalls Handled Centrally at the MCP 24

Why handle syscalls remotely? • open, read, write, close – Need to be handled centrally to maintain correct file modification semantics across processes

• brk, mmap, munmap – Maintain a single simulated address space

• futex, kill – Correct communication semantics across processes

• Centralized handling is done via the MCP

Syscall Handling Machinery

pin/handle_syscalls.h

• Pin front end

common/tile/ syscall_model.h

• Client back end (per tile)

common/system/ syscall_server.h

• Server back end (MCP)

Handling syscall read (front end) pin/handle_syscall.cc void syscallEnterRunModel(THREADID tid, CONTEXT *ctx, SYSCALL_STANDARD std, VOID *v) { Tile *tile = Sim()->getTileManager()->getCurrentTile(); Intptr syscall_number = PIN_GetSyscallNumber(ctx, std); if(syscall_number == SYS_read) { SyscallMdl::syscall_args_t args = syscallArgs(ctx, std); IntPtr new_syscall = tile->getSyscallMdl()->runEnter(syscall_number, args); PIN_SetSyscallNumber(ctx, std, new_syscall); } }

// Code to handle other syscalls

• Syscall entry callback in pin/handle_syscall.c simply calls into the syscall entry function in class SyscallMdl • Replace syscall read with NOP (syscall getpid)

Syscall Handling Machinery

pin/handle_syscalls.h

• Pin front end

common/tile/ syscall_model.h

• Client back end (per tile)

common/system/ syscall_server.h

• Server back end (MCP)

Handling syscall read (client) common/tile/syscall_model.h

common/tile/syscall_model.cc

class SyscallMdl { IntPtr m_syscall_number;

IntPtr SyscallMdl::runEnter(IntPtr syscall_num, syscall_args_t &args) { m_syscall_number = syscall_num; m_send_buff.clear(); m_recv_buff.clear();

UnstructuredBuffer m_send_buff; UnstructuredBuffer m_recv_buff;

if(syscall_num == SYS_read) { return marshallReadCall(args); }

IntPtr marshallReadCall(syscall_args_t args); }

// Other class members

}

// Code for other syscalls

• SyscallMdl defines a handler function for syscall read

Handling syscall read (client) common/tile/syscall_model.cc IntPtr SyscallMdl::marshallReadCall(syscall_args_t &args) { int fd = (int) args.arg0; void *buf = (void*) args.arg1; size_t count = (size_t) args.arg2; m_send_buff getMCPTileNum(), MCP_REQUEST_TYPE, m_send_buff.getBuffer(), m_send_buff.size()); NetPacket recv_pkt = m_network->netRecv(Config::getSingleton()->getMCPTileNum(), MCP_RESPONSE_TYPE); int num_bytes; m_recv_buff >> num_bytes; char *read_buff = new char[bytes]; m_recv_buff >> make_pair(read_buf, num_bytes); Core*core = Sim()->getTileManger()->getCurrentCore(); core->accessMemory(Core::NONE, Core::WRITE, (IntPtr) buf, read_buff, num_bytes); }

return num_bytes;

• Pack syscall parameters in a network packet

Handling syscall read (client) common/tile/syscall_model.cc IntPtr SyscallMdl::marshallReadCall(syscall_args_t &args) { int fd = (int) args.arg0; void *buf = (void*) args.arg1; size_t count = (size_t) args.arg2; m_send_buff getMCPTileNum(), MCP_REQUEST_TYPE, m_send_buff.getBuffer(), m_send_buff.size()); NetPacket recv_pkt = m_network->netRecv(Config::getSingleton()->getMCPTileNum(), MCP_RESPONSE_TYPE); int num_bytes; m_recv_buff >> num_bytes; char *read_buff = new char[bytes]; m_recv_buff >> make_pair(read_buf, num_bytes); Core*core = Sim()->getTileManger()->getCurrentCore(); core->accessMemory(Core::NONE, Core::WRITE, (IntPtr) buf, read_buff, num_bytes); }

return num_bytes;

• Send a request to MCP and wait for the response

Syscall Handling Machinery

pin/handle_syscalls.h

• Pin front end

common/tile/ syscall_model.h

• Client back end (per tile)

common/system/ syscall_server.h

• Server back end (MCP)

Handling syscall read (server) common/system/syscall_server.h

common/tile/syscall_model.cc

class SyscallServer { SyscallServer(); ~SyscallServer();

void SyscallServer::handleSyscall(core_id_t core_id) { IntPtr syscall_number; m_recv_buff >> syscall_number; if(syscall_num == SYS_read) { return marshallReadCall(args); }

void handleSyscall(core_id_t core_id); IntPtr marshallReadCall(syscall_args_t args); }

// Other class members }

// Code for other syscalls

• SyscallServer defines a handler function for syscall read

Handling syscall read (server) common/system/syscall_server.cc void SyscallServer::marshallReadCall(core_id_t core_id) { int fd; size_t count; char *read_buf = (char*) m_scratch; m_recv_buff >> fd >> count; int bytes = syscall(SYS_read, fd, (void*) read_buf, count); m_send_buff fd >> count; int bytes = syscall(SYS_read, fd, (void*) read_buf, count); m_send_buff getMCPTileNum(), MCP_RESPONSE_TYPE); int num_bytes; m_recv_buff >> num_bytes; char *read_buff = new char[bytes]; m_recv_buff >> make_pair(read_buf, num_bytes); Core *core = Sim()->getTileManger()->getCurrentCore(); core->accessMemory(Core::NONE, Core::WRITE, (IntPtr) buf, read_buff, num_bytes); }

return num_bytes;

• Receive results, update simulated memory if needed

Syscall Handling Machinery

pin/handle_syscalls.h

• Pin front end

common/tile/ syscall_model.h

• Client back end (per tile)

common/system/ syscall_server.h

• Server back end (MCP)

Session Overview • Adding new configuration parameters • Supporting new system calls – Handling system calls locally – Handling system call remotely