How to introduce an MSR in gem5 and integrate it with Linux kernel? - linux-kernel

I am trying to evaluate performance of custom prefetching models for Intel x86 architecture for which I would like to set and read some MSR registers. We are using Gem5 and Linux 5.4.84 kernel on a TimingSimpleCPU.
I have introduced the registers at some unused address in these files:
https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/src/arch/x86/regs/msr.cc
https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/src/arch/x86/regs/misc.hh
say MY_CUSTOM_REGISTER at 0xc0010118
I have also defined these addresses in :
https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/msr-index.h
https://github.com/torvalds/linux/blob/master/tools/testing/selftests/kvm/include/x86_64/processor.h
as I felt that somehow we need to add definitions in the kernel too.
However, after building gem5.opt binary and kernel, I am not able to access these registers with msr-tools. I get a segmentation fault while trying to get/set any values:
sudo rdmsr 0xc0010118
Can someone point out somewhere else I need to add something?

Related

Are ARM cortex-R watchpoints accessible via CP14 interface

On an ARM v7 Cortex-R4 chip, is there any way to access DBGWCR and DBGWVR using the mrc instruction, the mcr instruction and the CP14 interface? I cannot find this in the documentation.
This table lists the six CP14 accessible registers. They are enough to locate the memory mapped interface to the remaining debug registers, DBGDSAR and DBGDRAR being the key ones.
The memory mapped interface ought to be accessible from the core in any implementation, but there are no hard guarantees.

Manually exposing a CPU Flag to Guest VM for testing purposes

I have an Ubuntu (trying this on either 14.04 or 16.04) KVM host with an Intel E5-26xx v3 processor.
There is a certain flag that I need to have exposed to the guest VM, but QEMU/libvirt is not exposing that, even if I use the cpu mode='host-passthrough' in my VM libvirt XML definition. I believe this is due to what is defined in this file /usr/share/libvirt/cpu_map.xml in which the flag that I like to get exposed is not defined.
So, I'd like to be able to modify cpu_map.xml and manually add the CPU flag definition, but I'm not positive on how/where I can get the results of the CPUID function and whether they're in ebx/ecx etc. Any pointer is appreciated.
Disclaimer: I haven't meddled into CPU architecture, so my knowledge is very limited in this area.
Retrieving the results from the CPUID instruction is quite simple:
Check if the ID flag (bit 21) in the EFLAGS register is set, which indicates the availability of the CPUID instruction
Set the EAX and ECX registers to certain values
Call CPUID
Interpret the values of the EAX, EBX, ECX, and EDX registers
There are many sites convering the interpretation of the results. One of them is LowLevel. Many of them only cover a subset of possible results.
A thread on the specifics of CPUID in VMs extends this basic knowledge to:
UserCPUID is what will be visible to the guest Ring-3 code running natively when using binary translation. With binary translation, typically only Ring-0 (or IOPL-3) code is subject to binary translation. Most Ring-3 code runs natively (in a mode we refer to as "direct execution.")
Prior to the introduction of CPUID faulting, there was no way to intercept guest execution of the CPUID instruction when the guest was running under direct execution. Some CPUs support a limited ability to override the results of some CPUID leaves (on a register by register basis) even without intercepting the CPUID instruction. Hence, userCPUID is based on hostCPUID, but the registers that can be overridden have guestCPUID values.
The host-passthrough model will aim to expose every host CPU feature to the guest, but there are some exceptions to this rule. If the CPU feature is very new, then QEMU, KVM and libvirt may not be aware of its existence. KVM is conservative by default and so will not expose any feature it doesn't know about. In this case, merely editting cpu_map.xml is not going to help as that only tells libvirt about it - you'd still need QEMU & KVM to know about it which requires code changes. The second case is that some CPU features are not safe to expose to the guest, and so KVM will explicitly block them.
You can see what libvirt believes the host to have by using 'virsh capabilities'

Call an instruction on a specific core in kernel

I know that I can call a function on a selected set of cores in Linux kernel by using smp_call_function_single() [1].
What if I only want to execute an instruction, say rdmsr, on a specific core?
I know that I can wrap it as a function, but I think it is too expensive since I only execute one instruction.
Does anyone know if it is possible to call an instruction on a specific core in Linux kernel or Xen kernel?
Thank you very much for your help!
[1] http://lxr.free-electrons.com/source/kernel/smp.c#L271.

Can I dump/modify the content of x86 CPU cache/TLB

any apps or the system kernel can access or even modify the content of CPU cahce and/or TLB?
I found a short description about the CPU cache from this webiste:
"No programming language has direct access to CPU cache. Reading and writing the cache is something done automatically by the hardware; there's NO way to write instructions which treat the cache as any kind of separate entity. Reads and writes to the cache happen as side-effect to all instructions that touch memory."
From this message, it seems there is no way to read/write the content of CPU cahce/TLB.
However, I also got another information that conflicts with the above one. That information implies that a debug tool may be able to dump/show the content of CPU cache.
Currently I'm confused. so please help me.
I got some answers from another post: dump the contents of TLB buffer of x86 CPU. Thanks adamdunson.
People could read this document about test registers, but it is only available on very old x86 machines test registers
Another descriptions from wiki https://en.wikipedia.org/wiki/Test_register:
A test register, in the Intel 80486 processor, was a register used by
the processor, usually to do a self-test. Most of these registers were
undocumented, and used by specialized software. The test registers
were named TR3 to TR7. Regular programs don't usually require these
registers to work. With the Pentium, the test registers were replaced
by a variety of model-specific registers (MSRs).
Two test registers, TR6 and TR7, were provided for the purpose of
testing. TR6 was the test command register, and TR7 was the test data
register. These registers were accessed by variants of the MOV
instruction. A test register may either be the source operand or the
destination operand. The MOV instructions are defined in both
real-address mode and protected mode. The test registers are
privileged resources. In protected mode, the MOV instructions that
access them can only be executed at privilege level 0. An attempt to
read or write the test registers when executing at any other privilege
level causes a general protection exception. Also, those instructions
generate invalid opcode exception on any CPU newer than 80486.
In fact, I'm still expecting some similar functions on Intel i7 or i5. Unfortunately, I do not find any related document about that. If anyone has such information, please let me know.

Somewhat newb question about assy and the heap

Ultimately I am just trying to figure out how to dynamically allocate heap memory from within assembly.
If I call Linux sbrk() from assembly code, can I use the address returned as I would use an address of a statically (ie in the .data section of my program listing) declared chunk of memory?
I know Linux uses the hardware MMU if present, so I am not sure if what sbrk returns is a 'raw' pointer to real RAM, or is it a cooked pointer to RAM that may be modified by Linux's VM system?
I read this: How are sbrk/brk implemented in Linux?. I suspect I can not use the return value from sbrk() without worry: the MMU fault on access-non-allocated-address must cause the VM to alter the real location in RAM being addressed. Thus assy, not linked against libc or what-have-you, would not know the address has changed.
Does this make sense, or am I out to lunch?
Unix user processes live in virtual memory, no matter if written in assembler of Fortran, and should not care about physical addresses. That's kernel's business - kernel sets up and manages the MMU. You don't have to worry about it. Page faults are handled automatically and transparently.
sbrk(2) returns a virtual address specific to the process, if that's what you were asking.

Resources