-1

Many registers like data registers contain values corresponding to the current process being executed. But, there are some registers which are common for all the processes

I want read access to some registers which are non process specific and can be accessed from 2 different processes and still be able to get the same value.

I need the code for the x86-64 architecture. (The 3 commands uname -m,-p,-i return x86_64, when typed on my desktop)

Thanks.

fuz
  • 88,405
  • 25
  • 200
  • 352
user1877095
  • 75
  • 1
  • 2
  • 9
  • OK, you need the user manual for your processor, the source code for your OS, an assembler and some luck. Note that this mechanism, even if it existed, is not typically how processes communicate. What would happen if three processes wished to comunicate with this mechanism? – Martin James Jul 24 '17 at 07:16
  • Can you define which registers are 'control registers' ? Because PC and SP definitely contain different values for different processes. – Maged Elghareib Jul 24 '17 at 07:42
  • This is usually done using system calls, so that the code will be portable between different processors. – Barmar Jul 24 '17 at 08:12
  • Please pick one of C and Python. I won't play the game “that's not the programming language I really wanted” with you. – fuz Jul 24 '17 at 08:45
  • @fuz picked 'C'. Actually, I am okay with C or python, but since I am asked to pick one, I chose C. – user1877095 Jul 24 '17 at 08:52
  • @MagedElghareib Removed the "control registers" part. I was assuming that control register values are independent of process being executed. – user1877095 Jul 24 '17 at 09:00
  • @user1877095 For what architecture would you like to read control registers? Every architecture has different control registers, so answers are going to differ. – fuz Jul 24 '17 at 09:17
  • 1
    I have changed “64 bit architecture” to “x86-64 architecture.” x86-64 is one of many 64 bit architectures, but from your post it is the most likely one. Good! Now I can prepare an answer. – fuz Jul 24 '17 at 09:32

1 Answers1

3

The x86-64 architecture has quite a few such control registers. Most of them cannot be read without elevated privileges, those that can are marked. You might want to read this article for a detailed description on the bits in each register.

On Linux, you can obtain the relevant elevated privileges using the iopl system call. iopl(3) gives you all privileges you need.

  • The flags register contains information about recent arithmetic operations as well as some configuration. It can be read with the pushf instruction without special permissions. Read this article for more details.
  • The segment registers cs, ds, es, ss, fs, and gs contain segment selectors. On modern operating systems, these are usually fixed for all processes and can be read using mov r16,segr without elevated privileges.
  • The cr0 register contains configuration pertaining memory protection. Its low 16 bits can be read by any process using the rmsw instruction, the remaining bits can be read with elevated privileges using mov r32,cr0 as can all other control registers.
  • The cr2 register contains the address of the last page fault.
  • The cr3 register contains the address of the page directory.
  • The cr4 register contains additional CPU configuration.
  • The cr8 register contains information about task priority

There are also a bunch of model-specific registers which can be read with the rmsr instructions.

To read these registers, use inline assembly. Here is inline assembly for all registers previously mentioned. For reading the rflags register, also look at this question for some caveats.

/* read rflags */
uint64_t rflags;
asm("pushf; popf %0" : "=rm"(rflags));

/* read segment register, replace sr with the segment you want */
uint16_t seg;
asm("mov %sr,%0" : "=rm"(seg));

/* read low bits of cr0 */
/* on some CPUs, only the low 16 bits are correct,
/* on others all 32 bit are correct */
uint32_t cr0;
asm("smsw %0" : "=r"(cr0));

/* everything below here requires elevated privileges */

/* read control register, replace cr with register name */
uint64_t cr;
asm("mov %cr,%0" : "=rm"(cr));

/* read model specific register. msr contains register number */
uint32_t msr_no = 0xC0000080, msr_hi, msr_lo;
asm("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(msr_no));
uint64_t msr_val = (uint64_)msr_hi << 32 | msr_lo;
fuz
  • 88,405
  • 25
  • 200
  • 352
  • Most OSes use `fs` or `gs` for thread-local storage, so whichever one they use has a per-thread value. Also, changing a segment register in one process won't affect other processes. Each process has its segment regs either saved/restored on context switches, or just set to what the OS thinks they should be. (You can actually do a long jump to a different `cs` value under Linux or Windows, to run 32-bit code in a process that started in 64-bit mode. But after an interrupt, the OS will probably return to your process in the mode it thinks it should be in, rather than saving/restoring CS) – Peter Cordes Jul 27 '17 at 04:40
  • @PeterCordes In typical usage, you never touch any segment registers and the operating system uses the same segments for all processes. To exchange the TLS segment, the operating system simply edits the ldt and reloads the segment selector. Or, on amd64, use that special instruction to reload the gs segment base. – fuz Jul 27 '17 at 09:20
  • Yeah, of course you don't usually mess with them. But since user-space *can* mess with them, it would be a security problem for the kernel to assume that it didn't. Thus, they have to be written on each user->kernel switch. Not necessarily on kernel->user, though, since it's true that all processes normally get the same values (except for CS, where 32-bit processes get a different selector). – Peter Cordes Jul 27 '17 at 10:18
  • I can't believe I started talking about segments in an SO question that wasn't one of those crappy 16-bit questions. :P I'm really glad that the amount you need to know about them these days to optimize user-space code is currently zero (except for TLS). – Peter Cordes Jul 27 '17 at 10:18