mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 19:41:16 +00:00
vircpuhost: Add support for reading MSRs
The new virHostCPUGetMSR internal API will try to read the MSR from /dev/cpu/0/msr and if it is not possible (the device does not exist or libvirt is running unprivileged), it will fallback to asking KVM for the MSR using KVM_GET_MSRS ioctl. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
1c0ff5df07
commit
df4b46737f
@ -2027,6 +2027,7 @@ virHostCPUGetInfo;
|
||||
virHostCPUGetKVMMaxVCPUs;
|
||||
virHostCPUGetMap;
|
||||
virHostCPUGetMicrocodeVersion;
|
||||
virHostCPUGetMSR;
|
||||
virHostCPUGetOnline;
|
||||
virHostCPUGetOnlineBitmap;
|
||||
virHostCPUGetPresentBitmap;
|
||||
|
@ -58,6 +58,7 @@
|
||||
VIR_LOG_INIT("util.hostcpu");
|
||||
|
||||
#define KVM_DEVICE "/dev/kvm"
|
||||
#define MSR_DEVICE "/dev/cpu/0/msr"
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
@ -1254,3 +1255,82 @@ virHostCPUGetMicrocodeVersion(void)
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
|
||||
#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS)
|
||||
static int
|
||||
virHostCPUGetMSRFromKVM(unsigned long index,
|
||||
uint64_t *result)
|
||||
{
|
||||
VIR_AUTOCLOSE fd = -1;
|
||||
struct {
|
||||
struct kvm_msrs header;
|
||||
struct kvm_msr_entry entry;
|
||||
} msr = {
|
||||
.header = { .nmsrs = 1 },
|
||||
.entry = { .index = index },
|
||||
};
|
||||
|
||||
if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
|
||||
virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
|
||||
VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*result = msr.entry.data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED,
|
||||
uint64_t *result ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s",
|
||||
_("Reading MSRs via KVM is not supported on this platform"));
|
||||
return -1;
|
||||
}
|
||||
#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */
|
||||
|
||||
|
||||
/*
|
||||
* Returns 0 on success,
|
||||
* 1 when the MSR is not supported by the host CPU,
|
||||
* -1 on error.
|
||||
*/
|
||||
int
|
||||
virHostCPUGetMSR(unsigned long index,
|
||||
uint64_t *msr)
|
||||
{
|
||||
VIR_AUTOCLOSE fd = -1;
|
||||
char ebuf[1024];
|
||||
|
||||
*msr = 0;
|
||||
|
||||
if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) {
|
||||
VIR_DEBUG("Unable to open %s: %s",
|
||||
MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
|
||||
} else {
|
||||
int rc = pread(fd, msr, sizeof(*msr), index);
|
||||
|
||||
if (rc == sizeof(*msr))
|
||||
return 0;
|
||||
|
||||
if (rc < 0 && errno == EIO) {
|
||||
VIR_DEBUG("CPU does not support MSR 0x%lx", index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s",
|
||||
index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
|
||||
}
|
||||
|
||||
VIR_DEBUG("Falling back to KVM ioctl");
|
||||
|
||||
return virHostCPUGetMSRFromKVM(index, msr);
|
||||
}
|
||||
|
@ -66,4 +66,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online);
|
||||
|
||||
unsigned int virHostCPUGetMicrocodeVersion(void);
|
||||
|
||||
int virHostCPUGetMSR(unsigned long index,
|
||||
uint64_t *msr);
|
||||
|
||||
#endif /* LIBVIRT_VIRHOSTCPU_H */
|
||||
|
Loading…
Reference in New Issue
Block a user