Although UML has a concept of architecture dependent and architecture independent pieces, some architecture dependent pieces are still found in generic files which need a clean segregation. The main work involves filling up the details for some files that are Sparc64 specific by looking at Intel i386 specific files. UML also contains a considerable amount of Intel assembly code in i386 specific files. This means it is very much essential for a person doing this port to learn Sparc assembly language to understand and fill up the corresponding files. This stage takes up a lot of time wherein the obscure, architecture specific code for ptrace, registers, sigcontext, etc needs to be clearly understood for the gaps to be correctly filled in.
arch/um/Makefile-sparc64. This file contains the definitions for:
START_ADDR - The address where the UML executable will load in memory. UML maps its executable, physical memory, and kernel virtual memory into the address space of each of its processes. This address must be chosen so that it won't conflict with any memory that a UML process is going to want to use. UML puts its own memory in the area starting at 0xa0000000 and process stacks 4M below its own process stack. To locate a likely area on Sparc64, looking at the output of /proc/$$/maps should be helpful.
ARCH_CFLAGS - This is used to turn off any definitions that would pull hardware-specific code into the kernel. For example, -U__$(SUBARCH)__, -U$(SUBARCH), etc.
ELF_SUBARCH - The name of the ELF (Executable and Linking Format) object format for the architecture.
ELF_SUBARCH = elf32-sparc
Ultrasparc is weird in the sense that even though the kernel and the kernel modules are 64-bit, userland is still 32-bit. Since all of User Mode Linux runs in userspace which can be debugged just like any other normal process, it is essential that UML be compiled and linked as 32-bit on Ultrasparc. This is the reason for ELF_SUBARCH being set to elf32-sparc instead of elf64-sparc.
Sparc64 needs to provide a set of headers located in include/asm-um. Uml mostly uses the headers of the underlying architecture by creating a symlink from include/asm-um/arch to include/asm-sparc64. Some of the architecture-dependent headers which need to be present in include/asm-um are:
archparam-sparc64.h - This header contains misellaneous sparc64-dependent definitions for elf.h which are sparc64-specific register initializations.
processor-sparc64.h - This header is used by UML/Sparc64 to choose between including sparc64-specific processor.h and UML-specific processor.h.
ptrace-sparc64.h - It defines Sparc64-dependent access macros into struct pt_regs which aren't used in generic code. But these macros may be needed if ELF_PLAT_INIT is defined.
sigcontext-sparc64.h - The purpose of this header is to define the occurrences of pt_regs in asm-sparc64/sigcontext.h out of way.
system-sparc64.h - This header defines empty_zero_page out of way.
Architecture headers: These are the headers that need to go in arch/um/include/sysdep-sparc64.
ptrace.h - It deals with the machine's register set and contains definitions for:
struct uml_pt_regs: It contains a system call number, a set of syscall arguments, a flag saying whether the kernel was entered from userspace or kernelspace and a pointer to the sigcontext structure on the current stack. This structure is architecture independent.
EMPTY_UML_PT_REGS: It is an initializer for uml_pt_regs which is architecture-independent too.
UPT_REG(regs, reg): It should return the value of the appropriate Sparc64 register from the saved sigcontext.
UPT_SET(regs, reg, val): It needs to set the value of appropriate Sparc64 register in the saved sigcontext to whatever value is passed in.
Few macros like UPT_SET_SYSCALL_RETURN, UPT_RESTART_SYSCALL, UPT_IP, UPT_SP, etc which will call the sigcontext macros since they need to modify the current sigcontext.
ptrace_user.h - It defines a set of macros into the host's pt_regs structure which should be implemented in terms of register definitions in the host < asm/ptrace.h> like PT_SYSCALL_NR, PT_SYSCALL_NR_OFFSET, PT_SYSCALL_ARG1_OFFSET, PT_IP, PT_IP_OFFSET, PT_SP, FRAME_SIZE, FRAME_SIZE_OFFSET, FP_FRAME_SIZE, etc.
sigcontext.h - It defines sigcontext related macros some of which are accessed through PT_REGS and UPT_REGS macros.
SC_RESTART_SYSCALL: It does some IP fiddling to cause the current system call to restart when userspace is re-entered. On Sparc64, this subtracts 4 from IP since a system call instruction is 4 bytes long.
SC_SET_SYSCALL_RETURN: Sets the system call return value.
SC_FAULT_ADDR, SC_FAULT_WRITE: These are called from generic UML code. On a segfault, they pick out a fault address from sigcontext and determine whether the fault was on a write.
void sc_to_regs(struct uml_pt_regs *regs, struct sigcontext *sc, unsigned long syscall): This is called at the beginning of a system call to fill in a pt_regs structure from the sigcontext. It parses the system call from the sigcontext and fills in the system call number and the arguments in pt_regs and is called from generic UML code.
Implementation files: The actual implementation of the Uml/Sparc64 port is contained in sys-sparc64 directory which defines the following files:
ptrace.c - int putreg(struct task_struct *child, unsigned long regno, unsigned long value) does any needed validity checking on the register value and assigns the value to the appropriate register in child->thread.process_regs.
unsigned long getreg(struct task_struct *child, unsigned long regno) fetches the value of the requested register from child->thread.process_regs, doing any required masking of registers which don't use all their bits
ptrace_user.c - This file contains definitions for ptrace_getregs and ptrace_setregs to hide the difference from generic code since Linux doesn't implement PTRACE_SETREGS and PTRACE_GETREGS on all architectures.
semaphore.c - Implements the architecture's semaphore primitives and is a symlink to the underlying Sparc64 semaphore.c.
sigcontext.c - It defines some sigcontext related functions:
int sc_size(void *data): It reflects the size of sigcontext and takes into account the floating point state as well as sigcontext structure itself.
int copy_sc_to_user(void *to_ptr, void *from_ptr, void *data): Copies a sigcontext from process stack and uses copy_to_user_proc.
int copy_sc_from_user(void *to_ptr, void *from_ptr, void *data): Copies a sigcontext from a process stack into kernel memory and must use copy_from_user_proc, not memcopy.
void sc_to_sc(void *to_ptr, void *from_ptr): It copies a sigcontext from one kernel stack to another. It is used during thread creation(kernel_thread(),fork(), or clone()) to initialize a kernel stack with a signal frame that a new process can return from.
Also sys-sparc64/util directory contains mk_sc.c which is used to generate system header sc.h. It generates sigcontext related macros based on < asm/ptrace.h>.