From bdd2d1c29798384a8ea08ae98f94d2b177497ac6 Mon Sep 17 00:00:00 2001 From: Venkatesh Srinivas <venkateshs@google.com> Date: Sat, 27 Apr 2019 17:24:18 +0000 Subject: [PATCH] [kernel][x86] Introduce read_msr_on_cpu read_msr_on_cpu reads an MSR on a single target CPU. The MSR needs to be readable without causing a #GP; the read happens in IPI function handler. ZX-3359 Tested: See 4th patch in patch stack; k cpu rdmsr/wrmsr are added to exercise these. Change-Id: I42e6162ba8c2f19872b4d058532b454367e19879 --- zircon/kernel/arch/x86/BUILD.gn | 1 + zircon/kernel/arch/x86/include/arch/x86.h | 4 ++ zircon/kernel/arch/x86/msr.cpp | 55 +++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 zircon/kernel/arch/x86/msr.cpp diff --git a/zircon/kernel/arch/x86/BUILD.gn b/zircon/kernel/arch/x86/BUILD.gn index 5378932bb28..855a184a0c4 100644 --- a/zircon/kernel/arch/x86/BUILD.gn +++ b/zircon/kernel/arch/x86/BUILD.gn @@ -91,6 +91,7 @@ library("x86") { "mmu.cpp", "mmu_mem_types.cpp", "mp.cpp", + "msr.cpp", "ops.S", "perf_mon.cpp", "proc_trace.cpp", diff --git a/zircon/kernel/arch/x86/include/arch/x86.h b/zircon/kernel/arch/x86/include/arch/x86.h index 4b6f5549531..2bb61c0ae0c 100644 --- a/zircon/kernel/arch/x86/include/arch/x86.h +++ b/zircon/kernel/arch/x86/include/arch/x86.h @@ -10,6 +10,7 @@ #pragma once #include <cpuid.h> +#include <kernel/cpu.h> #include <stdbool.h> #include <stdlib.h> #include <sys/types.h> @@ -326,6 +327,9 @@ static inline uint32_t read_msr32(uint32_t msr_id) { zx_status_t read_msr_safe(uint32_t msr_id, uint64_t* val); +// Read msr |msr_id| on CPU |cpu| and return the 64-bit value. +uint64_t read_msr_on_cpu(cpu_num_t cpu, uint32_t msr_id); + static inline void write_msr(uint32_t msr_id, uint64_t msr_write_val) { __asm__ __volatile__( "wrmsr \n\t" diff --git a/zircon/kernel/arch/x86/msr.cpp b/zircon/kernel/arch/x86/msr.cpp new file mode 100644 index 00000000000..1ef338a2734 --- /dev/null +++ b/zircon/kernel/arch/x86/msr.cpp @@ -0,0 +1,55 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#include <assert.h> +#include <debug.h> +#include <err.h> +#include <stdio.h> +#include <string.h> +#include <trace.h> +#include <zircon/compiler.h> + +#include <arch/mp.h> +#include <arch/ops.h> +#include <arch/x86.h> +#include <arch/x86/apic.h> +#include <arch/x86/descriptor.h> +#include <arch/x86/feature.h> +#include <arch/x86/interrupts.h> +#include <arch/x86/mp.h> +#include <arch/x86/tsc.h> +#include <dev/hw_rng.h> +#include <dev/interrupt.h> +#include <kernel/event.h> +#include <kernel/timer.h> +#include <platform.h> +#include <zircon/types.h> + + +struct read_msr_context { + uint32_t msr; + uint64_t val; +}; + +static void read_msr_on_cpu_task(void* raw_context) { + auto* const context = reinterpret_cast<struct read_msr_context*>(raw_context); + context->val = read_msr(context->msr); +} + +uint64_t read_msr_on_cpu(cpu_num_t cpu, uint32_t msr_id) { + struct read_msr_context context = {}; + cpu_mask_t mask = {}; + + if (!mp_is_cpu_online(cpu)) { + return -1; + } + + context.msr = msr_id; + mask |= cpu_num_to_mask(cpu); + mp_sync_exec(MP_IPI_TARGET_MASK, mask, read_msr_on_cpu_task, + reinterpret_cast<void*>(&context)); + return context.val; +} -- GitLab