title: Modifying control register in kernel module
body: <p>The following simple kernel module sets the 13th bit of the cr4 register (<code>CR4.VMXE</code>) once it is loaded and clears the bit on exit.</p>
  
  <h1>vmx.c</h1>
  
  <pre><code>#include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  
  MODULE_LICENSE("GPL");
  
  static inline uint64_t getcr4(void) {
      register uint64_t ret = 0;
  
      asm volatile (
          "movq %%cr4, %0\n"
          :"=r"(ret)
      );
  
      return ret;
  }
  
  static inline void setcr4(register uint64_t val) {
      asm volatile (
          "movq %0, %%cr4\n"
          :
          :"r"(val)
      );
  }
  
  static int __init init_routine(void) {
      uint64_t cr4 = getcr4();
  
      printk(KERN_INFO "VTX Test loaded: %llu (%u).\n", cr4, (unsigned char)((cr4 &gt;&gt; 13) &amp; 1));
      cr4 |= (1 &lt;&lt; 13);
      setcr4(cr4);
      cr4 = getcr4();
      printk(KERN_INFO "cr4: %llu (%u).\n", cr4, (unsigned char)((cr4 &gt;&gt; 13) &amp; 1));
  
      return 0;
  }
  
  static void __exit exit_routine(void) {
      uint64_t cr4 = getcr4();
  
      printk(KERN_INFO "cr4: %llu (%u).\n", cr4, (unsigned char)((cr4 &gt;&gt; 13) &amp; 1));
      cr4 &amp;= ~(1 &lt;&lt; 13);
      setcr4(cr4);
      cr4 = getcr4();
      printk(KERN_INFO "VTX Test exited: %llu (%u).\n", cr4, (unsigned char)((cr4 &gt;&gt; 13) &amp; 1));
  }
  
  module_init(init_routine);
  module_exit(exit_routine);
  </code></pre>
  
  <h1>Makefile</h1>
  
  <pre><code>obj-m += vmx.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
  </code></pre>
  
  <p>To run the module I use <code>make clean &amp;&amp; make &amp;&amp; sudo insmod vmx.ko &amp;&amp; sudo rmmod vmx &amp;&amp; sudo dmesg -c</code>. This sometimes gives me the following (expected) output</p>
  
  <pre><code>[ 2295.121537] VTX Test loaded: 1312736 (0).
  [ 2295.121540] cr4: 1320928 (1).
  [ 2295.123975] cr4: 1320928 (1).
  [ 2295.123977] VTX Test exited: 1312736 (0).
  </code></pre>
  
  <p>And sometimes also the following:</p>
  
  <pre><code>[ 2296.256982] VTX Test loaded: 1320928 (1).
  [ 2296.256984] cr4: 1320928 (1).
  [ 2296.259481] cr4: 1312736 (0).
  [ 2296.259483] VTX Test exited: 1312736 (0).
  </code></pre>
  
  <p>The second and third line in the secound output seem strange to me, because it seems like the modified control register cr4 has been reset after leaving <code>init_routine</code>. Additionally it is strange that in the first line the VMXE bit seems to be set, which doesn't really make any sense. Is this behavior normal? How can it be explained? Could there be another kernel module running which modifies CR4? This seems rather strange because I've seen several VTX implementations and they all set the VMXE bit in their initialization routine and clear the bit in their exit routine in the same fashion as in this module.</p>