The example is to implement the handler for the task call that will use virtual_copy to copy a large struct from kernel memory to a user process's memory.
We have to specify a struct vir_addr to describe the virtual address of the kernel's source data and another struct vir_addr to describe the virtual address of the destination user's variable to receive the copy.
struct vir_addr { int proc_nr_e; int segment; vir_bytes offset; }; proc_nr_e: endpoint value of the process segment: This should be T, D, or S (0,1, or 2) T for Text, D for Data, S for Stack offset: Byte offset from the beginning of the segment.
From the discussion above, for copying data, you can set the segment to be D or S and specify the byte offset as the address of the data item (using C expression to calculate this address). This should work if the data is either in the data segment or the stack segment. The umap_local function will change the segment if it is not the correct one before calculating the physical address.