How to access the control registers cr0,cr2,cr3 from a program? Getting segmentation fault
Quoting from Intel® 64 and IA-32 Architectures Software Developer Manuals 3-650 Vol. 2A on moving to and from control registers:
This instruction can be executed only when the current privilege level is 0.
Which means the instruction can only be executed in kernel mode.
A minimal kernel module, that logs the contents of cr0, cr2 and cr3 could look something like this (32-bit code path untested):
/* hello.c */
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
#ifdef __x86_64__
u64 cr0, cr2, cr3;
__asm__ __volatile__ (
"mov %%cr0, %%rax\n\t"
"mov %%eax, %0\n\t"
"mov %%cr2, %%rax\n\t"
"mov %%eax, %1\n\t"
"mov %%cr3, %%rax\n\t"
"mov %%eax, %2\n\t"
: "=m" (cr0), "=m" (cr2), "=m" (cr3)
: /* no input */
: "%rax"
);
#elif defined(__i386__)
u32 cr0, cr2, cr3;
__asm__ __volatile__ (
"mov %%cr0, %%eax\n\t"
"mov %%eax, %0\n\t"
"mov %%cr2, %%eax\n\t"
"mov %%eax, %1\n\t"
"mov %%cr3, %%eax\n\t"
"mov %%eax, %2\n\t"
: "=m" (cr0), "=m" (cr2), "=m" (cr3)
: /* no input */
: "%eax"
);
#endif
printk(KERN_INFO "cr0 = 0x%8.8X\n", cr0);
printk(KERN_INFO "cr2 = 0x%8.8X\n", cr2);
printk(KERN_INFO "cr3 = 0x%8.8X\n", cr3);
return 0;
}
void cleanup_module(void)
{
}
# Makefile
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
test: all
sudo insmod ./hello.ko
sudo rmmod hello
dmesg | tail
Related videos on Youtube
Chris
Updated on June 13, 2020Comments
-
Chris about 4 years
I have written a program which tries to read from and write to the control registers.
The program compiles fine, but when the inline assembly is about to be executed, it produces a segmentation fault.
Code:
void instructions(int val) { int i; int value; for(i = 0; i < val; i++) __asm__("mov %cr0, %eax"); }
I used GDB and stepped through each assembly line and it is on the
mov %cr0,%eax
that the segmentation fault is occurring.Anyone who knows what is wrong?
-
Ciro Santilli OurBigBook.com@DavidWohlferd I do. Maybe some day he will come back. I'm not waiting for him to answer. Questions on SO are useful forever. I often answer those, and some times got rep. :-)
-
David Wohlferd@CiroSantilli六四事件法轮功纳米比亚威视 You do realize this question is 4 years old? Chris hasn't been seen since 2011.
-
-
corny about 7 yearsDid you mean
u64
? At leastcr3
is documented in the intel manuals for intel 64 from bits 0 : 63. -
user786653 about 7 years@corny: It was just a quick example to show how to access the control registers, so for simplicity I only print the lower 32-bits even in 64-bit mode. I think all the control registers are 64-bit in long mode and you definitely want all bits of CR2/CR3 if you're actually doing something useful with the contents.
-
corny about 7 yearsCorrect, in 64 bit mode, all control registers are 64 bit. Section 2.5, “CONTROL REGISTERS” in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A. I edited your answer, let's delete our comment and let's just preserve your improved answer.
-
user786653 about 7 yearsI don't currently have a way to easily check the code, but I think the format string should to be
%016lx
in 64-bit mode (or perhaps%p
can be used if cr0/cr2/cr3 are cast tovoid*
) -
Phidelux over 3 yearsAs it is a 64-bit register it should be %016llx (additional long).
-
Shuzheng about 3 years@user786653 - Will you show how to write to
cr0
? I can read, but get segmentation fault when writing to it.