Merge bc1bb2a49b ("Merge tag 'x86_sev_for_v6.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline

Steps on the way to 6.4-rc1

Change-Id: If25ed7f241bcf4948a962c335a526dda96b85002
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2023-05-16 11:36:09 +00:00
57 changed files with 994 additions and 960 deletions
+13 -7
View File
@@ -37,11 +37,11 @@ along with a description:
the return value. General error numbers (-ENOMEM, -EINVAL)
are not detailed, but errors with specific meanings are.
The guest ioctl should be issued on a file descriptor of the /dev/sev-guest device.
The ioctl accepts struct snp_user_guest_request. The input and output structure is
specified through the req_data and resp_data field respectively. If the ioctl fails
to execute due to a firmware error, then fw_err code will be set otherwise the
fw_err will be set to 0x00000000000000ff.
The guest ioctl should be issued on a file descriptor of the /dev/sev-guest
device. The ioctl accepts struct snp_user_guest_request. The input and
output structure is specified through the req_data and resp_data field
respectively. If the ioctl fails to execute due to a firmware error, then
the fw_error code will be set, otherwise fw_error will be set to -1.
The firmware checks that the message sequence counter is one greater than
the guests message sequence counter. If guest driver fails to increment message
@@ -57,8 +57,14 @@ counter (e.g. counter overflow), then -EIO will be returned.
__u64 req_data;
__u64 resp_data;
/* firmware error code on failure (see psp-sev.h) */
__u64 fw_err;
/* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */
union {
__u64 exitinfo2;
struct {
__u32 fw_error;
__u32 vmm_error;
};
};
};
2.1 SNP_GET_REPORT
+11
View File
@@ -22670,6 +22670,17 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/asm
F: arch/x86/entry/
X86 HARDWARE VULNERABILITIES
M: Thomas Gleixner <tglx@linutronix.de>
M: Borislav Petkov <bp@alien8.de>
M: Peter Zijlstra <peterz@infradead.org>
M: Josh Poimboeuf <jpoimboe@kernel.org>
R: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
S: Maintained
F: Documentation/admin-guide/hw-vuln/
F: arch/x86/include/asm/nospec-branch.h
F: arch/x86/kernel/cpu/bugs.c
X86 MCE INFRASTRUCTURE
M: Tony Luck <tony.luck@intel.com>
M: Borislav Petkov <bp@alien8.de>
+30 -10
View File
@@ -29,6 +29,22 @@ static bool intel_cc_platform_has(enum cc_attr attr)
}
}
/*
* Handle the SEV-SNP vTOM case where sme_me_mask is zero, and
* the other levels of SME/SEV functionality, including C-bit
* based SEV-SNP, are not enabled.
*/
static __maybe_unused bool amd_cc_platform_vtom(enum cc_attr attr)
{
switch (attr) {
case CC_ATTR_GUEST_MEM_ENCRYPT:
case CC_ATTR_MEM_ENCRYPT:
return true;
default:
return false;
}
}
/*
* SME and SEV are very similar but they are not the same, so there are
* times that the kernel will need to distinguish between SME and SEV. The
@@ -41,9 +57,14 @@ static bool intel_cc_platform_has(enum cc_attr attr)
* up under SME the trampoline area cannot be encrypted, whereas under SEV
* the trampoline area must be encrypted.
*/
static bool amd_cc_platform_has(enum cc_attr attr)
{
#ifdef CONFIG_AMD_MEM_ENCRYPT
if (sev_status & MSR_AMD64_SNP_VTOM)
return amd_cc_platform_vtom(attr);
switch (attr) {
case CC_ATTR_MEM_ENCRYPT:
return sme_me_mask;
@@ -76,11 +97,6 @@ static bool amd_cc_platform_has(enum cc_attr attr)
#endif
}
static bool hyperv_cc_platform_has(enum cc_attr attr)
{
return attr == CC_ATTR_GUEST_MEM_ENCRYPT;
}
bool cc_platform_has(enum cc_attr attr)
{
switch (vendor) {
@@ -88,8 +104,6 @@ bool cc_platform_has(enum cc_attr attr)
return amd_cc_platform_has(attr);
case CC_VENDOR_INTEL:
return intel_cc_platform_has(attr);
case CC_VENDOR_HYPERV:
return hyperv_cc_platform_has(attr);
default:
return false;
}
@@ -103,11 +117,14 @@ u64 cc_mkenc(u64 val)
* encryption status of the page.
*
* - for AMD, bit *set* means the page is encrypted
* - for Intel *clear* means encrypted.
* - for AMD with vTOM and for Intel, *clear* means encrypted
*/
switch (vendor) {
case CC_VENDOR_AMD:
return val | cc_mask;
if (sev_status & MSR_AMD64_SNP_VTOM)
return val & ~cc_mask;
else
return val | cc_mask;
case CC_VENDOR_INTEL:
return val & ~cc_mask;
default:
@@ -120,7 +137,10 @@ u64 cc_mkdec(u64 val)
/* See comment in cc_mkenc() */
switch (vendor) {
case CC_VENDOR_AMD:
return val & ~cc_mask;
if (sev_status & MSR_AMD64_SNP_VTOM)
return val | cc_mask;
else
return val & ~cc_mask;
case CC_VENDOR_INTEL:
return val | cc_mask;
default:
-11
View File
@@ -29,7 +29,6 @@
#include <linux/syscore_ops.h>
#include <clocksource/hyperv_timer.h>
#include <linux/highmem.h>
#include <linux/swiotlb.h>
int hyperv_init_cpuhp;
u64 hv_current_partition_id = ~0ull;
@@ -504,16 +503,6 @@ void __init hyperv_init(void)
/* Query the VMs extended capability once, so that it can be cached. */
hv_query_ext_cap(0);
#ifdef CONFIG_SWIOTLB
/*
* Swiotlb bounce buffer needs to be mapped in extra address
* space. Map function doesn't work in the early place and so
* call swiotlb_update_mem_attributes() here.
*/
if (hv_is_isolation_supported())
swiotlb_update_mem_attributes();
#endif
return;
clean_guest_os_id:
+96 -46
View File
@@ -13,6 +13,8 @@
#include <asm/svm.h>
#include <asm/sev.h>
#include <asm/io.h>
#include <asm/coco.h>
#include <asm/mem_encrypt.h>
#include <asm/mshyperv.h>
#include <asm/hypervisor.h>
@@ -233,41 +235,6 @@ void hv_ghcb_msr_read(u64 msr, u64 *value)
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
#endif
enum hv_isolation_type hv_get_isolation_type(void)
{
if (!(ms_hyperv.priv_high & HV_ISOLATION))
return HV_ISOLATION_TYPE_NONE;
return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
}
EXPORT_SYMBOL_GPL(hv_get_isolation_type);
/*
* hv_is_isolation_supported - Check system runs in the Hyper-V
* isolation VM.
*/
bool hv_is_isolation_supported(void)
{
if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
return false;
if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
return false;
return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
}
DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
/*
* hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
* isolation VM.
*/
bool hv_isolation_type_snp(void)
{
return static_branch_unlikely(&isolation_type_snp);
}
/*
* hv_mark_gpa_visibility - Set pages visible to host via hvcall.
@@ -320,27 +287,25 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
}
/*
* hv_set_mem_host_visibility - Set specified memory visible to host.
* hv_vtom_set_host_visibility - Set specified memory visible to host.
*
* In Isolation VM, all guest memory is encrypted from host and guest
* needs to set memory visible to host via hvcall before sharing memory
* with host. This function works as wrap of hv_mark_gpa_visibility()
* with memory base and size.
*/
int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visible)
static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc)
{
enum hv_mem_host_visibility visibility = visible ?
VMBUS_PAGE_VISIBLE_READ_WRITE : VMBUS_PAGE_NOT_VISIBLE;
enum hv_mem_host_visibility visibility = enc ?
VMBUS_PAGE_NOT_VISIBLE : VMBUS_PAGE_VISIBLE_READ_WRITE;
u64 *pfn_array;
int ret = 0;
bool result = true;
int i, pfn;
if (!hv_is_isolation_supported() || !hv_hypercall_pg)
return 0;
pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
if (!pfn_array)
return -ENOMEM;
return false;
for (i = 0, pfn = 0; i < pagecount; i++) {
pfn_array[pfn] = virt_to_hvpfn((void *)kbuffer + i * HV_HYP_PAGE_SIZE);
@@ -349,17 +314,68 @@ int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visibl
if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) {
ret = hv_mark_gpa_visibility(pfn, pfn_array,
visibility);
if (ret)
if (ret) {
result = false;
goto err_free_pfn_array;
}
pfn = 0;
}
}
err_free_pfn_array:
kfree(pfn_array);
return ret;
return result;
}
static bool hv_vtom_tlb_flush_required(bool private)
{
return true;
}
static bool hv_vtom_cache_flush_required(void)
{
return false;
}
static bool hv_is_private_mmio(u64 addr)
{
/*
* Hyper-V always provides a single IO-APIC in a guest VM.
* When a paravisor is used, it is emulated by the paravisor
* in the guest context and must be mapped private.
*/
if (addr >= HV_IOAPIC_BASE_ADDRESS &&
addr < (HV_IOAPIC_BASE_ADDRESS + PAGE_SIZE))
return true;
/* Same with a vTPM */
if (addr >= VTPM_BASE_ADDRESS &&
addr < (VTPM_BASE_ADDRESS + PAGE_SIZE))
return true;
return false;
}
void __init hv_vtom_init(void)
{
/*
* By design, a VM using vTOM doesn't see the SEV setting,
* so SEV initialization is bypassed and sev_status isn't set.
* Set it here to indicate a vTOM VM.
*/
sev_status = MSR_AMD64_SNP_VTOM;
cc_set_vendor(CC_VENDOR_AMD);
cc_set_mask(ms_hyperv.shared_gpa_boundary);
physical_mask &= ms_hyperv.shared_gpa_boundary - 1;
x86_platform.hyper.is_private_mmio = hv_is_private_mmio;
x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required;
x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility;
}
#endif /* CONFIG_AMD_MEM_ENCRYPT */
/*
* hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM.
*/
@@ -377,7 +393,7 @@ void *hv_map_memory(void *addr, unsigned long size)
pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) +
(ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT);
vaddr = vmap_pfn(pfns, size / PAGE_SIZE, PAGE_KERNEL_IO);
vaddr = vmap_pfn(pfns, size / PAGE_SIZE, pgprot_decrypted(PAGE_KERNEL));
kfree(pfns);
return vaddr;
@@ -387,3 +403,37 @@ void hv_unmap_memory(void *addr)
{
vunmap(addr);
}
enum hv_isolation_type hv_get_isolation_type(void)
{
if (!(ms_hyperv.priv_high & HV_ISOLATION))
return HV_ISOLATION_TYPE_NONE;
return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
}
EXPORT_SYMBOL_GPL(hv_get_isolation_type);
/*
* hv_is_isolation_supported - Check system runs in the Hyper-V
* isolation VM.
*/
bool hv_is_isolation_supported(void)
{
if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
return false;
if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
return false;
return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
}
DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
/*
* hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
* isolation VM.
*/
bool hv_isolation_type_snp(void)
{
return static_branch_unlikely(&isolation_type_snp);
}
-1
View File
@@ -7,7 +7,6 @@
enum cc_vendor {
CC_VENDOR_NONE,
CC_VENDOR_AMD,
CC_VENDOR_HYPERV,
CC_VENDOR_INTEL,
};
+1
View File
@@ -56,6 +56,7 @@ void __init sev_es_init_vc_handling(void);
#else /* !CONFIG_AMD_MEM_ENCRYPT */
#define sme_me_mask 0ULL
#define sev_status 0ULL
static inline void __init sme_early_encrypt(resource_size_t paddr,
unsigned long size) { }
+2 -9
View File
@@ -16,13 +16,6 @@
extern atomic64_t last_mm_ctx_id;
#ifndef CONFIG_PARAVIRT_XXL
static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
}
#endif /* !CONFIG_PARAVIRT_XXL */
#ifdef CONFIG_PERF_EVENTS
DECLARE_STATIC_KEY_FALSE(rdpmc_never_available_key);
DECLARE_STATIC_KEY_FALSE(rdpmc_always_available_key);
@@ -135,7 +128,7 @@ extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
#define activate_mm(prev, next) \
do { \
paravirt_activate_mm((prev), (next)); \
paravirt_enter_mmap(next); \
switch_mm((prev), (next), NULL); \
} while (0);
@@ -168,7 +161,7 @@ static inline void arch_dup_pkeys(struct mm_struct *oldmm,
static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
{
arch_dup_pkeys(oldmm, mm);
paravirt_arch_dup_mmap(oldmm, mm);
paravirt_enter_mmap(mm);
return ldt_dup_context(oldmm, mm);
}
+10 -6
View File
@@ -11,6 +11,14 @@
#include <asm/paravirt.h>
#include <asm/mshyperv.h>
/*
* Hyper-V always provides a single IO-APIC at this MMIO address.
* Ideally, the value should be looked up in ACPI tables, but it
* is needed for mapping the IO-APIC early in boot on Confidential
* VMs, before ACPI functions can be used.
*/
#define HV_IOAPIC_BASE_ADDRESS 0xfec00000
union hv_ghcb;
DECLARE_STATIC_KEY_FALSE(isolation_type_snp);
@@ -206,18 +214,19 @@ struct irq_domain *hv_create_pci_msi_domain(void);
int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
struct hv_interrupt_entry *entry);
int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
#ifdef CONFIG_AMD_MEM_ENCRYPT
void hv_ghcb_msr_write(u64 msr, u64 value);
void hv_ghcb_msr_read(u64 msr, u64 *value);
bool hv_ghcb_negotiate_protocol(void);
void hv_ghcb_terminate(unsigned int set, unsigned int reason);
void hv_vtom_init(void);
#else
static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
static inline void hv_vtom_init(void) {}
#endif
extern bool hv_isolation_type_snp(void);
@@ -259,11 +268,6 @@ static inline void hv_set_register(unsigned int reg, u64 value) { }
static inline u64 hv_get_register(unsigned int reg) { return 0; }
static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
bool visible)
{
return -1;
}
#endif /* CONFIG_HYPERV */
+3 -11
View File
@@ -334,16 +334,9 @@ static inline void tss_update_io_bitmap(void)
}
#endif
static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next)
static inline void paravirt_enter_mmap(struct mm_struct *next)
{
PVOP_VCALL2(mmu.activate_mm, prev, next);
}
static inline void paravirt_arch_dup_mmap(struct mm_struct *oldmm,
struct mm_struct *mm)
{
PVOP_VCALL2(mmu.dup_mmap, oldmm, mm);
PVOP_VCALL1(mmu.enter_mmap, next);
}
static inline int paravirt_pgd_alloc(struct mm_struct *mm)
@@ -789,8 +782,7 @@ extern void default_banner(void);
#ifndef __ASSEMBLY__
#ifndef CONFIG_PARAVIRT_XXL
static inline void paravirt_arch_dup_mmap(struct mm_struct *oldmm,
struct mm_struct *mm)
static inline void paravirt_enter_mmap(struct mm_struct *mm)
{
}
#endif
+9 -6
View File
@@ -164,11 +164,8 @@ struct pv_mmu_ops {
unsigned long (*read_cr3)(void);
void (*write_cr3)(unsigned long);
/* Hooks for intercepting the creation/use of an mm_struct. */
void (*activate_mm)(struct mm_struct *prev,
struct mm_struct *next);
void (*dup_mmap)(struct mm_struct *oldmm,
struct mm_struct *mm);
/* Hook for intercepting the creation/use of an mm_struct. */
void (*enter_mmap)(struct mm_struct *mm);
/* Hooks for allocating and freeing a pagetable top-level */
int (*pgd_alloc)(struct mm_struct *mm);
@@ -562,8 +559,14 @@ void paravirt_flush_lazy_mmu(void);
void _paravirt_nop(void);
void paravirt_BUG(void);
u64 _paravirt_ident_64(u64);
unsigned long paravirt_ret0(void);
#ifdef CONFIG_PARAVIRT_XXL
u64 _paravirt_ident_64(u64);
unsigned long pv_native_save_fl(void);
void pv_native_irq_disable(void);
void pv_native_irq_enable(void);
unsigned long pv_native_read_cr2(void);
#endif
#define paravirt_nop ((void *)_paravirt_nop)
-4
View File
@@ -128,10 +128,6 @@ struct snp_psc_desc {
struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY];
} __packed;
/* Guest message request error codes */
#define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32)
#define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33)
#define GHCB_MSR_TERM_REQ 0x100
#define GHCB_MSR_TERM_REASON_SET_POS 12
#define GHCB_MSR_TERM_REASON_SET_MASK 0xf
+7 -3
View File
@@ -9,6 +9,8 @@
#define __ASM_ENCRYPTED_STATE_H
#include <linux/types.h>
#include <linux/sev-guest.h>
#include <asm/insn.h>
#include <asm/sev-common.h>
#include <asm/bootparam.h>
@@ -185,6 +187,9 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
return rc;
}
struct snp_guest_request_ioctl;
void setup_ghcb(void);
void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
unsigned int npages);
@@ -196,7 +201,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
void snp_set_wakeup_secondary_cpu(void);
bool snp_init(struct boot_params *bp);
void __init __noreturn snp_abort(void);
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err);
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -216,8 +221,7 @@ static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npag
static inline void snp_set_wakeup_secondary_cpu(void) { }
static inline bool snp_init(struct boot_params *bp) { return false; }
static inline void snp_abort(void) { }
static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input,
unsigned long *fw_err)
static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
{
return -ENOTTY;
}
+4
View File
@@ -259,11 +259,15 @@ struct x86_legacy_features {
* VMMCALL under SEV-ES. Needs to return 'false'
* if the checks fail. Called from the #VC
* exception handler.
* @is_private_mmio: For CoCo VMs, must map MMIO address as private.
* Used when device is emulated by a paravisor
* layer in the VM context.
*/
struct x86_hyper_runtime {
void (*pin_vcpu)(int cpu);
void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs);
bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs);
bool (*is_private_mmio)(u64 addr);
};
/**
+8 -3
View File
@@ -1858,13 +1858,18 @@ early_param("acpi_sci", setup_acpi_sci);
int __acpi_acquire_global_lock(unsigned int *lock)
{
unsigned int old, new;
unsigned int old, new, val;
old = READ_ONCE(*lock);
do {
new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
val = (old >> 1) & 0x1;
new = (old & ~0x3) + 2 + val;
} while (!try_cmpxchg(lock, &old, new));
return ((new & 0x3) < 3) ? -1 : 0;
if (val)
return 0;
return -1;
}
int __acpi_release_global_lock(unsigned int *lock)
+8 -2
View File
@@ -66,6 +66,7 @@
#include <asm/hw_irq.h>
#include <asm/apic.h>
#include <asm/pgtable.h>
#include <asm/x86_init.h>
#define for_each_ioapic(idx) \
for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
@@ -2680,10 +2681,15 @@ static void io_apic_set_fixmap(enum fixed_addresses idx, phys_addr_t phys)
pgprot_t flags = FIXMAP_PAGE_NOCACHE;
/*
* Ensure fixmaps for IOAPIC MMIO respect memory encryption pgprot
* Ensure fixmaps for IO-APIC MMIO respect memory encryption pgprot
* bits, just like normal ioremap():
*/
flags = pgprot_decrypted(flags);
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
if (x86_platform.hyper.is_private_mmio(phys))
flags = pgprot_encrypted(flags);
else
flags = pgprot_decrypted(flags);
}
__set_fixmap(idx, phys, flags);
}
+11
View File
@@ -1009,6 +1009,17 @@ static void init_amd(struct cpuinfo_x86 *c)
msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
check_null_seg_clears_base(c);
/*
* Make sure EFER[AIBRSE - Automatic IBRS Enable] is set. The APs are brought up
* using the trampoline code and as part of it, MSR_EFER gets prepared there in
* order to be replicated onto them. Regardless, set it here again, if not set,
* to protect against any future refactoring/code reorganization which might
* miss setting this important bit.
*/
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
cpu_has(c, X86_FEATURE_AUTOIBRS))
WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
}
#ifdef CONFIG_X86_32
+1 -9
View File
@@ -784,8 +784,7 @@ static int __init nospectre_v1_cmdline(char *str)
}
early_param("nospectre_v1", nospectre_v1_cmdline);
static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
SPECTRE_V2_NONE;
enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = SPECTRE_V2_NONE;
#undef pr_fmt
#define pr_fmt(fmt) "RETBleed: " fmt
@@ -1133,13 +1132,6 @@ spectre_v2_parse_user_cmdline(void)
return SPECTRE_V2_USER_CMD_AUTO;
}
static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
{
return mode == SPECTRE_V2_EIBRS ||
mode == SPECTRE_V2_EIBRS_RETPOLINE ||
mode == SPECTRE_V2_EIBRS_LFENCE;
}
static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
{
return spectre_v2_in_eibrs_mode(mode) || mode == SPECTRE_V2_IBRS;
+1
View File
@@ -121,6 +121,7 @@ static const struct x86_cpu_id ppin_cpuids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &ppin_info[X86_VENDOR_INTEL]),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &ppin_info[X86_VENDOR_INTEL]),
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &ppin_info[X86_VENDOR_INTEL]),
X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &ppin_info[X86_VENDOR_INTEL]),
X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &ppin_info[X86_VENDOR_INTEL]),
X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &ppin_info[X86_VENDOR_INTEL]),
+8
View File
@@ -83,4 +83,12 @@ unsigned int aperfmperf_get_khz(int cpu);
extern void x86_spec_ctrl_setup_ap(void);
extern void update_srbds_msr(void);
extern enum spectre_v2_mitigation spectre_v2_enabled;
static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
{
return mode == SPECTRE_V2_EIBRS ||
mode == SPECTRE_V2_EIBRS_RETPOLINE ||
mode == SPECTRE_V2_EIBRS_LFENCE;
}
#endif /* ARCH_X86_CPU_H */
+22 -37
View File
@@ -1451,31 +1451,13 @@ void handle_bus_lock(struct pt_regs *regs)
}
/*
* Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
* only be trusted if it is confirmed that a CPU model implements a
* specific feature at a particular bit position.
*
* The possible driver data field values:
*
* - 0: CPU models that are known to have the per-core split-lock detection
* feature even though they do not enumerate IA32_CORE_CAPABILITIES.
*
* - 1: CPU models which may enumerate IA32_CORE_CAPABILITIES and if so use
* bit 5 to enumerate the per-core split-lock detection feature.
* CPU models that are known to have the per-core split-lock detection
* feature even though they do not enumerate IA32_CORE_CAPABILITIES.
*/
static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, 0),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, 0),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, 0),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, 1),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, 1),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, 1),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, 1),
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, 1),
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, 1),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, 1),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, 1),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, 1),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, 0),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, 0),
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, 0),
{}
};
@@ -1487,24 +1469,27 @@ static void __init split_lock_setup(struct cpuinfo_x86 *c)
if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
return;
/* Check for CPUs that have support but do not enumerate it: */
m = x86_match_cpu(split_lock_cpu_ids);
if (!m)
if (m)
goto supported;
if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
return;
switch (m->driver_data) {
case 0:
break;
case 1:
if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
return;
rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT))
return;
break;
default:
return;
}
/*
* Not all bits in MSR_IA32_CORE_CAPS are architectural, but
* MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is. All CPUs that set
* it have split lock detection.
*/
rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
goto supported;
/* CPU is not in the model list and does not have the MSR bit: */
return;
supported:
cpu_model_supports_sld = true;
__split_lock_setup();
}
+8 -8
View File
@@ -235,10 +235,10 @@ static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
* A list of the banks enabled on each logical CPU. Controls which respective
* descriptors to initialize later in mce_threshold_create_device().
*/
static DEFINE_PER_CPU(unsigned int, bank_map);
static DEFINE_PER_CPU(u64, bank_map);
/* Map of banks that have more than MCA_MISC0 available. */
static DEFINE_PER_CPU(u32, smca_misc_banks_map);
static DEFINE_PER_CPU(u64, smca_misc_banks_map);
static void amd_threshold_interrupt(void);
static void amd_deferred_error_interrupt(void);
@@ -267,7 +267,7 @@ static void smca_set_misc_banks_map(unsigned int bank, unsigned int cpu)
return;
if (low & MASK_BLKPTR_LO)
per_cpu(smca_misc_banks_map, cpu) |= BIT(bank);
per_cpu(smca_misc_banks_map, cpu) |= BIT_ULL(bank);
}
@@ -530,7 +530,7 @@ static u32 smca_get_block_address(unsigned int bank, unsigned int block,
if (!block)
return MSR_AMD64_SMCA_MCx_MISC(bank);
if (!(per_cpu(smca_misc_banks_map, cpu) & BIT(bank)))
if (!(per_cpu(smca_misc_banks_map, cpu) & BIT_ULL(bank)))
return 0;
return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
@@ -574,7 +574,7 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
int new;
if (!block)
per_cpu(bank_map, cpu) |= (1 << bank);
per_cpu(bank_map, cpu) |= BIT_ULL(bank);
memset(&b, 0, sizeof(b));
b.cpu = cpu;
@@ -878,7 +878,7 @@ static void amd_threshold_interrupt(void)
return;
for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
if (!(per_cpu(bank_map, cpu) & BIT_ULL(bank)))
continue;
first_block = bp[bank]->blocks;
@@ -1029,7 +1029,7 @@ static const struct sysfs_ops threshold_ops = {
static void threshold_block_release(struct kobject *kobj);
static struct kobj_type threshold_ktype = {
static const struct kobj_type threshold_ktype = {
.sysfs_ops = &threshold_ops,
.default_groups = default_groups,
.release = threshold_block_release,
@@ -1356,7 +1356,7 @@ int mce_threshold_create_device(unsigned int cpu)
return -ENOMEM;
for (bank = 0; bank < numbanks; ++bank) {
if (!(this_cpu_read(bank_map) & (1 << bank)))
if (!(this_cpu_read(bank_map) & BIT_ULL(bank)))
continue;
err = threshold_create_bank(bp, cpu, bank);
if (err) {
+5 -5
View File
@@ -244,11 +244,11 @@ noinstr void pentium_machine_check(struct pt_regs *regs);
noinstr void winchip_machine_check(struct pt_regs *regs);
static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
#else
static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
static inline void enable_p5_mce(void) {}
static inline void pentium_machine_check(struct pt_regs *regs) {}
static inline void winchip_machine_check(struct pt_regs *regs) {}
static __always_inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
static __always_inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
static __always_inline void enable_p5_mce(void) {}
static __always_inline void pentium_machine_check(struct pt_regs *regs) {}
static __always_inline void winchip_machine_check(struct pt_regs *regs) {}
#endif
noinstr u64 mce_rdmsrl(u32 msr);
+7 -8
View File
@@ -33,7 +33,6 @@
#include <asm/nmi.h>
#include <clocksource/hyperv_timer.h>
#include <asm/numa.h>
#include <asm/coco.h>
/* Is Linux running as the root partition? */
bool hv_root_partition;
@@ -401,8 +400,10 @@ static void __init ms_hyperv_init_platform(void)
if (ms_hyperv.priv_high & HV_ISOLATION) {
ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);
ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);
ms_hyperv.shared_gpa_boundary =
BIT_ULL(ms_hyperv.shared_gpa_boundary_bits);
if (ms_hyperv.shared_gpa_boundary_active)
ms_hyperv.shared_gpa_boundary =
BIT_ULL(ms_hyperv.shared_gpa_boundary_bits);
pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",
ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);
@@ -413,11 +414,6 @@ static void __init ms_hyperv_init_platform(void)
swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary;
#endif
}
/* Isolation VMs are unenlightened SEV-based VMs, thus this check: */
if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
if (hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE)
cc_set_vendor(CC_VENDOR_HYPERV);
}
}
if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {
@@ -486,6 +482,9 @@ static void __init ms_hyperv_init_platform(void)
i8253_clear_counter_on_shutdown = false;
#if IS_ENABLED(CONFIG_HYPERV)
if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) ||
(hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP))
hv_vtom_init();
/*
* Setup the hook to get control post apic initialization.
*/
+7 -23
View File
@@ -64,11 +64,11 @@ static unsigned paravirt_patch_call(void *insn_buff, const void *target,
}
#ifdef CONFIG_PARAVIRT_XXL
/* identity function, which can be inlined */
u64 notrace _paravirt_ident_64(u64 x)
{
return x;
}
DEFINE_PARAVIRT_ASM(_paravirt_ident_64, "mov %rdi, %rax", .text);
DEFINE_PARAVIRT_ASM(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
DEFINE_PARAVIRT_ASM(pv_native_irq_disable, "cli", .noinstr.text);
DEFINE_PARAVIRT_ASM(pv_native_irq_enable, "sti", .noinstr.text);
DEFINE_PARAVIRT_ASM(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text);
#endif
DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
@@ -197,11 +197,6 @@ void paravirt_end_context_switch(struct task_struct *next)
arch_enter_lazy_mmu_mode();
}
static noinstr unsigned long pv_native_read_cr2(void)
{
return native_read_cr2();
}
static noinstr void pv_native_write_cr2(unsigned long val)
{
native_write_cr2(val);
@@ -222,16 +217,6 @@ noinstr void pv_native_wbinvd(void)
native_wbinvd();
}
static noinstr void pv_native_irq_enable(void)
{
native_irq_enable();
}
static noinstr void pv_native_irq_disable(void)
{
native_irq_disable();
}
static noinstr void pv_native_safe_halt(void)
{
native_safe_halt();
@@ -298,7 +283,7 @@ struct paravirt_patch_template pv_ops = {
.cpu.end_context_switch = paravirt_nop,
/* Irq ops. */
.irq.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
.irq.save_fl = __PV_IS_CALLEE_SAVE(pv_native_save_fl),
.irq.irq_disable = __PV_IS_CALLEE_SAVE(pv_native_irq_disable),
.irq.irq_enable = __PV_IS_CALLEE_SAVE(pv_native_irq_enable),
.irq.safe_halt = pv_native_safe_halt,
@@ -363,8 +348,7 @@ struct paravirt_patch_template pv_ops = {
.mmu.make_pte = PTE_IDENT,
.mmu.make_pgd = PTE_IDENT,
.mmu.dup_mmap = paravirt_nop,
.mmu.activate_mm = paravirt_nop,
.mmu.enter_mmap = paravirt_nop,
.mmu.lazy_mode = {
.enter = paravirt_nop,
+8 -7
View File
@@ -22,6 +22,8 @@
#include <linux/efi.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/psp-sev.h>
#include <uapi/linux/sev-guest.h>
#include <asm/cpu_entry_area.h>
#include <asm/stacktrace.h>
@@ -2175,7 +2177,7 @@ static int __init init_sev_config(char *str)
}
__setup("sev=", init_sev_config);
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err)
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
{
struct ghcb_state state;
struct es_em_ctxt ctxt;
@@ -2183,8 +2185,7 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
struct ghcb *ghcb;
int ret;
if (!fw_err)
return -EINVAL;
rio->exitinfo2 = SEV_RET_NO_FW_CALL;
/*
* __sev_get_ghcb() needs to run with IRQs disabled because it is using
@@ -2209,16 +2210,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
if (ret)
goto e_put;
*fw_err = ghcb->save.sw_exit_info_2;
switch (*fw_err) {
rio->exitinfo2 = ghcb->save.sw_exit_info_2;
switch (rio->exitinfo2) {
case 0:
break;
case SNP_GUEST_REQ_ERR_BUSY:
case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_BUSY):
ret = -EAGAIN;
break;
case SNP_GUEST_REQ_INVALID_LEN:
case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN):
/* Number of expected pages are returned in RBX */
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
input->data_npages = ghcb_get_rbx(ghcb);
+2
View File
@@ -134,6 +134,7 @@ static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool
static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; }
static bool enc_tlb_flush_required_noop(bool enc) { return false; }
static bool enc_cache_flush_required_noop(void) { return false; }
static bool is_private_mmio_noop(u64 addr) {return false; }
struct x86_platform_ops x86_platform __ro_after_init = {
.calibrate_cpu = native_calibrate_cpu_early,
@@ -149,6 +150,7 @@ struct x86_platform_ops x86_platform __ro_after_init = {
.realmode_reserve = reserve_real_mode,
.realmode_init = init_real_mode,
.hyper.pin_vcpu = x86_op_int_noop,
.hyper.is_private_mmio = is_private_mmio_noop,
.guest = {
.enc_status_change_prepare = enc_status_change_prepare_noop,
+1 -1
View File
@@ -806,7 +806,7 @@ void __init poking_init(void)
BUG_ON(!poking_mm);
/* Xen PV guests need the PGD to be pinned. */
paravirt_arch_dup_mmap(NULL, poking_mm);
paravirt_enter_mmap(poking_mm);
/*
* Randomize the poking address, but make sure that the following page
+5
View File
@@ -116,6 +116,11 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
return;
if (x86_platform.hyper.is_private_mmio(addr)) {
desc->flags |= IORES_MAP_ENCRYPTED;
return;
}
if (!IS_ENABLED(CONFIG_EFI))
return;
+7 -3
View File
@@ -513,10 +513,14 @@ void __init mem_encrypt_free_decrypted_mem(void)
npages = (vaddr_end - vaddr) >> PAGE_SHIFT;
/*
* The unused memory range was mapped decrypted, change the encryption
* attribute from decrypted to encrypted before freeing it.
* If the unused memory range was mapped decrypted, change the encryption
* attribute from decrypted to encrypted before freeing it. Base the
* re-encryption on the same condition used for the decryption in
* sme_postprocess_startup(). Higher level abstractions, such as
* CC_ATTR_MEM_ENCRYPT, aren't necessarily equivalent in a Hyper-V VM
* using vTOM, where sme_me_mask is always zero.
*/
if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
if (sme_me_mask) {
r = set_memory_encrypted(vaddr, npages);
if (r) {
pr_warn("failed to free unused decrypted pages\n");
-3
View File
@@ -2175,9 +2175,6 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
{
if (hv_is_isolation_supported())
return hv_set_mem_host_visibility(addr, numpages, !enc);
if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
return __set_memory_enc_pgtable(addr, numpages, enc);
+2 -10
View File
@@ -885,14 +885,7 @@ void xen_mm_unpin_all(void)
spin_unlock(&pgd_lock);
}
static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
spin_lock(&next->page_table_lock);
xen_pgd_pin(next);
spin_unlock(&next->page_table_lock);
}
static void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
static void xen_enter_mmap(struct mm_struct *mm)
{
spin_lock(&mm->page_table_lock);
xen_pgd_pin(mm);
@@ -2153,8 +2146,7 @@ static const typeof(pv_ops) xen_mmu_ops __initconst = {
.make_p4d = PV_CALLEE_SAVE(xen_make_p4d),
#endif
.activate_mm = xen_activate_mm,
.dup_mmap = xen_dup_mmap,
.enter_mmap = xen_enter_mmap,
.exit_mmap = xen_exit_mmap,
.lazy_mode = {
+14 -8
View File
@@ -442,12 +442,19 @@ static int __sev_init_ex_locked(int *error)
return __sev_do_cmd_locked(SEV_CMD_INIT_EX, &data, error);
}
static inline int __sev_do_init_locked(int *psp_ret)
{
if (sev_init_ex_buffer)
return __sev_init_ex_locked(psp_ret);
else
return __sev_init_locked(psp_ret);
}
static int __sev_platform_init_locked(int *error)
{
int rc = 0, psp_ret = SEV_RET_NO_FW_CALL;
struct psp_device *psp = psp_master;
struct sev_device *sev;
int rc = 0, psp_ret = -1;
int (*init_function)(int *error);
if (!psp || !psp->sev_data)
return -ENODEV;
@@ -458,15 +465,12 @@ static int __sev_platform_init_locked(int *error)
return 0;
if (sev_init_ex_buffer) {
init_function = __sev_init_ex_locked;
rc = sev_read_init_ex_file();
if (rc)
return rc;
} else {
init_function = __sev_init_locked;
}
rc = init_function(&psp_ret);
rc = __sev_do_init_locked(&psp_ret);
if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) {
/*
* Initialization command returned an integrity check failure
@@ -475,9 +479,11 @@ static int __sev_platform_init_locked(int *error)
* initialization function should succeed by replacing the state
* with a reset state.
*/
dev_err(sev->dev, "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state.");
rc = init_function(&psp_ret);
dev_err(sev->dev,
"SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state.");
rc = __sev_do_init_locked(&psp_ret);
}
if (error)
*error = psp_ret;
+3 -7
View File
@@ -2149,10 +2149,8 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
}
edac->sb_irq = platform_get_irq(pdev, 0);
if (edac->sb_irq < 0) {
dev_err(&pdev->dev, "No SBERR IRQ resource\n");
if (edac->sb_irq < 0)
return edac->sb_irq;
}
irq_set_chained_handler_and_data(edac->sb_irq,
altr_edac_a10_irq_handler,
@@ -2184,10 +2182,9 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
}
#else
edac->db_irq = platform_get_irq(pdev, 1);
if (edac->db_irq < 0) {
dev_err(&pdev->dev, "No DBERR IRQ resource\n");
if (edac->db_irq < 0)
return edac->db_irq;
}
irq_set_chained_handler_and_data(edac->db_irq,
altr_edac_a10_irq_handler, edac);
#endif
@@ -2226,6 +2223,5 @@ static struct platform_driver altr_edac_a10_driver = {
};
module_platform_driver(altr_edac_a10_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Thor Thayer");
MODULE_DESCRIPTION("EDAC Driver for Altera Memories");
+458 -584
View File
File diff suppressed because it is too large Load Diff
+25 -42
View File
@@ -273,25 +273,6 @@
#define UMC_SDP_INIT BIT(31)
enum amd_families {
K8_CPUS = 0,
F10_CPUS,
F15_CPUS,
F15_M30H_CPUS,
F15_M60H_CPUS,
F16_CPUS,
F16_M30H_CPUS,
F17_CPUS,
F17_M10H_CPUS,
F17_M30H_CPUS,
F17_M60H_CPUS,
F17_M70H_CPUS,
F19_CPUS,
F19_M10H_CPUS,
F19_M50H_CPUS,
NUM_FAMILIES,
};
/* Error injection control structure */
struct error_injection {
u32 section;
@@ -334,6 +315,16 @@ struct amd64_umc {
enum mem_type dram_type;
};
struct amd64_family_flags {
/*
* Indicates that the system supports the new register offsets, etc.
* first introduced with Family 19h Model 10h.
*/
__u64 zn_regs_v2 : 1,
__reserved : 63;
};
struct amd64_pvt {
struct low_ops *ops;
@@ -375,6 +366,12 @@ struct amd64_pvt {
/* x4, x8, or x16 syndromes in use */
u8 ecc_sym_sz;
const char *ctl_name;
u16 f1_id, f2_id;
/* Maximum number of memory controllers per die/node. */
u8 max_mcs;
struct amd64_family_flags flags;
/* place to store error injection parameters prior to issue */
struct error_injection injection;
@@ -465,29 +462,15 @@ struct ecc_settings {
* functions and per device encoding/decoding logic.
*/
struct low_ops {
void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr,
struct err_info *);
int (*dbam_to_cs) (struct amd64_pvt *pvt, u8 dct,
unsigned cs_mode, int cs_mask_nr);
};
struct amd64_family_flags {
/*
* Indicates that the system supports the new register offsets, etc.
* first introduced with Family 19h Model 10h.
*/
__u64 zn_regs_v2 : 1,
__reserved : 63;
};
struct amd64_family_type {
const char *ctl_name;
u16 f1_id, f2_id;
/* Maximum number of memory controllers per die/node. */
u8 max_mcs;
struct amd64_family_flags flags;
struct low_ops ops;
void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci, u64 sys_addr,
struct err_info *err);
int (*dbam_to_cs)(struct amd64_pvt *pvt, u8 dct,
unsigned int cs_mode, int cs_mask_nr);
int (*hw_info_get)(struct amd64_pvt *pvt);
bool (*ecc_enabled)(struct amd64_pvt *pvt);
void (*setup_mci_misc_attrs)(struct mem_ctl_info *mci);
void (*dump_misc_regs)(struct amd64_pvt *pvt);
void (*get_err_info)(struct mce *m, struct err_info *err);
};
int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+1 -1
View File
@@ -593,5 +593,5 @@ module_init(amd8111_edac_init);
module_exit(amd8111_edac_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
MODULE_DESCRIPTION("AMD8111 HyperTransport I/O Hub EDAC kernel module");
+1 -1
View File
@@ -354,5 +354,5 @@ module_init(amd8131_edac_init);
module_exit(amd8131_edac_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
MODULE_DESCRIPTION("AMD8131 HyperTransport PCI-X Tunnel EDAC kernel module");
+1 -1
View File
@@ -1462,7 +1462,7 @@ module_init(e752x_init);
module_exit(e752x_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman");
MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
module_param(force_function_unhide, int, 0444);
+1 -2
View File
@@ -596,8 +596,7 @@ module_init(e7xxx_init);
module_exit(e7xxx_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
"Based on.work by Dan Hollis et al");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al");
MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+1
View File
@@ -906,6 +906,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = {
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(EMERALDRAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(GRANITERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SIERRAFOREST_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
{}
};
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
+2 -5
View File
@@ -1573,13 +1573,10 @@ module_init(i5000_init);
module_exit(i5000_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR
("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
I5000_REVISION);
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - " I5000_REVISION);
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
module_param(misc_messages, int, 0444);
MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
+2 -3
View File
@@ -909,7 +909,7 @@ static void i5100_do_inject(struct mem_ctl_info *mci)
*
* The injection code don't work without setting this register.
* The register needs to be flipped off then on else the hardware
* will only preform the first injection.
* will only perform the first injection.
*
* Stop condition bits 7:4
* 1010 - Stop after one injection
@@ -1220,6 +1220,5 @@ module_init(i5100_init);
module_exit(i5100_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR
("Arthur Jones <ajones@riverbed.com>");
MODULE_AUTHOR("Arthur Jones <ajones@riverbed.com>");
MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers");
+1 -2
View File
@@ -355,8 +355,7 @@ module_init(i82860_init);
module_exit(i82860_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
"Ben Woodard <woodard@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) Ben Woodard <woodard@redhat.com>");
MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
module_param(edac_op_state, int, 0444);
+1 -2
View File
@@ -72,5 +72,4 @@ module_exit(fsl_ddr_mc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("NXP Semiconductor");
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state,
"EDAC Error Reporting state: 0=Poll, 2=Interrupt");
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
+1 -2
View File
@@ -711,5 +711,4 @@ module_exit(mpc85xx_mc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Montavista Software, Inc.");
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state,
"EDAC Error Reporting state: 0=Poll, 2=Interrupt");
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
+1 -2
View File
@@ -415,8 +415,7 @@ module_init(r82600_init);
module_exit(r82600_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
"on behalf of EADS Astrium");
MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. on behalf of EADS Astrium");
MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
module_param(disable_hardware_scrub, bool, 0644);
+2 -2
View File
@@ -510,7 +510,7 @@ rir_found:
}
static u8 skx_close_row[] = {
15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33
15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33, 34
};
static u8 skx_close_column[] = {
@@ -518,7 +518,7 @@ static u8 skx_close_column[] = {
};
static u8 skx_open_row[] = {
14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33
14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34
};
static u8 skx_open_column[] = {
+1 -1
View File
@@ -211,7 +211,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
ring_info->ring_buffer = (struct hv_ring_buffer *)
vmap_pfn(pfns_wraparound, page_cnt * 2 - 1,
PAGE_KERNEL);
pgprot_decrypted(PAGE_KERNEL));
kfree(pfns_wraparound);
if (!ring_info->ring_buffer)
-1
View File
@@ -2156,7 +2156,6 @@ void vmbus_device_unregister(struct hv_device *device_obj)
* VMBUS is an acpi enumerated device. Get the information we
* need from DSDT.
*/
#define VTPM_BASE_ADDRESS 0xfed40000
static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
{
resource_size_t start = 0;
+62 -37
View File
@@ -46,7 +46,15 @@ struct snp_guest_dev {
void *certs_data;
struct snp_guest_crypto *crypto;
/* request and response are in unencrypted memory */
struct snp_guest_msg *request, *response;
/*
* Avoid information leakage by double-buffering shared messages
* in fields that are in regular encrypted memory.
*/
struct snp_guest_msg secret_request, secret_response;
struct snp_secrets_page_layout *layout;
struct snp_req_data input;
u32 *os_area_msg_seqno;
@@ -266,14 +274,17 @@ static int dec_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg,
static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz)
{
struct snp_guest_crypto *crypto = snp_dev->crypto;
struct snp_guest_msg *resp = snp_dev->response;
struct snp_guest_msg *req = snp_dev->request;
struct snp_guest_msg *resp = &snp_dev->secret_response;
struct snp_guest_msg *req = &snp_dev->secret_request;
struct snp_guest_msg_hdr *req_hdr = &req->hdr;
struct snp_guest_msg_hdr *resp_hdr = &resp->hdr;
dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n",
resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz);
/* Copy response from shared memory to encrypted memory. */
memcpy(resp, snp_dev->response, sizeof(*resp));
/* Verify that the sequence counter is incremented by 1 */
if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1)))
return -EBADMSG;
@@ -297,7 +308,7 @@ static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload,
static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type,
void *payload, size_t sz)
{
struct snp_guest_msg *req = snp_dev->request;
struct snp_guest_msg *req = &snp_dev->secret_request;
struct snp_guest_msg_hdr *hdr = &req->hdr;
memset(req, 0, sizeof(*req));
@@ -321,11 +332,12 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8
return __enc_payload(snp_dev, req, payload, sz);
}
static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err)
static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code,
struct snp_guest_request_ioctl *rio)
{
unsigned long err = 0xff, override_err = 0;
unsigned long req_start = jiffies;
unsigned int override_npages = 0;
u64 override_err = 0;
int rc;
retry_request:
@@ -335,7 +347,7 @@ retry_request:
* sequence number must be incremented or the VMPCK must be deleted to
* prevent reuse of the IV.
*/
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
rc = snp_issue_guest_request(exit_code, &snp_dev->input, rio);
switch (rc) {
case -ENOSPC:
/*
@@ -353,7 +365,7 @@ retry_request:
* request buffer size was too small and give the caller the
* required buffer size.
*/
override_err = SNP_GUEST_REQ_INVALID_LEN;
override_err = SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN);
/*
* If this call to the firmware succeeds, the sequence number can
@@ -366,7 +378,7 @@ retry_request:
goto retry_request;
/*
* The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been
* The host may return SNP_GUEST_VMM_ERR_BUSY if the request has been
* throttled. Retry in the driver to avoid returning and reusing the
* message sequence number on a different message.
*/
@@ -387,27 +399,29 @@ retry_request:
*/
snp_inc_msg_seqno(snp_dev);
if (fw_err)
*fw_err = override_err ?: err;
if (override_err) {
rio->exitinfo2 = override_err;
/*
* If an extended guest request was issued and the supplied certificate
* buffer was not large enough, a standard guest request was issued to
* prevent IV reuse. If the standard request was successful, return -EIO
* back to the caller as would have originally been returned.
*/
if (!rc && override_err == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
rc = -EIO;
}
if (override_npages)
snp_dev->input.data_npages = override_npages;
/*
* If an extended guest request was issued and the supplied certificate
* buffer was not large enough, a standard guest request was issued to
* prevent IV reuse. If the standard request was successful, return -EIO
* back to the caller as would have originally been returned.
*/
if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN)
return -EIO;
return rc;
}
static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,
u8 type, void *req_buf, size_t req_sz, void *resp_buf,
u32 resp_sz, __u64 *fw_err)
static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code,
struct snp_guest_request_ioctl *rio, u8 type,
void *req_buf, size_t req_sz, void *resp_buf,
u32 resp_sz)
{
u64 seqno;
int rc;
@@ -417,19 +431,31 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
if (!seqno)
return -EIO;
/* Clear shared memory's response for the host to populate. */
memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
/* Encrypt the userspace provided payload */
rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
/* Encrypt the userspace provided payload in snp_dev->secret_request. */
rc = enc_payload(snp_dev, seqno, rio->msg_version, type, req_buf, req_sz);
if (rc)
return rc;
rc = __handle_guest_request(snp_dev, exit_code, fw_err);
/*
* Write the fully encrypted request to the shared unencrypted
* request page.
*/
memcpy(snp_dev->request, &snp_dev->secret_request,
sizeof(snp_dev->secret_request));
rc = __handle_guest_request(snp_dev, exit_code, rio);
if (rc) {
if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN)
if (rc == -EIO &&
rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
return rc;
dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err);
dev_alert(snp_dev->dev,
"Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n",
rc, rio->exitinfo2);
snp_disable_vmpck(snp_dev);
return rc;
}
@@ -469,9 +495,9 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
if (!resp)
return -ENOMEM;
rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version,
rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg,
SNP_MSG_REPORT_REQ, &req, sizeof(req), resp->data,
resp_len, &arg->fw_err);
resp_len);
if (rc)
goto e_free;
@@ -509,9 +535,8 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req)))
return -EFAULT;
rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version,
SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len,
&arg->fw_err);
rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg,
SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len);
if (rc)
return rc;
@@ -571,12 +596,12 @@ cmd:
return -ENOMEM;
snp_dev->input.data_npages = npages;
ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg->msg_version,
ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg,
SNP_MSG_REPORT_REQ, &req.data,
sizeof(req.data), resp->data, resp_len, &arg->fw_err);
sizeof(req.data), resp->data, resp_len);
/* If certs length is invalid then copy the returned length */
if (arg->fw_err == SNP_GUEST_REQ_INVALID_LEN) {
if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {
req.certs_len = snp_dev->input.data_npages << PAGE_SHIFT;
if (copy_to_user((void __user *)arg->req_data, &req, sizeof(req)))
@@ -611,7 +636,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
if (copy_from_user(&input, argp, sizeof(input)))
return -EFAULT;
input.fw_err = 0xff;
input.exitinfo2 = 0xff;
/* Message version must be non-zero */
if (!input.msg_version)
@@ -642,7 +667,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
mutex_unlock(&snp_cmd_mutex);
if (input.fw_err && copy_to_user(argp, &input, sizeof(input)))
if (input.exitinfo2 && copy_to_user(argp, &input, sizeof(input)))
return -EFAULT;
return ret;
+2
View File
@@ -26,6 +26,8 @@
#include <asm/ptrace.h>
#include <asm/hyperv-tlfs.h>
#define VTPM_BASE_ADDRESS 0xfed40000
struct ms_hyperv_info {
u32 features;
u32 priv_high;
+7
View File
@@ -36,6 +36,13 @@ enum {
* SEV Firmware status code
*/
typedef enum {
/*
* This error code is not in the SEV spec. Its purpose is to convey that
* there was an error that prevented the SEV firmware from being called.
* The SEV API error codes are 16 bits, so the -1 value will not overlap
* with possible values from the specification.
*/
SEV_RET_NO_FW_CALL = -1,
SEV_RET_SUCCESS = 0,
SEV_RET_INVALID_PLATFORM_STATE,
SEV_RET_INVALID_GUEST_STATE,
+16 -2
View File
@@ -52,8 +52,14 @@ struct snp_guest_request_ioctl {
__u64 req_data;
__u64 resp_data;
/* firmware error code on failure (see psp-sev.h) */
__u64 fw_err;
/* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */
union {
__u64 exitinfo2;
struct {
__u32 fw_error;
__u32 vmm_error;
};
};
};
struct snp_ext_report_req {
@@ -77,4 +83,12 @@ struct snp_ext_report_req {
/* Get SNP extended report as defined in the GHCB specification version 2. */
#define SNP_GET_EXT_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x2, struct snp_guest_request_ioctl)
/* Guest message request EXIT_INFO_2 constants */
#define SNP_GUEST_FW_ERR_MASK GENMASK_ULL(31, 0)
#define SNP_GUEST_VMM_ERR_SHIFT 32
#define SNP_GUEST_VMM_ERR(x) (((u64)x) << SNP_GUEST_VMM_ERR_SHIFT)
#define SNP_GUEST_VMM_ERR_INVALID_LEN 1
#define SNP_GUEST_VMM_ERR_BUSY 2
#endif /* __UAPI_LINUX_SEV_GUEST_H_ */
+11 -8
View File
@@ -1090,14 +1090,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
*/
locking_selftest();
/*
* This needs to be called before any devices perform DMA
* operations that might use the SWIOTLB bounce buffers. It will
* mark the bounce buffers as decrypted so that their usage will
* not cause "plain-text" data to be decrypted when accessed.
*/
mem_encrypt_init();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
@@ -1114,6 +1106,17 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
late_time_init();
sched_clock_init();
calibrate_delay();
/*
* This needs to be called before any devices perform DMA
* operations that might use the SWIOTLB bounce buffers. It will
* mark the bounce buffers as decrypted so that their usage will
* not cause "plain-text" data to be decrypted when accessed. It
* must be called after late_time_init() so that Hyper-V x86/x64
* hypercalls work when the SWIOTLB bounce buffers are decrypted.
*/
mem_encrypt_init();
pid_idr_init();
anon_vma_init();
#ifdef CONFIG_X86
+58 -7
View File
@@ -184,8 +184,8 @@
7, 0, EBX, 27, avx512er, AVX512 Exponent Reciproca instr
7, 0, EBX, 28, avx512cd, AVX512 Conflict Detection instr
7, 0, EBX, 29, sha, Intel Secure Hash Algorithm Extensions instr
7, 0, EBX, 26, avx512bw, AVX512 Byte & Word instr
7, 0, EBX, 28, avx512vl, AVX512 Vector Length Extentions (VL)
7, 0, EBX, 30, avx512bw, AVX512 Byte & Word instr
7, 0, EBX, 31, avx512vl, AVX512 Vector Length Extentions (VL)
7, 0, ECX, 0, prefetchwt1, X
7, 0, ECX, 1, avx512vbmi, AVX512 Vector Byte Manipulation Instructions
7, 0, ECX, 2, umip, User-mode Instruction Prevention
@@ -340,19 +340,70 @@
# According to SDM
# 40000000H - 4FFFFFFFH is invalid range
# Leaf 80000001H
# Extended Processor Signature and Feature Bits
0x80000001, 0, ECX, 0, lahf_lm, LAHF/SAHF available in 64-bit mode
0x80000001, 0, ECX, 5, lzcnt, LZCNT
0x80000001, 0, ECX, 8, prefetchw, PREFETCHW
0x80000001, 0, EAX, 27:20, extfamily, Extended family
0x80000001, 0, EAX, 19:16, extmodel, Extended model
0x80000001, 0, EAX, 11:8, basefamily, Description of Family
0x80000001, 0, EAX, 11:8, basemodel, Model numbers vary with product
0x80000001, 0, EAX, 3:0, stepping, Processor stepping (revision) for a specific model
0x80000001, 0, EBX, 31:28, pkgtype, Specifies the package type
0x80000001, 0, ECX, 0, lahf_lm, LAHF/SAHF available in 64-bit mode
0x80000001, 0, ECX, 1, cmplegacy, Core multi-processing legacy mode
0x80000001, 0, ECX, 2, svm, Indicates support for: VMRUN, VMLOAD, VMSAVE, CLGI, VMMCALL, and INVLPGA
0x80000001, 0, ECX, 3, extapicspace, Extended APIC register space
0x80000001, 0, ECX, 4, altmovecr8, Indicates support for LOCK MOV CR0 means MOV CR8
0x80000001, 0, ECX, 5, lzcnt, LZCNT
0x80000001, 0, ECX, 6, sse4a, EXTRQ, INSERTQ, MOVNTSS, and MOVNTSD instruction support
0x80000001, 0, ECX, 7, misalignsse, Misaligned SSE Mode
0x80000001, 0, ECX, 8, prefetchw, PREFETCHW
0x80000001, 0, ECX, 9, osvw, OS Visible Work-around support
0x80000001, 0, ECX, 10, ibs, Instruction Based Sampling
0x80000001, 0, ECX, 11, xop, Extended operation support
0x80000001, 0, ECX, 12, skinit, SKINIT and STGI support
0x80000001, 0, ECX, 13, wdt, Watchdog timer support
0x80000001, 0, ECX, 15, lwp, Lightweight profiling support
0x80000001, 0, ECX, 16, fma4, Four-operand FMA instruction support
0x80000001, 0, ECX, 17, tce, Translation cache extension
0x80000001, 0, ECX, 22, TopologyExtensions, Indicates support for Core::X86::Cpuid::CachePropEax0 and Core::X86::Cpuid::ExtApicId
0x80000001, 0, ECX, 23, perfctrextcore, Indicates support for Core::X86::Msr::PERF_CTL0 - 5 and Core::X86::Msr::PERF_CTR
0x80000001, 0, ECX, 24, perfctrextdf, Indicates support for Core::X86::Msr::DF_PERF_CTL and Core::X86::Msr::DF_PERF_CTR
0x80000001, 0, ECX, 26, databreakpointextension, Indicates data breakpoint support for Core::X86::Msr::DR0_ADDR_MASK, Core::X86::Msr::DR1_ADDR_MASK, Core::X86::Msr::DR2_ADDR_MASK and Core::X86::Msr::DR3_ADDR_MASK
0x80000001, 0, ECX, 27, perftsc, Performance time-stamp counter supported
0x80000001, 0, ECX, 28, perfctrextllc, Indicates support for L3 performance counter extensions
0x80000001, 0, ECX, 29, mwaitextended, MWAITX and MONITORX capability is supported
0x80000001, 0, ECX, 30, admskextn, Indicates support for address mask extension (to 32 bits and to all 4 DRs) for instruction breakpoints
0x80000001, 0, EDX, 0, fpu, x87 floating point unit on-chip
0x80000001, 0, EDX, 1, vme, Virtual-mode enhancements
0x80000001, 0, EDX, 2, de, Debugging extensions, IO breakpoints, CR4.DE
0x80000001, 0, EDX, 3, pse, Page-size extensions (4 MB pages)
0x80000001, 0, EDX, 4, tsc, Time stamp counter, RDTSC/RDTSCP instructions, CR4.TSD
0x80000001, 0, EDX, 5, msr, Model-specific registers (MSRs), with RDMSR and WRMSR instructions
0x80000001, 0, EDX, 6, pae, Physical-address extensions (PAE)
0x80000001, 0, EDX, 7, mce, Machine Check Exception, CR4.MCE
0x80000001, 0, EDX, 8, cmpxchg8b, CMPXCHG8B instruction
0x80000001, 0, EDX, 9, apic, advanced programmable interrupt controller (APIC) exists and is enabled
0x80000001, 0, EDX, 11, sysret, SYSCALL/SYSRET supported
0x80000001, 0, EDX, 12, mtrr, Memory-type range registers
0x80000001, 0, EDX, 13, pge, Page global extension, CR4.PGE
0x80000001, 0, EDX, 14, mca, Machine check architecture, MCG_CAP
0x80000001, 0, EDX, 15, cmov, Conditional move instructions, CMOV, FCOMI, FCMOV
0x80000001, 0, EDX, 16, pat, Page attribute table
0x80000001, 0, EDX, 17, pse36, Page-size extensions
0x80000001, 0, EDX, 20, exec_dis, Execute Disable Bit available
0x80000001, 0, EDX, 22, mmxext, AMD extensions to MMX instructions
0x80000001, 0, EDX, 23, mmx, MMX instructions
0x80000001, 0, EDX, 24, fxsr, FXSAVE and FXRSTOR instructions
0x80000001, 0, EDX, 25, ffxsr, FXSAVE and FXRSTOR instruction optimizations
0x80000001, 0, EDX, 26, 1gb_page, 1GB page supported
0x80000001, 0, EDX, 27, rdtscp, RDTSCP and IA32_TSC_AUX are available
#0x80000001, 0, EDX, 29, 64b, 64b Architecture supported
0x80000001, 0, EDX, 29, lm, 64b Architecture supported
0x80000001, 0, EDX, 30, threednowext, AMD extensions to 3DNow! instructions
0x80000001, 0, EDX, 31, threednow, 3DNow! instructions
# Leaf 80000002H/80000003H/80000004H
# Processor Brand String
1 # The basic row format is:
184 #
185 # Leaf 08H
186 #
187 # Leaf 09H
188 # Direct Cache Access (DCA) information
189
190 # Leaf 0AH
191 # Architectural Performance Monitoring
340 0x80000001, 0, EDX, 25, ffxsr, FXSAVE and FXRSTOR instruction optimizations
341 0x80000001, 0, EDX, 26, 1gb_page, 1GB page supported
342 0x80000001, 0, EDX, 27, rdtscp, RDTSCP and IA32_TSC_AUX are available
343 0x80000001, 0, EDX, 29, lm, 64b Architecture supported
344 0x80000001, 0, EDX, 30, threednowext, AMD extensions to 3DNow! instructions
345 0x80000001, 0, EDX, 31, threednow, 3DNow! instructions
346 # Leaf 80000002H/80000003H/80000004H
347 # Processor Brand String
348 # Leaf 80000005H
349 # Reserved
350 # Leaf 80000006H
351 # Extended L2 Cache Features
352 0x80000006, 0, ECX, 7:0, clsize, Cache Line size in bytes
353 0x80000006, 0, ECX, 15:12, l2c_assoc, L2 Associativity
354 0x80000006, 0, ECX, 31:16, csize, Cache size in 1K units
355 # Leaf 80000007H
356 0x80000007, 0, EDX, 8, nonstop_tsc, Invariant TSC available
357 # Leaf 80000008H
358 0x80000008, 0, EAX, 7:0, phy_adr_bits, Physical Address Bits
359 0x80000008, 0, EAX, 15:8, lnr_adr_bits, Linear Address Bits
360 0x80000007, 0, EBX, 9, wbnoinvd, WBNOINVD
361 # 0x8000001E
362 # EAX: Extended APIC ID
363 0x8000001E,
364 # EBX: Core Identifiers
365 0x8000001E,
366 0x8000001E,
367 # ECX: Node Identifiers
368 0x8000001E,
369 0x8000001E,
370 # 8000001F: AMD Secure Encryption
371 0x8000001F,
372 0x8000001F,
373 0x8000001F,
374 0x8000001F,
375 0x8000001F,
376 0x8000001F,
377 0x8000001F,
378 0x8000001F,
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
+25 -7
View File
@@ -33,7 +33,7 @@ struct reg_desc {
struct bits_desc descs[32];
};
enum {
enum cpuid_reg {
R_EAX = 0,
R_EBX,
R_ECX,
@@ -41,6 +41,10 @@ enum {
NR_REGS
};
static const char * const reg_names[] = {
"EAX", "EBX", "ECX", "EDX",
};
struct subleaf {
u32 index;
u32 sub;
@@ -428,12 +432,18 @@ static void parse_text(void)
/* Decode every eax/ebx/ecx/edx */
static void decode_bits(u32 value, struct reg_desc *rdesc)
static void decode_bits(u32 value, struct reg_desc *rdesc, enum cpuid_reg reg)
{
struct bits_desc *bdesc;
int start, end, i;
u32 mask;
if (!rdesc->nr) {
if (show_details)
printf("\t %s: 0x%08x\n", reg_names[reg], value);
return;
}
for (i = 0; i < rdesc->nr; i++) {
bdesc = &rdesc->descs[i];
@@ -468,13 +478,21 @@ static void show_leaf(struct subleaf *leaf)
if (!leaf)
return;
if (show_raw)
if (show_raw) {
leaf_print_raw(leaf);
} else {
if (show_details)
printf("CPUID_0x%x_ECX[0x%x]:\n",
leaf->index, leaf->sub);
}
decode_bits(leaf->eax, &leaf->info[R_EAX]);
decode_bits(leaf->ebx, &leaf->info[R_EBX]);
decode_bits(leaf->ecx, &leaf->info[R_ECX]);
decode_bits(leaf->edx, &leaf->info[R_EDX]);
decode_bits(leaf->eax, &leaf->info[R_EAX], R_EAX);
decode_bits(leaf->ebx, &leaf->info[R_EBX], R_EBX);
decode_bits(leaf->ecx, &leaf->info[R_ECX], R_ECX);
decode_bits(leaf->edx, &leaf->info[R_EDX], R_EDX);
if (!show_raw && show_details)
printf("\n");
}
static void show_func(struct cpuid_func *func)