diff --git a/zircon/kernel/arch/x86/BUILD.gn b/zircon/kernel/arch/x86/BUILD.gn index 5378932bb28235cca63e3d8266cbd44b814141c4..855a184a0c44df2df3f638b6c1b2b64cbd8411f9 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 4b6f554953102541b150d537733cf525a8069984..2bb61c0ae0c70eebfcbccd996cc2e5c8aebcd3c4 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 0000000000000000000000000000000000000000..1ef338a2734db6024c7698e4e8c30f3240f4d1bd --- /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; +}