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:
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
enum cc_vendor {
|
||||
CC_VENDOR_NONE,
|
||||
CC_VENDOR_AMD,
|
||||
CC_VENDOR_HYPERV,
|
||||
CC_VENDOR_INTEL,
|
||||
};
|
||||
|
||||
|
||||
@@ -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) { }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]),
|
||||
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+25
-42
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user