mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge tag 'v6.1.84' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroidxu4-6.1.y
This is the 6.1.84 stable release Change-Id: I3798853c42e99a817a0ca9ca1aa65f81f3279e99
This commit is contained in:
@@ -484,11 +484,14 @@ Spectre variant 2
|
||||
|
||||
Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
|
||||
boot, by setting the IBRS bit, and they're automatically protected against
|
||||
Spectre v2 variant attacks, including cross-thread branch target injections
|
||||
on SMT systems (STIBP). In other words, eIBRS enables STIBP too.
|
||||
Spectre v2 variant attacks.
|
||||
|
||||
Legacy IBRS systems clear the IBRS bit on exit to userspace and
|
||||
therefore explicitly enable STIBP for that
|
||||
On Intel's enhanced IBRS systems, this includes cross-thread branch target
|
||||
injections on SMT systems (STIBP). In other words, Intel eIBRS enables
|
||||
STIBP, too.
|
||||
|
||||
AMD Automatic IBRS does not protect userspace, and Legacy IBRS systems clear
|
||||
the IBRS bit on exit to userspace, therefore both explicitly enable STIBP.
|
||||
|
||||
The retpoline mitigation is turned on by default on vulnerable
|
||||
CPUs. It can be forced on or off by the administrator
|
||||
@@ -621,9 +624,9 @@ kernel command line.
|
||||
retpoline,generic Retpolines
|
||||
retpoline,lfence LFENCE; indirect branch
|
||||
retpoline,amd alias for retpoline,lfence
|
||||
eibrs enhanced IBRS
|
||||
eibrs,retpoline enhanced IBRS + Retpolines
|
||||
eibrs,lfence enhanced IBRS + LFENCE
|
||||
eibrs Enhanced/Auto IBRS
|
||||
eibrs,retpoline Enhanced/Auto IBRS + Retpolines
|
||||
eibrs,lfence Enhanced/Auto IBRS + LFENCE
|
||||
ibrs use IBRS to protect kernel
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
|
||||
@@ -3206,9 +3206,7 @@
|
||||
|
||||
mem_encrypt= [X86-64] AMD Secure Memory Encryption (SME) control
|
||||
Valid arguments: on, off
|
||||
Default (depends on kernel configuration option):
|
||||
on (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y)
|
||||
off (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=n)
|
||||
Default: off
|
||||
mem_encrypt=on: Activate SME
|
||||
mem_encrypt=off: Do not activate SME
|
||||
|
||||
@@ -5765,9 +5763,9 @@
|
||||
retpoline,generic - Retpolines
|
||||
retpoline,lfence - LFENCE; indirect branch
|
||||
retpoline,amd - alias for retpoline,lfence
|
||||
eibrs - enhanced IBRS
|
||||
eibrs,retpoline - enhanced IBRS + Retpolines
|
||||
eibrs,lfence - enhanced IBRS + LFENCE
|
||||
eibrs - Enhanced/Auto IBRS
|
||||
eibrs,retpoline - Enhanced/Auto IBRS + Retpolines
|
||||
eibrs,lfence - Enhanced/Auto IBRS + LFENCE
|
||||
ibrs - use IBRS to protect kernel
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
|
||||
@@ -375,12 +375,11 @@ Types and flags used to represent the media graph elements
|
||||
are origins of links.
|
||||
|
||||
* - ``MEDIA_PAD_FL_MUST_CONNECT``
|
||||
- If this flag is set and the pad is linked to any other pad, then
|
||||
at least one of those links must be enabled for the entity to be
|
||||
able to stream. There could be temporary reasons (e.g. device
|
||||
configuration dependent) for the pad to need enabled links even
|
||||
when this flag isn't set; the absence of the flag doesn't imply
|
||||
there is none.
|
||||
- If this flag is set, then for this pad to be able to stream, it must
|
||||
be connected by at least one enabled link. There could be temporary
|
||||
reasons (e.g. device configuration dependent) for the pad to need
|
||||
enabled links even when this flag isn't set; the absence of the flag
|
||||
doesn't imply there is none.
|
||||
|
||||
|
||||
One and only one of ``MEDIA_PAD_FL_SINK`` and ``MEDIA_PAD_FL_SOURCE``
|
||||
|
||||
@@ -87,14 +87,14 @@ The state of SME in the Linux kernel can be documented as follows:
|
||||
kernel is non-zero).
|
||||
|
||||
SME can also be enabled and activated in the BIOS. If SME is enabled and
|
||||
activated in the BIOS, then all memory accesses will be encrypted and it will
|
||||
not be necessary to activate the Linux memory encryption support. If the BIOS
|
||||
merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG), then Linux can activate
|
||||
memory encryption by default (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y) or
|
||||
by supplying mem_encrypt=on on the kernel command line. However, if BIOS does
|
||||
not enable SME, then Linux will not be able to activate memory encryption, even
|
||||
if configured to do so by default or the mem_encrypt=on command line parameter
|
||||
is specified.
|
||||
activated in the BIOS, then all memory accesses will be encrypted and it
|
||||
will not be necessary to activate the Linux memory encryption support.
|
||||
|
||||
If the BIOS merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG),
|
||||
then memory encryption can be enabled by supplying mem_encrypt=on on the
|
||||
kernel command line. However, if BIOS does not enable SME, then Linux
|
||||
will not be able to activate memory encryption, even if configured to do
|
||||
so by default or the mem_encrypt=on command line parameter is specified.
|
||||
|
||||
Secure Nested Paging (SNP)
|
||||
==========================
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 83
|
||||
SUBLEVEL = 84
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
&twsi1 {
|
||||
status = "okay";
|
||||
pmic: max8925@3c {
|
||||
compatible = "maxium,max8925";
|
||||
compatible = "maxim,max8925";
|
||||
reg = <0x3c>;
|
||||
interrupts = <1>;
|
||||
interrupt-parent = <&intcmux4>;
|
||||
|
||||
@@ -2028,8 +2028,16 @@
|
||||
ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
|
||||
<0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
|
||||
|
||||
interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "msi";
|
||||
interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "msi0", "msi1", "msi2", "msi3",
|
||||
"msi4", "msi5", "msi6", "msi7";
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0x7>;
|
||||
interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
||||
@@ -64,6 +64,7 @@ SECTIONS
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
ELF_DETAILS
|
||||
.hexagon.attributes 0 : { *(.hexagon.attributes) }
|
||||
|
||||
DISCARDS
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t
|
||||
#define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l))
|
||||
#define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l))
|
||||
|
||||
#define __io_aw() mmiowb()
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||
|
||||
@@ -25,7 +25,12 @@ static inline void set_my_cpu_offset(unsigned long off)
|
||||
__my_cpu_offset = off;
|
||||
csr_write64(off, PERCPU_BASE_KS);
|
||||
}
|
||||
#define __my_cpu_offset __my_cpu_offset
|
||||
|
||||
#define __my_cpu_offset \
|
||||
({ \
|
||||
__asm__ __volatile__("":"+r"(__my_cpu_offset)); \
|
||||
__my_cpu_offset; \
|
||||
})
|
||||
|
||||
#define PERCPU_OP(op, asm_op, c_op) \
|
||||
static __always_inline unsigned long __percpu_##op(void *ptr, \
|
||||
|
||||
@@ -97,26 +97,28 @@
|
||||
* version takes two arguments: a src and destination register.
|
||||
* However, the source and destination registers can not be
|
||||
* the same register.
|
||||
*
|
||||
* We use add,l to avoid clobbering the C/B bits in the PSW.
|
||||
*/
|
||||
|
||||
.macro tophys grvirt, grphys
|
||||
ldil L%(__PAGE_OFFSET), \grphys
|
||||
sub \grvirt, \grphys, \grphys
|
||||
ldil L%(-__PAGE_OFFSET), \grphys
|
||||
addl \grvirt, \grphys, \grphys
|
||||
.endm
|
||||
|
||||
|
||||
.macro tovirt grphys, grvirt
|
||||
ldil L%(__PAGE_OFFSET), \grvirt
|
||||
add \grphys, \grvirt, \grvirt
|
||||
addl \grphys, \grvirt, \grvirt
|
||||
.endm
|
||||
|
||||
.macro tophys_r1 gr
|
||||
ldil L%(__PAGE_OFFSET), %r1
|
||||
sub \gr, %r1, \gr
|
||||
ldil L%(-__PAGE_OFFSET), %r1
|
||||
addl \gr, %r1, \gr
|
||||
.endm
|
||||
|
||||
|
||||
.macro tovirt_r1 gr
|
||||
ldil L%(__PAGE_OFFSET), %r1
|
||||
add \gr, %r1, \gr
|
||||
addl \gr, %r1, \gr
|
||||
.endm
|
||||
|
||||
.macro delay value
|
||||
|
||||
@@ -40,7 +40,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||
" addc %0, %5, %0\n"
|
||||
" addc %0, %3, %0\n"
|
||||
"1: ldws,ma 4(%1), %3\n"
|
||||
" addib,< 0, %2, 1b\n"
|
||||
" addib,> -1, %2, 1b\n"
|
||||
" addc %0, %3, %0\n"
|
||||
"\n"
|
||||
" extru %0, 31, 16, %4\n"
|
||||
@@ -126,6 +126,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||
** Try to keep 4 registers with "live" values ahead of the ALU.
|
||||
*/
|
||||
|
||||
" depdi 0, 31, 32, %0\n"/* clear upper half of incoming checksum */
|
||||
" ldd,ma 8(%1), %4\n" /* get 1st saddr word */
|
||||
" ldd,ma 8(%2), %5\n" /* get 1st daddr word */
|
||||
" add %4, %0, %0\n"
|
||||
@@ -137,8 +138,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||
" add,dc %3, %0, %0\n" /* fold in proto+len | carry bit */
|
||||
" extrd,u %0, 31, 32, %4\n"/* copy upper half down */
|
||||
" depdi 0, 31, 32, %0\n"/* clear upper half */
|
||||
" add %4, %0, %0\n" /* fold into 32-bits */
|
||||
" addc 0, %0, %0\n" /* add carry */
|
||||
" add,dc %4, %0, %0\n" /* fold into 32-bits, plus carry */
|
||||
" addc 0, %0, %0\n" /* add final carry */
|
||||
|
||||
#else
|
||||
|
||||
@@ -163,7 +164,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||
" ldw,ma 4(%2), %7\n" /* 4th daddr */
|
||||
" addc %6, %0, %0\n"
|
||||
" addc %7, %0, %0\n"
|
||||
" addc %3, %0, %0\n" /* fold in proto+len, catch carry */
|
||||
" addc %3, %0, %0\n" /* fold in proto+len */
|
||||
" addc 0, %0, %0\n" /* add carry */
|
||||
|
||||
#endif
|
||||
: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len),
|
||||
|
||||
@@ -167,6 +167,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
|
||||
static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
|
||||
{
|
||||
unsigned long saddr = regs->ior;
|
||||
unsigned long shift, temp1;
|
||||
__u64 val = 0;
|
||||
ASM_EXCEPTIONTABLE_VAR(ret);
|
||||
|
||||
@@ -178,25 +179,22 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
__asm__ __volatile__ (
|
||||
" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */
|
||||
" mtsp %4, %%sr1\n"
|
||||
" depd %%r0,63,3,%3\n"
|
||||
"1: ldd 0(%%sr1,%3),%0\n"
|
||||
"2: ldd 8(%%sr1,%3),%%r20\n"
|
||||
" subi 64,%%r19,%%r19\n"
|
||||
" mtsar %%r19\n"
|
||||
" shrpd %0,%%r20,%%sar,%0\n"
|
||||
" depd,z %2,60,3,%3\n" /* shift=(ofs&7)*8 */
|
||||
" mtsp %5, %%sr1\n"
|
||||
" depd %%r0,63,3,%2\n"
|
||||
"1: ldd 0(%%sr1,%2),%0\n"
|
||||
"2: ldd 8(%%sr1,%2),%4\n"
|
||||
" subi 64,%3,%3\n"
|
||||
" mtsar %3\n"
|
||||
" shrpd %0,%4,%%sar,%0\n"
|
||||
"3: \n"
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1")
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1")
|
||||
: "=r" (val), "+r" (ret)
|
||||
: "0" (val), "r" (saddr), "r" (regs->isr)
|
||||
: "r19", "r20" );
|
||||
: "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
|
||||
: "r" (regs->isr) );
|
||||
#else
|
||||
{
|
||||
unsigned long shift, temp1;
|
||||
__asm__ __volatile__ (
|
||||
" zdep %2,29,2,%3\n" /* r19=(ofs&3)*8 */
|
||||
" zdep %2,29,2,%3\n" /* shift=(ofs&3)*8 */
|
||||
" mtsp %5, %%sr1\n"
|
||||
" dep %%r0,31,2,%2\n"
|
||||
"1: ldw 0(%%sr1,%2),%0\n"
|
||||
@@ -212,7 +210,6 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 4b, "%1")
|
||||
: "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
|
||||
: "r" (regs->isr) );
|
||||
}
|
||||
#endif
|
||||
|
||||
DPRINTF("val = 0x%llx\n", val);
|
||||
|
||||
@@ -12,9 +12,16 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
/* Performance Monitor Registers */
|
||||
#define mfpmr(rn) ({unsigned int rval; \
|
||||
asm volatile("mfpmr %0," __stringify(rn) \
|
||||
asm volatile(".machine push; " \
|
||||
".machine e300; " \
|
||||
"mfpmr %0," __stringify(rn) ";" \
|
||||
".machine pop; " \
|
||||
: "=r" (rval)); rval;})
|
||||
#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
|
||||
#define mtpmr(rn, v) asm volatile(".machine push; " \
|
||||
".machine e300; " \
|
||||
"mtpmr " __stringify(rn) ",%0; " \
|
||||
".machine pop; " \
|
||||
: : "r" (v))
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/* Freescale Book E Performance Monitor APU Registers */
|
||||
|
||||
@@ -369,6 +369,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
||||
if (IS_ENABLED(CONFIG_PPC64))
|
||||
boot_cpu_hwid = be32_to_cpu(intserv[found_thread]);
|
||||
|
||||
if (nr_cpu_ids % nthreads != 0) {
|
||||
set_nr_cpu_ids(ALIGN(nr_cpu_ids, nthreads));
|
||||
pr_warn("nr_cpu_ids was not a multiple of threads_per_core, adjusted to %d\n",
|
||||
nr_cpu_ids);
|
||||
}
|
||||
|
||||
if (boot_cpuid >= nr_cpu_ids) {
|
||||
set_nr_cpu_ids(min(CONFIG_NR_CPUS, ALIGN(boot_cpuid + 1, nthreads)));
|
||||
pr_warn("Boot CPU %d >= nr_cpu_ids, adjusted nr_cpu_ids to %d\n",
|
||||
boot_cpuid, nr_cpu_ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* PAPR defines "logical" PVR values for cpus that
|
||||
* meet various levels of the architecture:
|
||||
|
||||
@@ -72,7 +72,7 @@ obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
|
||||
obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o
|
||||
|
||||
obj-$(CONFIG_ALTIVEC) += xor_vmx.o xor_vmx_glue.o
|
||||
CFLAGS_xor_vmx.o += -maltivec $(call cc-option,-mabi=altivec)
|
||||
CFLAGS_xor_vmx.o += -mhard-float -maltivec $(call cc-option,-mabi=altivec)
|
||||
# Enable <altivec.h>
|
||||
CFLAGS_xor_vmx.o += -isystem $(shell $(CC) -print-file-name=include)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
/* This is a dummy device table linked into all of the crypto
|
||||
* opcode drivers. It serves to trigger the module autoloading
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define __ASM_SPARC_FLOPPY_H
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
#include <asm/idprom.h>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define __ASM_SPARC64_FLOPPY_H
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/auxio.h>
|
||||
|
||||
@@ -1,255 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* parport.h: sparc64 specific parport initialization and dma.
|
||||
*
|
||||
* Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
|
||||
*/
|
||||
#ifndef ___ASM_SPARC_PARPORT_H
|
||||
#define ___ASM_SPARC_PARPORT_H
|
||||
|
||||
#ifndef _ASM_SPARC64_PARPORT_H
|
||||
#define _ASM_SPARC64_PARPORT_H 1
|
||||
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <asm/ebus_dma.h>
|
||||
#include <asm/ns87303.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#define PARPORT_PC_MAX_PORTS PARPORT_MAX
|
||||
|
||||
/*
|
||||
* While sparc64 doesn't have an ISA DMA API, we provide something that looks
|
||||
* close enough to make parport_pc happy
|
||||
*/
|
||||
#define HAS_DMA
|
||||
|
||||
#ifdef CONFIG_PARPORT_PC_FIFO
|
||||
static DEFINE_SPINLOCK(dma_spin_lock);
|
||||
|
||||
#define claim_dma_lock() \
|
||||
({ unsigned long flags; \
|
||||
spin_lock_irqsave(&dma_spin_lock, flags); \
|
||||
flags; \
|
||||
})
|
||||
|
||||
#define release_dma_lock(__flags) \
|
||||
spin_unlock_irqrestore(&dma_spin_lock, __flags);
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/parport_64.h>
|
||||
#else
|
||||
#include <asm-generic/parport.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static struct sparc_ebus_info {
|
||||
struct ebus_dma_info info;
|
||||
unsigned int addr;
|
||||
unsigned int count;
|
||||
int lock;
|
||||
|
||||
struct parport *port;
|
||||
} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
|
||||
|
||||
static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
|
||||
|
||||
static inline int request_dma(unsigned int dmanr, const char *device_id)
|
||||
{
|
||||
if (dmanr >= PARPORT_PC_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void free_dma(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr >= PARPORT_PC_MAX_PORTS) {
|
||||
printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
|
||||
printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
|
||||
|
||||
if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
|
||||
sparc_ebus_dmas[dmanr].addr,
|
||||
sparc_ebus_dmas[dmanr].count))
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
|
||||
}
|
||||
|
||||
static inline void clear_dma_ff(unsigned int dmanr)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
static inline void set_dma_mode(unsigned int dmanr, char mode)
|
||||
{
|
||||
ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
|
||||
}
|
||||
|
||||
static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
|
||||
{
|
||||
sparc_ebus_dmas[dmanr].addr = addr;
|
||||
}
|
||||
|
||||
static inline void set_dma_count(unsigned int dmanr, unsigned int count)
|
||||
{
|
||||
sparc_ebus_dmas[dmanr].count = count;
|
||||
}
|
||||
|
||||
static inline unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
|
||||
}
|
||||
|
||||
static int ecpp_probe(struct platform_device *op)
|
||||
{
|
||||
unsigned long base = op->resource[0].start;
|
||||
unsigned long config = op->resource[1].start;
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
struct device_node *parent;
|
||||
struct parport *p;
|
||||
int slot, err;
|
||||
|
||||
parent = op->dev.of_node->parent;
|
||||
if (of_node_name_eq(parent, "dma")) {
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
|
||||
op->dev.parent->parent, 0);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
|
||||
if (!test_and_set_bit(slot, dma_slot_map))
|
||||
break;
|
||||
}
|
||||
err = -ENODEV;
|
||||
if (slot >= PARPORT_PC_MAX_PORTS)
|
||||
goto out_err;
|
||||
|
||||
spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
sparc_ebus_dmas[slot].info.regs =
|
||||
of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
|
||||
|
||||
if (!sparc_ebus_dmas[slot].info.regs)
|
||||
goto out_clear_map;
|
||||
|
||||
sparc_ebus_dmas[slot].info.flags = 0;
|
||||
sparc_ebus_dmas[slot].info.callback = NULL;
|
||||
sparc_ebus_dmas[slot].info.client_cookie = NULL;
|
||||
sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
|
||||
strcpy(sparc_ebus_dmas[slot].info.name, "parport");
|
||||
if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
|
||||
goto out_unmap_regs;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
|
||||
|
||||
/* Configure IRQ to Push Pull, Level Low */
|
||||
/* Enable ECP, set bit 2 of the CTR first */
|
||||
outb(0x04, base + 0x02);
|
||||
ns87303_modify(config, PCR,
|
||||
PCR_EPP_ENABLE |
|
||||
PCR_IRQ_ODRAIN,
|
||||
PCR_ECP_ENABLE |
|
||||
PCR_ECP_CLK_ENA |
|
||||
PCR_IRQ_POLAR);
|
||||
|
||||
/* CTR bit 5 controls direction of port */
|
||||
ns87303_modify(config, PTR,
|
||||
0, PTR_LPT_REG_DIR);
|
||||
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->archdata.irqs[0],
|
||||
slot,
|
||||
op->dev.parent,
|
||||
0);
|
||||
err = -ENOMEM;
|
||||
if (!p)
|
||||
goto out_disable_irq;
|
||||
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_irq:
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
|
||||
|
||||
out_clear_map:
|
||||
clear_bit(slot, dma_slot_map);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ecpp_remove(struct platform_device *op)
|
||||
{
|
||||
struct parport *p = dev_get_drvdata(&op->dev);
|
||||
int slot = p->dma;
|
||||
|
||||
parport_pc_unregister_port(p);
|
||||
|
||||
if (slot != PARPORT_DMA_NOFIFO) {
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
of_iounmap(&op->resource[2],
|
||||
sparc_ebus_dmas[slot].info.regs,
|
||||
d_len);
|
||||
clear_bit(slot, dma_slot_map);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ecpp_match[] = {
|
||||
{
|
||||
.name = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ns87317-ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "pnpALI,1533,3",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver ecpp_driver = {
|
||||
.driver = {
|
||||
.name = "ecpp",
|
||||
.of_match_table = ecpp_match,
|
||||
},
|
||||
.probe = ecpp_probe,
|
||||
.remove = ecpp_remove,
|
||||
};
|
||||
|
||||
static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
|
||||
{
|
||||
return platform_driver_register(&ecpp_driver);
|
||||
}
|
||||
|
||||
#endif /* !(_ASM_SPARC64_PARPORT_H */
|
||||
|
||||
256
arch/sparc/include/asm/parport_64.h
Normal file
256
arch/sparc/include/asm/parport_64.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* parport.h: sparc64 specific parport initialization and dma.
|
||||
*
|
||||
* Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
|
||||
*/
|
||||
|
||||
#ifndef _ASM_SPARC64_PARPORT_H
|
||||
#define _ASM_SPARC64_PARPORT_H 1
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/ebus_dma.h>
|
||||
#include <asm/ns87303.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#define PARPORT_PC_MAX_PORTS PARPORT_MAX
|
||||
|
||||
/*
|
||||
* While sparc64 doesn't have an ISA DMA API, we provide something that looks
|
||||
* close enough to make parport_pc happy
|
||||
*/
|
||||
#define HAS_DMA
|
||||
|
||||
#ifdef CONFIG_PARPORT_PC_FIFO
|
||||
static DEFINE_SPINLOCK(dma_spin_lock);
|
||||
|
||||
#define claim_dma_lock() \
|
||||
({ unsigned long flags; \
|
||||
spin_lock_irqsave(&dma_spin_lock, flags); \
|
||||
flags; \
|
||||
})
|
||||
|
||||
#define release_dma_lock(__flags) \
|
||||
spin_unlock_irqrestore(&dma_spin_lock, __flags);
|
||||
#endif
|
||||
|
||||
static struct sparc_ebus_info {
|
||||
struct ebus_dma_info info;
|
||||
unsigned int addr;
|
||||
unsigned int count;
|
||||
int lock;
|
||||
|
||||
struct parport *port;
|
||||
} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
|
||||
|
||||
static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
|
||||
|
||||
static inline int request_dma(unsigned int dmanr, const char *device_id)
|
||||
{
|
||||
if (dmanr >= PARPORT_PC_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void free_dma(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr >= PARPORT_PC_MAX_PORTS) {
|
||||
printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
|
||||
printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
|
||||
|
||||
if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
|
||||
sparc_ebus_dmas[dmanr].addr,
|
||||
sparc_ebus_dmas[dmanr].count))
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
|
||||
}
|
||||
|
||||
static inline void clear_dma_ff(unsigned int dmanr)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
static inline void set_dma_mode(unsigned int dmanr, char mode)
|
||||
{
|
||||
ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
|
||||
}
|
||||
|
||||
static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
|
||||
{
|
||||
sparc_ebus_dmas[dmanr].addr = addr;
|
||||
}
|
||||
|
||||
static inline void set_dma_count(unsigned int dmanr, unsigned int count)
|
||||
{
|
||||
sparc_ebus_dmas[dmanr].count = count;
|
||||
}
|
||||
|
||||
static inline unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
|
||||
}
|
||||
|
||||
static int ecpp_probe(struct platform_device *op)
|
||||
{
|
||||
unsigned long base = op->resource[0].start;
|
||||
unsigned long config = op->resource[1].start;
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
struct device_node *parent;
|
||||
struct parport *p;
|
||||
int slot, err;
|
||||
|
||||
parent = op->dev.of_node->parent;
|
||||
if (of_node_name_eq(parent, "dma")) {
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
|
||||
op->dev.parent->parent, 0);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
|
||||
if (!test_and_set_bit(slot, dma_slot_map))
|
||||
break;
|
||||
}
|
||||
err = -ENODEV;
|
||||
if (slot >= PARPORT_PC_MAX_PORTS)
|
||||
goto out_err;
|
||||
|
||||
spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
sparc_ebus_dmas[slot].info.regs =
|
||||
of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
|
||||
|
||||
if (!sparc_ebus_dmas[slot].info.regs)
|
||||
goto out_clear_map;
|
||||
|
||||
sparc_ebus_dmas[slot].info.flags = 0;
|
||||
sparc_ebus_dmas[slot].info.callback = NULL;
|
||||
sparc_ebus_dmas[slot].info.client_cookie = NULL;
|
||||
sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
|
||||
strcpy(sparc_ebus_dmas[slot].info.name, "parport");
|
||||
if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
|
||||
goto out_unmap_regs;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
|
||||
|
||||
/* Configure IRQ to Push Pull, Level Low */
|
||||
/* Enable ECP, set bit 2 of the CTR first */
|
||||
outb(0x04, base + 0x02);
|
||||
ns87303_modify(config, PCR,
|
||||
PCR_EPP_ENABLE |
|
||||
PCR_IRQ_ODRAIN,
|
||||
PCR_ECP_ENABLE |
|
||||
PCR_ECP_CLK_ENA |
|
||||
PCR_IRQ_POLAR);
|
||||
|
||||
/* CTR bit 5 controls direction of port */
|
||||
ns87303_modify(config, PTR,
|
||||
0, PTR_LPT_REG_DIR);
|
||||
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->archdata.irqs[0],
|
||||
slot,
|
||||
op->dev.parent,
|
||||
0);
|
||||
err = -ENOMEM;
|
||||
if (!p)
|
||||
goto out_disable_irq;
|
||||
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_irq:
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
|
||||
|
||||
out_clear_map:
|
||||
clear_bit(slot, dma_slot_map);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ecpp_remove(struct platform_device *op)
|
||||
{
|
||||
struct parport *p = dev_get_drvdata(&op->dev);
|
||||
int slot = p->dma;
|
||||
|
||||
parport_pc_unregister_port(p);
|
||||
|
||||
if (slot != PARPORT_DMA_NOFIFO) {
|
||||
unsigned long d_base = op->resource[2].start;
|
||||
unsigned long d_len;
|
||||
|
||||
d_len = (op->resource[2].end - d_base) + 1UL;
|
||||
|
||||
ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
|
||||
ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
|
||||
of_iounmap(&op->resource[2],
|
||||
sparc_ebus_dmas[slot].info.regs,
|
||||
d_len);
|
||||
clear_bit(slot, dma_slot_map);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ecpp_match[] = {
|
||||
{
|
||||
.name = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "ns87317-ecpp",
|
||||
},
|
||||
{
|
||||
.name = "parallel",
|
||||
.compatible = "pnpALI,1533,3",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver ecpp_driver = {
|
||||
.driver = {
|
||||
.name = "ecpp",
|
||||
.of_match_table = ecpp_match,
|
||||
},
|
||||
.probe = ecpp_probe,
|
||||
.remove = ecpp_remove,
|
||||
};
|
||||
|
||||
static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
|
||||
{
|
||||
return platform_driver_register(&ecpp_driver);
|
||||
}
|
||||
|
||||
#endif /* !(_ASM_SPARC64_PARPORT_H */
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/fhc.h>
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/spitfire.h>
|
||||
#include <asm/chmctrl.h>
|
||||
#include <asm/cpudata.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/vaddrs.h>
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
* Code is partially derived from pcic.c
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
* Contributors: Daniel Hellstrom <daniel@gaisler.com>
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/leon.h>
|
||||
#include <asm/vaddrs.h>
|
||||
|
||||
@@ -274,7 +274,7 @@ static int __init setup_nmi_watchdog(char *str)
|
||||
if (!strncmp(str, "panic", 5))
|
||||
panic_on_timeout = 1;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
__setup("nmi_watchdog=", setup_nmi_watchdog);
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/leon.h>
|
||||
#include <asm/leon_amba.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
@@ -9,8 +8,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/spitfire.h>
|
||||
|
||||
#include "of_device_common.h"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "of_device_common.h"
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/oplib.h>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <linux/msi.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/numa.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/iommu.h>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include <linux/msi.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <asm/iommu-common.h>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/numa.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/upa.h>
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/numa.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/mc146818rtc.h>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/io-unit.h>
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
|
||||
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mxcc.h>
|
||||
|
||||
@@ -449,9 +449,8 @@ static __init int vdso_setup(char *s)
|
||||
unsigned long val;
|
||||
|
||||
err = kstrtoul(s, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
vdso_enabled = val;
|
||||
return 0;
|
||||
if (!err)
|
||||
vdso_enabled = val;
|
||||
return 1;
|
||||
}
|
||||
__setup("vdso=", vdso_setup);
|
||||
|
||||
@@ -1553,19 +1553,6 @@ config AMD_MEM_ENCRYPT
|
||||
This requires an AMD processor that supports Secure Memory
|
||||
Encryption (SME).
|
||||
|
||||
config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
|
||||
bool "Activate AMD Secure Memory Encryption (SME) by default"
|
||||
depends on AMD_MEM_ENCRYPT
|
||||
help
|
||||
Say yes to have system memory encrypted by default if running on
|
||||
an AMD processor that supports Secure Memory Encryption (SME).
|
||||
|
||||
If set to Y, then the encryption of system memory can be
|
||||
deactivated with the mem_encrypt=off command line option.
|
||||
|
||||
If set to N, then the encryption of system memory can be
|
||||
activated with the mem_encrypt=on command line option.
|
||||
|
||||
# Common NUMA Features
|
||||
config NUMA
|
||||
bool "NUMA Memory Allocation and Scheduler Support"
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/page_types.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
.code64
|
||||
.text
|
||||
@@ -49,6 +51,11 @@ SYM_FUNC_START(startup_64_mixed_mode)
|
||||
lea efi32_boot_args(%rip), %rdx
|
||||
mov 0(%rdx), %edi
|
||||
mov 4(%rdx), %esi
|
||||
|
||||
/* Switch to the firmware's stack */
|
||||
movl efi32_boot_sp(%rip), %esp
|
||||
andl $~7, %esp
|
||||
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
mov 8(%rdx), %edx // saved bootparams pointer
|
||||
test %edx, %edx
|
||||
@@ -150,6 +157,7 @@ SYM_FUNC_END(__efi64_thunk)
|
||||
SYM_FUNC_START(efi32_stub_entry)
|
||||
call 1f
|
||||
1: popl %ecx
|
||||
leal (efi32_boot_args - 1b)(%ecx), %ebx
|
||||
|
||||
/* Clear BSS */
|
||||
xorl %eax, %eax
|
||||
@@ -164,6 +172,7 @@ SYM_FUNC_START(efi32_stub_entry)
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
movl %esi, 8(%ebx)
|
||||
jmp efi32_entry
|
||||
SYM_FUNC_END(efi32_stub_entry)
|
||||
#endif
|
||||
@@ -240,8 +249,6 @@ SYM_FUNC_END(efi_enter32)
|
||||
*
|
||||
* Arguments: %ecx image handle
|
||||
* %edx EFI system table pointer
|
||||
* %esi struct bootparams pointer (or NULL when not using
|
||||
* the EFI handover protocol)
|
||||
*
|
||||
* Since this is the point of no return for ordinary execution, no registers
|
||||
* are considered live except for the function parameters. [Note that the EFI
|
||||
@@ -260,13 +267,25 @@ SYM_FUNC_START_LOCAL(efi32_entry)
|
||||
/* Store firmware IDT descriptor */
|
||||
sidtl (efi32_boot_idt - 1b)(%ebx)
|
||||
|
||||
/* Store firmware stack pointer */
|
||||
movl %esp, (efi32_boot_sp - 1b)(%ebx)
|
||||
|
||||
/* Store boot arguments */
|
||||
leal (efi32_boot_args - 1b)(%ebx), %ebx
|
||||
movl %ecx, 0(%ebx)
|
||||
movl %edx, 4(%ebx)
|
||||
movl %esi, 8(%ebx)
|
||||
movb $0x0, 12(%ebx) // efi_is64
|
||||
|
||||
/*
|
||||
* Allocate some memory for a temporary struct boot_params, which only
|
||||
* needs the minimal pieces that startup_32() relies on.
|
||||
*/
|
||||
subl $PARAM_SIZE, %esp
|
||||
movl %esp, %esi
|
||||
movl $PAGE_SIZE, BP_kernel_alignment(%esi)
|
||||
movl $_end - 1b, BP_init_size(%esi)
|
||||
subl $startup_32 - 1b, BP_init_size(%esi)
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
@@ -292,8 +311,7 @@ SYM_FUNC_START(efi32_pe_entry)
|
||||
|
||||
movl 8(%ebp), %ecx // image_handle
|
||||
movl 12(%ebp), %edx // sys_table
|
||||
xorl %esi, %esi
|
||||
jmp efi32_entry // pass %ecx, %edx, %esi
|
||||
jmp efi32_entry // pass %ecx, %edx
|
||||
// no other registers remain live
|
||||
|
||||
2: popl %edi // restore callee-save registers
|
||||
@@ -324,5 +342,6 @@ SYM_DATA_END(efi32_boot_idt)
|
||||
|
||||
SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_sp, .long 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
|
||||
SYM_DATA(efi_is64, .byte 1)
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <asm/coco.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
static enum cc_vendor vendor __ro_after_init;
|
||||
static u64 cc_mask __ro_after_init;
|
||||
enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE;
|
||||
u64 cc_mask __ro_after_init;
|
||||
|
||||
static bool intel_cc_platform_has(enum cc_attr attr)
|
||||
{
|
||||
@@ -83,7 +83,7 @@ static bool hyperv_cc_platform_has(enum cc_attr attr)
|
||||
|
||||
bool cc_platform_has(enum cc_attr attr)
|
||||
{
|
||||
switch (vendor) {
|
||||
switch (cc_vendor) {
|
||||
case CC_VENDOR_AMD:
|
||||
return amd_cc_platform_has(attr);
|
||||
case CC_VENDOR_INTEL:
|
||||
@@ -105,7 +105,7 @@ u64 cc_mkenc(u64 val)
|
||||
* - for AMD, bit *set* means the page is encrypted
|
||||
* - for Intel *clear* means encrypted.
|
||||
*/
|
||||
switch (vendor) {
|
||||
switch (cc_vendor) {
|
||||
case CC_VENDOR_AMD:
|
||||
return val | cc_mask;
|
||||
case CC_VENDOR_INTEL:
|
||||
@@ -118,7 +118,7 @@ u64 cc_mkenc(u64 val)
|
||||
u64 cc_mkdec(u64 val)
|
||||
{
|
||||
/* See comment in cc_mkenc() */
|
||||
switch (vendor) {
|
||||
switch (cc_vendor) {
|
||||
case CC_VENDOR_AMD:
|
||||
return val & ~cc_mask;
|
||||
case CC_VENDOR_INTEL:
|
||||
@@ -128,13 +128,3 @@ u64 cc_mkdec(u64 val)
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cc_mkdec);
|
||||
|
||||
__init void cc_set_vendor(enum cc_vendor v)
|
||||
{
|
||||
vendor = v;
|
||||
}
|
||||
|
||||
__init void cc_set_mask(u64 mask)
|
||||
{
|
||||
cc_mask = mask;
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ void __init tdx_early_init(void)
|
||||
|
||||
setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);
|
||||
|
||||
cc_set_vendor(CC_VENDOR_INTEL);
|
||||
cc_vendor = CC_VENDOR_INTEL;
|
||||
tdx_parse_tdinfo(&cc_mask);
|
||||
cc_set_mask(cc_mask);
|
||||
|
||||
|
||||
@@ -113,6 +113,20 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __pic__
|
||||
static __always_inline __pure void *rip_rel_ptr(void *p)
|
||||
{
|
||||
asm("leaq %c1(%%rip), %0" : "=r"(p) : "i"(p));
|
||||
|
||||
return p;
|
||||
}
|
||||
#define RIP_REL_REF(var) (*(typeof(&(var)))rip_rel_ptr(&(var)))
|
||||
#else
|
||||
#define RIP_REL_REF(var) (var)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to generate condition code outputs from inline assembly,
|
||||
* The output operand must be type "bool".
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef _ASM_X86_COCO_H
|
||||
#define _ASM_X86_COCO_H
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
enum cc_vendor {
|
||||
@@ -11,10 +12,15 @@ enum cc_vendor {
|
||||
CC_VENDOR_INTEL,
|
||||
};
|
||||
|
||||
void cc_set_vendor(enum cc_vendor v);
|
||||
void cc_set_mask(u64 mask);
|
||||
extern enum cc_vendor cc_vendor;
|
||||
extern u64 cc_mask;
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
|
||||
static inline void cc_set_mask(u64 mask)
|
||||
{
|
||||
RIP_REL_REF(cc_mask) = mask;
|
||||
}
|
||||
|
||||
u64 cc_mkenc(u64 val);
|
||||
u64 cc_mkdec(u64 val);
|
||||
#else
|
||||
|
||||
@@ -427,6 +427,7 @@
|
||||
#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */
|
||||
#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
|
||||
|
||||
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
|
||||
#define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */
|
||||
#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
|
||||
#define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/cc_platform.h>
|
||||
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/asm.h>
|
||||
struct boot_params;
|
||||
|
||||
#ifdef CONFIG_X86_MEM_ENCRYPT
|
||||
void __init mem_encrypt_init(void);
|
||||
@@ -57,6 +58,11 @@ void __init mem_encrypt_free_decrypted_mem(void);
|
||||
|
||||
void __init sev_es_init_vc_handling(void);
|
||||
|
||||
static inline u64 sme_get_me_mask(void)
|
||||
{
|
||||
return RIP_REL_REF(sme_me_mask);
|
||||
}
|
||||
|
||||
#define __bss_decrypted __section(".bss..decrypted")
|
||||
|
||||
#else /* !CONFIG_AMD_MEM_ENCRYPT */
|
||||
@@ -88,6 +94,8 @@ early_set_mem_enc_dec_hypercall(unsigned long vaddr, unsigned long size, bool en
|
||||
|
||||
static inline void mem_encrypt_free_decrypted_mem(void) { }
|
||||
|
||||
static inline u64 sme_get_me_mask(void) { return 0; }
|
||||
|
||||
#define __bss_decrypted
|
||||
|
||||
#endif /* CONFIG_AMD_MEM_ENCRYPT */
|
||||
@@ -105,11 +113,6 @@ void add_encrypt_protection_map(void);
|
||||
|
||||
extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[];
|
||||
|
||||
static inline u64 sme_get_me_mask(void)
|
||||
{
|
||||
return sme_me_mask;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __X86_MEM_ENCRYPT_H__ */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#define _EFER_SVME 12 /* Enable virtualization */
|
||||
#define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */
|
||||
#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */
|
||||
#define _EFER_AUTOIBRS 21 /* Enable Automatic IBRS */
|
||||
|
||||
#define EFER_SCE (1<<_EFER_SCE)
|
||||
#define EFER_LME (1<<_EFER_LME)
|
||||
@@ -38,6 +39,7 @@
|
||||
#define EFER_SVME (1<<_EFER_SVME)
|
||||
#define EFER_LMSLE (1<<_EFER_LMSLE)
|
||||
#define EFER_FFXSR (1<<_EFER_FFXSR)
|
||||
#define EFER_AUTOIBRS (1<<_EFER_AUTOIBRS)
|
||||
|
||||
/* Intel MSRs. Some also available on other CPUs */
|
||||
|
||||
|
||||
@@ -196,12 +196,12 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
|
||||
unsigned long npages);
|
||||
void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
|
||||
unsigned long npages);
|
||||
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op);
|
||||
void snp_set_memory_shared(unsigned long vaddr, unsigned long npages);
|
||||
void snp_set_memory_private(unsigned long vaddr, unsigned long npages);
|
||||
void snp_set_wakeup_secondary_cpu(void);
|
||||
bool snp_init(struct boot_params *bp);
|
||||
void __init __noreturn snp_abort(void);
|
||||
void snp_dmi_setup(void);
|
||||
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
|
||||
u64 snp_get_unsupported_features(u64 status);
|
||||
u64 sev_get_status(void);
|
||||
@@ -219,12 +219,12 @@ static inline void __init
|
||||
early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
|
||||
static inline void __init
|
||||
early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
|
||||
static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { }
|
||||
static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { }
|
||||
static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { }
|
||||
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 void snp_dmi_setup(void) { }
|
||||
static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
|
||||
{
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
|
||||
/* image of the saved processor state */
|
||||
struct saved_context {
|
||||
/*
|
||||
* On x86_32, all segment registers except gs are saved at kernel
|
||||
* entry in pt_regs.
|
||||
*/
|
||||
u16 gs;
|
||||
unsigned long cr0, cr2, cr3, cr4;
|
||||
u64 misc_enable;
|
||||
struct saved_msrs saved_msrs;
|
||||
@@ -27,6 +22,11 @@ struct saved_context {
|
||||
unsigned long tr;
|
||||
unsigned long safety;
|
||||
unsigned long return_address;
|
||||
/*
|
||||
* On x86_32, all segment registers except gs are saved at kernel
|
||||
* entry in pt_regs.
|
||||
*/
|
||||
u16 gs;
|
||||
bool misc_enable_saved;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
@@ -30,12 +30,13 @@ struct x86_init_mpparse {
|
||||
* @reserve_resources: reserve the standard resources for the
|
||||
* platform
|
||||
* @memory_setup: platform specific memory setup
|
||||
*
|
||||
* @dmi_setup: platform specific DMI setup
|
||||
*/
|
||||
struct x86_init_resources {
|
||||
void (*probe_roms)(void);
|
||||
void (*reserve_resources)(void);
|
||||
char *(*memory_setup)(void);
|
||||
void (*dmi_setup)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -997,11 +997,11 @@ static bool cpu_has_zenbleed_microcode(void)
|
||||
u32 good_rev = 0;
|
||||
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
|
||||
case 0x60 ... 0x67: good_rev = 0x0860010b; break;
|
||||
case 0x68 ... 0x6f: good_rev = 0x08608105; break;
|
||||
case 0x70 ... 0x7f: good_rev = 0x08701032; break;
|
||||
case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
|
||||
case 0x30 ... 0x3f: good_rev = 0x0830107b; break;
|
||||
case 0x60 ... 0x67: good_rev = 0x0860010c; break;
|
||||
case 0x68 ... 0x6f: good_rev = 0x08608107; break;
|
||||
case 0x70 ... 0x7f: good_rev = 0x08701033; break;
|
||||
case 0xa0 ... 0xaf: good_rev = 0x08a00009; break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -1354,19 +1354,21 @@ spectre_v2_user_select_mitigation(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* If no STIBP, enhanced IBRS is enabled, or SMT impossible, STIBP
|
||||
* If no STIBP, Intel enhanced IBRS is enabled, or SMT impossible, STIBP
|
||||
* is not required.
|
||||
*
|
||||
* Enhanced IBRS also protects against cross-thread branch target
|
||||
* Intel's Enhanced IBRS also protects against cross-thread branch target
|
||||
* injection in user-mode as the IBRS bit remains always set which
|
||||
* implicitly enables cross-thread protections. However, in legacy IBRS
|
||||
* mode, the IBRS bit is set only on kernel entry and cleared on return
|
||||
* to userspace. This disables the implicit cross-thread protection,
|
||||
* so allow for STIBP to be selected in that case.
|
||||
* to userspace. AMD Automatic IBRS also does not protect userspace.
|
||||
* These modes therefore disable the implicit cross-thread protection,
|
||||
* so allow for STIBP to be selected in those cases.
|
||||
*/
|
||||
if (!boot_cpu_has(X86_FEATURE_STIBP) ||
|
||||
!smt_possible ||
|
||||
spectre_v2_in_eibrs_mode(spectre_v2_enabled))
|
||||
(spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
|
||||
!boot_cpu_has(X86_FEATURE_AUTOIBRS)))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1396,9 +1398,9 @@ static const char * const spectre_v2_strings[] = {
|
||||
[SPECTRE_V2_NONE] = "Vulnerable",
|
||||
[SPECTRE_V2_RETPOLINE] = "Mitigation: Retpolines",
|
||||
[SPECTRE_V2_LFENCE] = "Mitigation: LFENCE",
|
||||
[SPECTRE_V2_EIBRS] = "Mitigation: Enhanced IBRS",
|
||||
[SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced IBRS + LFENCE",
|
||||
[SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced IBRS + Retpolines",
|
||||
[SPECTRE_V2_EIBRS] = "Mitigation: Enhanced / Automatic IBRS",
|
||||
[SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced / Automatic IBRS + LFENCE",
|
||||
[SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced / Automatic IBRS + Retpolines",
|
||||
[SPECTRE_V2_IBRS] = "Mitigation: IBRS",
|
||||
};
|
||||
|
||||
@@ -1467,7 +1469,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
||||
cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
|
||||
cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) &&
|
||||
!boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
|
||||
pr_err("%s selected but CPU doesn't have eIBRS. Switching to AUTO select\n",
|
||||
pr_err("%s selected but CPU doesn't have Enhanced or Automatic IBRS. Switching to AUTO select\n",
|
||||
mitigation_options[i].option);
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
}
|
||||
@@ -1652,8 +1654,12 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
|
||||
|
||||
if (spectre_v2_in_ibrs_mode(mode)) {
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
|
||||
update_spec_ctrl(x86_spec_ctrl_base);
|
||||
if (boot_cpu_has(X86_FEATURE_AUTOIBRS)) {
|
||||
msr_set_bit(MSR_EFER, _EFER_AUTOIBRS);
|
||||
} else {
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
|
||||
update_spec_ctrl(x86_spec_ctrl_base);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
@@ -1737,8 +1743,8 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
/*
|
||||
* Retpoline protects the kernel, but doesn't protect firmware. IBRS
|
||||
* and Enhanced IBRS protect firmware too, so enable IBRS around
|
||||
* firmware calls only when IBRS / Enhanced IBRS aren't otherwise
|
||||
* enabled.
|
||||
* firmware calls only when IBRS / Enhanced / Automatic IBRS aren't
|
||||
* otherwise enabled.
|
||||
*
|
||||
* Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
|
||||
* the user might select retpoline on the kernel command line and if
|
||||
@@ -2568,74 +2574,74 @@ static const char * const l1tf_vmx_states[] = {
|
||||
static ssize_t l1tf_show_state(char *buf)
|
||||
{
|
||||
if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO)
|
||||
return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
|
||||
return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
|
||||
|
||||
if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
|
||||
(l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
|
||||
sched_smt_active())) {
|
||||
return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
|
||||
l1tf_vmx_states[l1tf_vmx_mitigation]);
|
||||
return sysfs_emit(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
|
||||
l1tf_vmx_states[l1tf_vmx_mitigation]);
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
|
||||
l1tf_vmx_states[l1tf_vmx_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
return sysfs_emit(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
|
||||
l1tf_vmx_states[l1tf_vmx_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
}
|
||||
|
||||
static ssize_t itlb_multihit_show_state(char *buf)
|
||||
{
|
||||
if (!boot_cpu_has(X86_FEATURE_MSR_IA32_FEAT_CTL) ||
|
||||
!boot_cpu_has(X86_FEATURE_VMX))
|
||||
return sprintf(buf, "KVM: Mitigation: VMX unsupported\n");
|
||||
return sysfs_emit(buf, "KVM: Mitigation: VMX unsupported\n");
|
||||
else if (!(cr4_read_shadow() & X86_CR4_VMXE))
|
||||
return sprintf(buf, "KVM: Mitigation: VMX disabled\n");
|
||||
return sysfs_emit(buf, "KVM: Mitigation: VMX disabled\n");
|
||||
else if (itlb_multihit_kvm_mitigation)
|
||||
return sprintf(buf, "KVM: Mitigation: Split huge pages\n");
|
||||
return sysfs_emit(buf, "KVM: Mitigation: Split huge pages\n");
|
||||
else
|
||||
return sprintf(buf, "KVM: Vulnerable\n");
|
||||
return sysfs_emit(buf, "KVM: Vulnerable\n");
|
||||
}
|
||||
#else
|
||||
static ssize_t l1tf_show_state(char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
|
||||
return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
|
||||
}
|
||||
|
||||
static ssize_t itlb_multihit_show_state(char *buf)
|
||||
{
|
||||
return sprintf(buf, "Processor vulnerable\n");
|
||||
return sysfs_emit(buf, "Processor vulnerable\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t mds_show_state(char *buf)
|
||||
{
|
||||
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
|
||||
return sprintf(buf, "%s; SMT Host state unknown\n",
|
||||
mds_strings[mds_mitigation]);
|
||||
return sysfs_emit(buf, "%s; SMT Host state unknown\n",
|
||||
mds_strings[mds_mitigation]);
|
||||
}
|
||||
|
||||
if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
|
||||
return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
(mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
|
||||
sched_smt_active() ? "mitigated" : "disabled"));
|
||||
return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
(mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
|
||||
sched_smt_active() ? "mitigated" : "disabled"));
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
}
|
||||
|
||||
static ssize_t tsx_async_abort_show_state(char *buf)
|
||||
{
|
||||
if ((taa_mitigation == TAA_MITIGATION_TSX_DISABLED) ||
|
||||
(taa_mitigation == TAA_MITIGATION_OFF))
|
||||
return sprintf(buf, "%s\n", taa_strings[taa_mitigation]);
|
||||
return sysfs_emit(buf, "%s\n", taa_strings[taa_mitigation]);
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
|
||||
return sprintf(buf, "%s; SMT Host state unknown\n",
|
||||
taa_strings[taa_mitigation]);
|
||||
return sysfs_emit(buf, "%s; SMT Host state unknown\n",
|
||||
taa_strings[taa_mitigation]);
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
return sysfs_emit(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
|
||||
sched_smt_active() ? "vulnerable" : "disabled");
|
||||
}
|
||||
|
||||
static ssize_t mmio_stale_data_show_state(char *buf)
|
||||
@@ -2662,7 +2668,8 @@ static ssize_t rfds_show_state(char *buf)
|
||||
|
||||
static char *stibp_state(void)
|
||||
{
|
||||
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
|
||||
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
|
||||
!boot_cpu_has(X86_FEATURE_AUTOIBRS))
|
||||
return "";
|
||||
|
||||
switch (spectre_v2_user_stibp) {
|
||||
@@ -2708,47 +2715,46 @@ static char *pbrsb_eibrs_state(void)
|
||||
static ssize_t spectre_v2_show_state(char *buf)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
|
||||
return sprintf(buf, "Vulnerable: LFENCE\n");
|
||||
return sysfs_emit(buf, "Vulnerable: LFENCE\n");
|
||||
|
||||
if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
|
||||
return sprintf(buf, "Vulnerable: eIBRS with unprivileged eBPF\n");
|
||||
return sysfs_emit(buf, "Vulnerable: eIBRS with unprivileged eBPF\n");
|
||||
|
||||
if (sched_smt_active() && unprivileged_ebpf_enabled() &&
|
||||
spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
|
||||
return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
|
||||
return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
|
||||
|
||||
return sprintf(buf, "%s%s%s%s%s%s%s\n",
|
||||
spectre_v2_strings[spectre_v2_enabled],
|
||||
ibpb_state(),
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
||||
stibp_state(),
|
||||
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
||||
pbrsb_eibrs_state(),
|
||||
spectre_v2_module_string());
|
||||
return sysfs_emit(buf, "%s%s%s%s%s%s%s\n",
|
||||
spectre_v2_strings[spectre_v2_enabled],
|
||||
ibpb_state(),
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
||||
stibp_state(),
|
||||
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
||||
pbrsb_eibrs_state(),
|
||||
spectre_v2_module_string());
|
||||
}
|
||||
|
||||
static ssize_t srbds_show_state(char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
|
||||
return sysfs_emit(buf, "%s\n", srbds_strings[srbds_mitigation]);
|
||||
}
|
||||
|
||||
static ssize_t retbleed_show_state(char *buf)
|
||||
{
|
||||
if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET ||
|
||||
retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
||||
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
||||
return sprintf(buf, "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n");
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
||||
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
||||
return sysfs_emit(buf, "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n");
|
||||
|
||||
return sprintf(buf, "%s; SMT %s\n",
|
||||
retbleed_strings[retbleed_mitigation],
|
||||
!sched_smt_active() ? "disabled" :
|
||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ?
|
||||
"enabled with STIBP protection" : "vulnerable");
|
||||
return sysfs_emit(buf, "%s; SMT %s\n", retbleed_strings[retbleed_mitigation],
|
||||
!sched_smt_active() ? "disabled" :
|
||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ?
|
||||
"enabled with STIBP protection" : "vulnerable");
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
||||
return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
||||
}
|
||||
|
||||
static ssize_t gds_show_state(char *buf)
|
||||
@@ -2770,26 +2776,26 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
||||
char *buf, unsigned int bug)
|
||||
{
|
||||
if (!boot_cpu_has_bug(bug))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
return sysfs_emit(buf, "Not affected\n");
|
||||
|
||||
switch (bug) {
|
||||
case X86_BUG_CPU_MELTDOWN:
|
||||
if (boot_cpu_has(X86_FEATURE_PTI))
|
||||
return sprintf(buf, "Mitigation: PTI\n");
|
||||
return sysfs_emit(buf, "Mitigation: PTI\n");
|
||||
|
||||
if (hypervisor_is_type(X86_HYPER_XEN_PV))
|
||||
return sprintf(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
|
||||
return sysfs_emit(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
|
||||
|
||||
break;
|
||||
|
||||
case X86_BUG_SPECTRE_V1:
|
||||
return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
|
||||
return sysfs_emit(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
|
||||
|
||||
case X86_BUG_SPECTRE_V2:
|
||||
return spectre_v2_show_state(buf);
|
||||
|
||||
case X86_BUG_SPEC_STORE_BYPASS:
|
||||
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
|
||||
return sysfs_emit(buf, "%s\n", ssb_strings[ssb_mode]);
|
||||
|
||||
case X86_BUG_L1TF:
|
||||
if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
|
||||
@@ -2828,7 +2834,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
||||
break;
|
||||
}
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
return sysfs_emit(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
|
||||
@@ -1212,8 +1212,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
||||
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
|
||||
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
|
||||
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
|
||||
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
|
||||
|
||||
/* Zhaoxin Family 7 */
|
||||
VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
|
||||
@@ -1362,8 +1362,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
!cpu_has(c, X86_FEATURE_AMD_SSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
||||
|
||||
if (ia32_cap & ARCH_CAP_IBRS_ALL)
|
||||
/*
|
||||
* AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
|
||||
* flag and protect from vendor-specific bugs via the whitelist.
|
||||
*/
|
||||
if ((ia32_cap & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
||||
!(ia32_cap & ARCH_CAP_PBRSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
||||
}
|
||||
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
|
||||
!(ia32_cap & ARCH_CAP_MDS_NO)) {
|
||||
@@ -1425,11 +1433,6 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
setup_force_cpu_bug(X86_BUG_RETBLEED);
|
||||
}
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_IBRS_ENHANCED) &&
|
||||
!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
||||
!(ia32_cap & ARCH_CAP_PBRSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
||||
|
||||
if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
|
||||
setup_force_cpu_bug(X86_BUG_SMT_RSB);
|
||||
|
||||
|
||||
@@ -344,7 +344,7 @@ static void __init ms_hyperv_init_platform(void)
|
||||
/* 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);
|
||||
cc_vendor = CC_VENDOR_HYPERV;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* EISA specific code
|
||||
*/
|
||||
#include <linux/cc_platform.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/eisa.h>
|
||||
#include <linux/io.h>
|
||||
@@ -12,7 +13,7 @@ static __init int eisa_bus_probe(void)
|
||||
{
|
||||
void __iomem *p;
|
||||
|
||||
if (xen_pv_domain() && !xen_initial_domain())
|
||||
if ((xen_pv_domain() && !xen_initial_domain()) || cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
|
||||
return 0;
|
||||
|
||||
p = ioremap(0x0FFFD9, 4);
|
||||
|
||||
@@ -177,10 +177,11 @@ void fpu__init_cpu_xstate(void)
|
||||
* Must happen after CR4 setup and before xsetbv() to allow KVM
|
||||
* lazy passthrough. Write independent of the dynamic state static
|
||||
* key as that does not work on the boot CPU. This also ensures
|
||||
* that any stale state is wiped out from XFD.
|
||||
* that any stale state is wiped out from XFD. Reset the per CPU
|
||||
* xfd cache too.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_XFD))
|
||||
wrmsrl(MSR_IA32_XFD, init_fpstate.xfd);
|
||||
xfd_set_state(init_fpstate.xfd);
|
||||
|
||||
/*
|
||||
* XCR_XFEATURE_ENABLED_MASK (aka. XCR0) sets user features
|
||||
|
||||
@@ -148,20 +148,26 @@ static inline void xfd_validate_state(struct fpstate *fpstate, u64 mask, bool rs
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static inline void xfd_set_state(u64 xfd)
|
||||
{
|
||||
wrmsrl(MSR_IA32_XFD, xfd);
|
||||
__this_cpu_write(xfd_state, xfd);
|
||||
}
|
||||
|
||||
static inline void xfd_update_state(struct fpstate *fpstate)
|
||||
{
|
||||
if (fpu_state_size_dynamic()) {
|
||||
u64 xfd = fpstate->xfd;
|
||||
|
||||
if (__this_cpu_read(xfd_state) != xfd) {
|
||||
wrmsrl(MSR_IA32_XFD, xfd);
|
||||
__this_cpu_write(xfd_state, xfd);
|
||||
}
|
||||
if (__this_cpu_read(xfd_state) != xfd)
|
||||
xfd_set_state(xfd);
|
||||
}
|
||||
}
|
||||
|
||||
extern int __xfd_enable_feature(u64 which, struct fpu_guest *guest_fpu);
|
||||
#else
|
||||
static inline void xfd_set_state(u64 xfd) { }
|
||||
|
||||
static inline void xfd_update_state(struct fpstate *fpstate) { }
|
||||
|
||||
static inline int __xfd_enable_feature(u64 which, struct fpu_guest *guest_fpu) {
|
||||
|
||||
@@ -301,7 +301,16 @@ static int can_probe(unsigned long paddr)
|
||||
kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
|
||||
bool *on_func_entry)
|
||||
{
|
||||
if (is_endbr(*(u32 *)addr)) {
|
||||
u32 insn;
|
||||
|
||||
/*
|
||||
* Since 'addr' is not guaranteed to be safe to access, use
|
||||
* copy_from_kernel_nofault() to read the instruction:
|
||||
*/
|
||||
if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32)))
|
||||
return NULL;
|
||||
|
||||
if (is_endbr(insn)) {
|
||||
*on_func_entry = !offset || offset == 4;
|
||||
if (*on_func_entry)
|
||||
offset = 4;
|
||||
|
||||
@@ -203,16 +203,6 @@ void __init probe_roms(void)
|
||||
unsigned char c;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The ROM memory range is not part of the e820 table and is therefore not
|
||||
* pre-validated by BIOS. The kernel page table maps the ROM region as encrypted
|
||||
* memory, and SNP requires encrypted memory to be validated before access.
|
||||
* Do that here.
|
||||
*/
|
||||
snp_prep_memory(video_rom_resource.start,
|
||||
((system_rom_resource.end + 1) - video_rom_resource.start),
|
||||
SNP_PAGE_STATE_PRIVATE);
|
||||
|
||||
/* video rom */
|
||||
upper = adapter_rom_resources[0].start;
|
||||
for (start = video_rom_resource.start; start < upper; start += 2048) {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/crash_dump.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/ima.h>
|
||||
#include <linux/init_ohci1394_dma.h>
|
||||
@@ -1032,7 +1031,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (efi_enabled(EFI_BOOT))
|
||||
efi_init();
|
||||
|
||||
dmi_setup();
|
||||
x86_init.resources.dmi_setup();
|
||||
|
||||
/*
|
||||
* VMware detection requires dmi to be available, so this
|
||||
|
||||
@@ -553,9 +553,9 @@ static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_le
|
||||
leaf->eax = leaf->ebx = leaf->ecx = leaf->edx = 0;
|
||||
|
||||
/* Skip post-processing for out-of-range zero leafs. */
|
||||
if (!(leaf->fn <= cpuid_std_range_max ||
|
||||
(leaf->fn >= 0x40000000 && leaf->fn <= cpuid_hyp_range_max) ||
|
||||
(leaf->fn >= 0x80000000 && leaf->fn <= cpuid_ext_range_max)))
|
||||
if (!(leaf->fn <= RIP_REL_REF(cpuid_std_range_max) ||
|
||||
(leaf->fn >= 0x40000000 && leaf->fn <= RIP_REL_REF(cpuid_hyp_range_max)) ||
|
||||
(leaf->fn >= 0x80000000 && leaf->fn <= RIP_REL_REF(cpuid_ext_range_max))))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1060,10 +1060,10 @@ static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
|
||||
const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
|
||||
|
||||
if (fn->eax_in == 0x0)
|
||||
cpuid_std_range_max = fn->eax;
|
||||
RIP_REL_REF(cpuid_std_range_max) = fn->eax;
|
||||
else if (fn->eax_in == 0x40000000)
|
||||
cpuid_hyp_range_max = fn->eax;
|
||||
RIP_REL_REF(cpuid_hyp_range_max) = fn->eax;
|
||||
else if (fn->eax_in == 0x80000000)
|
||||
cpuid_ext_range_max = fn->eax;
|
||||
RIP_REL_REF(cpuid_ext_range_max) = fn->eax;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/psp-sev.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <uapi/linux/sev-guest.h>
|
||||
|
||||
#include <asm/cpu_entry_area.h>
|
||||
@@ -736,7 +737,7 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
|
||||
* This eliminates worries about jump tables or checking boot_cpu_data
|
||||
* in the cc_platform_has() function.
|
||||
*/
|
||||
if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
if (!(RIP_REL_REF(sev_status) & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -758,7 +759,7 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr
|
||||
* This eliminates worries about jump tables or checking boot_cpu_data
|
||||
* in the cc_platform_has() function.
|
||||
*/
|
||||
if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
if (!(RIP_REL_REF(sev_status) & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
return;
|
||||
|
||||
/* Invalidate the memory pages before they are marked shared in the RMP table. */
|
||||
@@ -768,21 +769,6 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr
|
||||
early_set_pages_state(paddr, npages, SNP_PAGE_STATE_SHARED);
|
||||
}
|
||||
|
||||
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op)
|
||||
{
|
||||
unsigned long vaddr, npages;
|
||||
|
||||
vaddr = (unsigned long)__va(paddr);
|
||||
npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
|
||||
|
||||
if (op == SNP_PAGE_STATE_PRIVATE)
|
||||
early_snp_set_memory_private(vaddr, paddr, npages);
|
||||
else if (op == SNP_PAGE_STATE_SHARED)
|
||||
early_snp_set_memory_shared(vaddr, paddr, npages);
|
||||
else
|
||||
WARN(1, "invalid memory op %d\n", op);
|
||||
}
|
||||
|
||||
static int vmgexit_psc(struct snp_psc_desc *desc)
|
||||
{
|
||||
int cur_entry, end_entry, ret = 0;
|
||||
@@ -2152,6 +2138,17 @@ void __init __noreturn snp_abort(void)
|
||||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
|
||||
}
|
||||
|
||||
/*
|
||||
* SEV-SNP guests should only execute dmi_setup() if EFI_CONFIG_TABLES are
|
||||
* enabled, as the alternative (fallback) logic for DMI probing in the legacy
|
||||
* ROM region can cause a crash since this region is not pre-validated.
|
||||
*/
|
||||
void __init snp_dmi_setup(void)
|
||||
{
|
||||
if (efi_enabled(EFI_CONFIG_TABLES))
|
||||
dmi_setup();
|
||||
}
|
||||
|
||||
static void dump_cpuid_table(void)
|
||||
{
|
||||
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* For licencing details see kernel-base/COPYING
|
||||
*/
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/export.h>
|
||||
@@ -66,6 +67,7 @@ struct x86_init_ops x86_init __initdata = {
|
||||
.probe_roms = probe_roms,
|
||||
.reserve_resources = reserve_standard_io_resources,
|
||||
.memory_setup = e820__memory_setup_default,
|
||||
.dmi_setup = dmi_setup,
|
||||
},
|
||||
|
||||
.mpparse = {
|
||||
|
||||
@@ -535,9 +535,9 @@ static __always_inline void __kvm_cpu_cap_mask(unsigned int leaf)
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void kvm_cpu_cap_init_scattered(enum kvm_only_cpuid_leafs leaf, u32 mask)
|
||||
void kvm_cpu_cap_init_kvm_defined(enum kvm_only_cpuid_leafs leaf, u32 mask)
|
||||
{
|
||||
/* Use kvm_cpu_cap_mask for non-scattered leafs. */
|
||||
/* Use kvm_cpu_cap_mask for leafs that aren't KVM-only. */
|
||||
BUILD_BUG_ON(leaf < NCAPINTS);
|
||||
|
||||
kvm_cpu_caps[leaf] = mask;
|
||||
@@ -547,7 +547,7 @@ void kvm_cpu_cap_init_scattered(enum kvm_only_cpuid_leafs leaf, u32 mask)
|
||||
|
||||
static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
|
||||
{
|
||||
/* Use kvm_cpu_cap_init_scattered for scattered leafs. */
|
||||
/* Use kvm_cpu_cap_init_kvm_defined for KVM-only leafs. */
|
||||
BUILD_BUG_ON(leaf >= NCAPINTS);
|
||||
|
||||
kvm_cpu_caps[leaf] &= mask;
|
||||
@@ -652,11 +652,16 @@ void kvm_set_cpu_caps(void)
|
||||
F(AVX_VNNI) | F(AVX512_BF16)
|
||||
);
|
||||
|
||||
kvm_cpu_cap_init_kvm_defined(CPUID_7_2_EDX,
|
||||
F(INTEL_PSFD) | F(IPRED_CTRL) | F(RRSBA_CTRL) | F(DDPD_U) |
|
||||
F(BHI_CTRL) | F(MCDT_NO)
|
||||
);
|
||||
|
||||
kvm_cpu_cap_mask(CPUID_D_1_EAX,
|
||||
F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | F(XSAVES) | f_xfd
|
||||
);
|
||||
|
||||
kvm_cpu_cap_init_scattered(CPUID_12_EAX,
|
||||
kvm_cpu_cap_init_kvm_defined(CPUID_12_EAX,
|
||||
SF(SGX1) | SF(SGX2)
|
||||
);
|
||||
|
||||
@@ -902,13 +907,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
|
||||
break;
|
||||
/* function 7 has additional index. */
|
||||
case 7:
|
||||
entry->eax = min(entry->eax, 1u);
|
||||
max_idx = entry->eax = min(entry->eax, 2u);
|
||||
cpuid_entry_override(entry, CPUID_7_0_EBX);
|
||||
cpuid_entry_override(entry, CPUID_7_ECX);
|
||||
cpuid_entry_override(entry, CPUID_7_EDX);
|
||||
|
||||
/* KVM only supports 0x7.0 and 0x7.1, capped above via min(). */
|
||||
if (entry->eax == 1) {
|
||||
/* KVM only supports up to 0x7.2, capped above via min(). */
|
||||
if (max_idx >= 1) {
|
||||
entry = do_host_cpuid(array, function, 1);
|
||||
if (!entry)
|
||||
goto out;
|
||||
@@ -918,6 +923,16 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
|
||||
entry->ecx = 0;
|
||||
entry->edx = 0;
|
||||
}
|
||||
if (max_idx >= 2) {
|
||||
entry = do_host_cpuid(array, function, 2);
|
||||
if (!entry)
|
||||
goto out;
|
||||
|
||||
cpuid_entry_override(entry, CPUID_7_2_EDX);
|
||||
entry->ecx = 0;
|
||||
entry->ebx = 0;
|
||||
entry->eax = 0;
|
||||
}
|
||||
break;
|
||||
case 0xa: { /* Architectural Performance Monitoring */
|
||||
union cpuid10_eax eax;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "ioapic.h"
|
||||
#include "trace.h"
|
||||
#include "x86.h"
|
||||
#include "xen.h"
|
||||
#include "cpuid.h"
|
||||
#include "hyperv.h"
|
||||
|
||||
@@ -338,8 +339,10 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
|
||||
}
|
||||
|
||||
/* Check if there are APF page ready requests pending */
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
kvm_make_request(KVM_REQ_APF_READY, apic->vcpu);
|
||||
kvm_xen_sw_enable_lapic(apic->vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
|
||||
|
||||
@@ -7,23 +7,44 @@
|
||||
#include <asm/cpufeatures.h>
|
||||
|
||||
/*
|
||||
* Hardware-defined CPUID leafs that are scattered in the kernel, but need to
|
||||
* be directly used by KVM. Note, these word values conflict with the kernel's
|
||||
* "bug" caps, but KVM doesn't use those.
|
||||
* Hardware-defined CPUID leafs that are either scattered by the kernel or are
|
||||
* unknown to the kernel, but need to be directly used by KVM. Note, these
|
||||
* word values conflict with the kernel's "bug" caps, but KVM doesn't use those.
|
||||
*/
|
||||
enum kvm_only_cpuid_leafs {
|
||||
CPUID_12_EAX = NCAPINTS,
|
||||
CPUID_7_2_EDX,
|
||||
NR_KVM_CPU_CAPS,
|
||||
|
||||
NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Define a KVM-only feature flag.
|
||||
*
|
||||
* For features that are scattered by cpufeatures.h, __feature_translate() also
|
||||
* needs to be updated to translate the kernel-defined feature into the
|
||||
* KVM-defined feature.
|
||||
*
|
||||
* For features that are 100% KVM-only, i.e. not defined by cpufeatures.h,
|
||||
* forego the intermediate KVM_X86_FEATURE and directly define X86_FEATURE_* so
|
||||
* that X86_FEATURE_* can be used in KVM. No __feature_translate() handling is
|
||||
* needed in this case.
|
||||
*/
|
||||
#define KVM_X86_FEATURE(w, f) ((w)*32 + (f))
|
||||
|
||||
/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */
|
||||
#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0)
|
||||
#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1)
|
||||
|
||||
/* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */
|
||||
#define X86_FEATURE_INTEL_PSFD KVM_X86_FEATURE(CPUID_7_2_EDX, 0)
|
||||
#define X86_FEATURE_IPRED_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 1)
|
||||
#define KVM_X86_FEATURE_RRSBA_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 2)
|
||||
#define X86_FEATURE_DDPD_U KVM_X86_FEATURE(CPUID_7_2_EDX, 3)
|
||||
#define X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
|
||||
#define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5)
|
||||
|
||||
struct cpuid_reg {
|
||||
u32 function;
|
||||
u32 index;
|
||||
@@ -49,6 +70,7 @@ static const struct cpuid_reg reverse_cpuid[] = {
|
||||
[CPUID_12_EAX] = {0x00000012, 0, CPUID_EAX},
|
||||
[CPUID_8000_001F_EAX] = {0x8000001f, 0, CPUID_EAX},
|
||||
[CPUID_8000_0021_EAX] = {0x80000021, 0, CPUID_EAX},
|
||||
[CPUID_7_2_EDX] = { 7, 2, CPUID_EDX},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -75,12 +97,16 @@ static __always_inline void reverse_cpuid_check(unsigned int x86_leaf)
|
||||
*/
|
||||
static __always_inline u32 __feature_translate(int x86_feature)
|
||||
{
|
||||
if (x86_feature == X86_FEATURE_SGX1)
|
||||
return KVM_X86_FEATURE_SGX1;
|
||||
else if (x86_feature == X86_FEATURE_SGX2)
|
||||
return KVM_X86_FEATURE_SGX2;
|
||||
#define KVM_X86_TRANSLATE_FEATURE(f) \
|
||||
case X86_FEATURE_##f: return KVM_X86_FEATURE_##f
|
||||
|
||||
return x86_feature;
|
||||
switch (x86_feature) {
|
||||
KVM_X86_TRANSLATE_FEATURE(SGX1);
|
||||
KVM_X86_TRANSLATE_FEATURE(SGX2);
|
||||
KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL);
|
||||
default:
|
||||
return x86_feature;
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline u32 __feature_leaf(int x86_feature)
|
||||
|
||||
@@ -1958,20 +1958,22 @@ int sev_mem_enc_register_region(struct kvm *kvm,
|
||||
goto e_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* The guest may change the memory encryption attribute from C=0 -> C=1
|
||||
* or vice versa for this memory range. Lets make sure caches are
|
||||
* flushed to ensure that guest data gets written into memory with
|
||||
* correct C-bit. Note, this must be done before dropping kvm->lock,
|
||||
* as region and its array of pages can be freed by a different task
|
||||
* once kvm->lock is released.
|
||||
*/
|
||||
sev_clflush_pages(region->pages, region->npages);
|
||||
|
||||
region->uaddr = range->addr;
|
||||
region->size = range->size;
|
||||
|
||||
list_add_tail(®ion->list, &sev->regions_list);
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
/*
|
||||
* The guest may change the memory encryption attribute from C=0 -> C=1
|
||||
* or vice versa for this memory range. Lets make sure caches are
|
||||
* flushed to ensure that guest data gets written into memory with
|
||||
* correct C-bit.
|
||||
*/
|
||||
sev_clflush_pages(region->pages, region->npages);
|
||||
|
||||
return ret;
|
||||
|
||||
e_free:
|
||||
|
||||
@@ -7758,6 +7758,16 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
|
||||
|
||||
if (r < 0)
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
|
||||
/*
|
||||
* Mark the page dirty _before_ checking whether or not the CMPXCHG was
|
||||
* successful, as the old value is written back on failure. Note, for
|
||||
* live migration, this is unnecessarily conservative as CMPXCHG writes
|
||||
* back the original value and the access is atomic, but KVM's ABI is
|
||||
* that all writes are dirty logged, regardless of the value written.
|
||||
*/
|
||||
kvm_vcpu_mark_page_dirty(vcpu, gpa_to_gfn(gpa));
|
||||
|
||||
if (r)
|
||||
return X86EMUL_CMPXCHG_FAILED;
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
|
||||
mark_page_dirty_in_slot(v->kvm, gpc->memslot, gpc->gpa >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *v)
|
||||
void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *v)
|
||||
{
|
||||
struct kvm_lapic_irq irq = { };
|
||||
int r;
|
||||
|
||||
@@ -16,6 +16,7 @@ extern struct static_key_false_deferred kvm_xen_enabled;
|
||||
|
||||
int __kvm_xen_has_interrupt(struct kvm_vcpu *vcpu);
|
||||
void kvm_xen_inject_pending_events(struct kvm_vcpu *vcpu);
|
||||
void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *vcpu);
|
||||
int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data);
|
||||
int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data);
|
||||
int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
|
||||
@@ -33,6 +34,19 @@ int kvm_xen_setup_evtchn(struct kvm *kvm,
|
||||
struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue);
|
||||
|
||||
static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/*
|
||||
* The local APIC is being enabled. If the per-vCPU upcall vector is
|
||||
* set and the vCPU's evtchn_upcall_pending flag is set, inject the
|
||||
* interrupt.
|
||||
*/
|
||||
if (static_branch_unlikely(&kvm_xen_enabled.key) &&
|
||||
vcpu->arch.xen.vcpu_info_cache.active &&
|
||||
vcpu->arch.xen.upcall_vector && __kvm_xen_has_interrupt(vcpu))
|
||||
kvm_xen_inject_vcpu_vector(vcpu);
|
||||
}
|
||||
|
||||
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
|
||||
{
|
||||
return static_branch_unlikely(&kvm_xen_enabled.key) &&
|
||||
@@ -98,6 +112,10 @@ static inline void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -513,6 +513,24 @@ void __init sme_early_init(void)
|
||||
*/
|
||||
if (sev_status & MSR_AMD64_SEV_ENABLED)
|
||||
ia32_disable();
|
||||
|
||||
/*
|
||||
* Override init functions that scan the ROM region in SEV-SNP guests,
|
||||
* as this memory is not pre-validated and would thus cause a crash.
|
||||
*/
|
||||
if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
|
||||
x86_init.mpparse.find_smp_config = x86_init_noop;
|
||||
x86_init.pci.init_irq = x86_init_noop;
|
||||
x86_init.resources.probe_roms = x86_init_noop;
|
||||
|
||||
/*
|
||||
* DMI setup behavior for SEV-SNP guests depends on
|
||||
* efi_enabled(EFI_CONFIG_TABLES), which hasn't been
|
||||
* parsed yet. snp_dmi_setup() will run after that
|
||||
* parsing has happened.
|
||||
*/
|
||||
x86_init.resources.dmi_setup = snp_dmi_setup;
|
||||
}
|
||||
}
|
||||
|
||||
void __init mem_encrypt_free_decrypted_mem(void)
|
||||
|
||||
@@ -97,7 +97,6 @@ static char sme_workarea[2 * PMD_PAGE_SIZE] __section(".init.scratch");
|
||||
|
||||
static char sme_cmdline_arg[] __initdata = "mem_encrypt";
|
||||
static char sme_cmdline_on[] __initdata = "on";
|
||||
static char sme_cmdline_off[] __initdata = "off";
|
||||
|
||||
static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
|
||||
{
|
||||
@@ -305,7 +304,8 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
|
||||
* instrumentation or checking boot_cpu_data in the cc_platform_has()
|
||||
* function.
|
||||
*/
|
||||
if (!sme_get_me_mask() || sev_status & MSR_AMD64_SEV_ENABLED)
|
||||
if (!sme_get_me_mask() ||
|
||||
RIP_REL_REF(sev_status) & MSR_AMD64_SEV_ENABLED)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -504,7 +504,7 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
|
||||
|
||||
void __init sme_enable(struct boot_params *bp)
|
||||
{
|
||||
const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
|
||||
const char *cmdline_ptr, *cmdline_arg, *cmdline_on;
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned long feature_mask;
|
||||
unsigned long me_mask;
|
||||
@@ -542,11 +542,11 @@ void __init sme_enable(struct boot_params *bp)
|
||||
me_mask = 1UL << (ebx & 0x3f);
|
||||
|
||||
/* Check the SEV MSR whether SEV or SME is enabled */
|
||||
sev_status = __rdmsr(MSR_AMD64_SEV);
|
||||
feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
|
||||
RIP_REL_REF(sev_status) = msr = __rdmsr(MSR_AMD64_SEV);
|
||||
feature_mask = (msr & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
|
||||
|
||||
/* The SEV-SNP CC blob should never be present unless SEV-SNP is enabled. */
|
||||
if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
if (snp && !(msr & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
snp_abort();
|
||||
|
||||
/* Check if memory encryption is enabled */
|
||||
@@ -572,7 +572,6 @@ void __init sme_enable(struct boot_params *bp)
|
||||
return;
|
||||
} else {
|
||||
/* SEV state cannot be controlled by a command line option */
|
||||
sme_me_mask = me_mask;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -587,28 +586,17 @@ void __init sme_enable(struct boot_params *bp)
|
||||
asm ("lea sme_cmdline_on(%%rip), %0"
|
||||
: "=r" (cmdline_on)
|
||||
: "p" (sme_cmdline_on));
|
||||
asm ("lea sme_cmdline_off(%%rip), %0"
|
||||
: "=r" (cmdline_off)
|
||||
: "p" (sme_cmdline_off));
|
||||
|
||||
if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
|
||||
sme_me_mask = me_mask;
|
||||
|
||||
cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
|
||||
((u64)bp->ext_cmd_line_ptr << 32));
|
||||
|
||||
if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
|
||||
goto out;
|
||||
|
||||
if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
|
||||
sme_me_mask = me_mask;
|
||||
else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
|
||||
sme_me_mask = 0;
|
||||
if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0 ||
|
||||
strncmp(buffer, cmdline_on, sizeof(buffer)))
|
||||
return;
|
||||
|
||||
out:
|
||||
if (sme_me_mask) {
|
||||
physical_mask &= ~sme_me_mask;
|
||||
cc_set_vendor(CC_VENDOR_AMD);
|
||||
cc_set_mask(sme_me_mask);
|
||||
}
|
||||
RIP_REL_REF(sme_me_mask) = me_mask;
|
||||
physical_mask &= ~me_mask;
|
||||
cc_vendor = CC_VENDOR_AMD;
|
||||
cc_set_mask(me_mask);
|
||||
}
|
||||
|
||||
11
block/bio.c
11
block/bio.c
@@ -1112,19 +1112,16 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
|
||||
struct folio_iter fi;
|
||||
|
||||
bio_for_each_folio_all(fi, bio) {
|
||||
struct page *page;
|
||||
size_t done = 0;
|
||||
size_t nr_pages;
|
||||
|
||||
if (mark_dirty) {
|
||||
folio_lock(fi.folio);
|
||||
folio_mark_dirty(fi.folio);
|
||||
folio_unlock(fi.folio);
|
||||
}
|
||||
page = folio_page(fi.folio, fi.offset / PAGE_SIZE);
|
||||
do {
|
||||
folio_put(fi.folio);
|
||||
done += PAGE_SIZE;
|
||||
} while (done < fi.length);
|
||||
nr_pages = (fi.offset + fi.length - 1) / PAGE_SIZE -
|
||||
fi.offset / PAGE_SIZE + 1;
|
||||
folio_put_refs(fi.folio, nr_pages);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__bio_release_pages);
|
||||
|
||||
@@ -675,6 +675,22 @@ out_queue_exit:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blk_mq_alloc_request_hctx);
|
||||
|
||||
static void blk_mq_finish_request(struct request *rq)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
|
||||
if ((rq->rq_flags & RQF_ELVPRIV) &&
|
||||
q->elevator->type->ops.finish_request) {
|
||||
q->elevator->type->ops.finish_request(rq);
|
||||
/*
|
||||
* For postflush request that may need to be
|
||||
* completed twice, we should clear this flag
|
||||
* to avoid double finish_request() on the rq.
|
||||
*/
|
||||
rq->rq_flags &= ~RQF_ELVPRIV;
|
||||
}
|
||||
}
|
||||
|
||||
static void __blk_mq_free_request(struct request *rq)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
@@ -701,9 +717,7 @@ void blk_mq_free_request(struct request *rq)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
|
||||
if ((rq->rq_flags & RQF_ELVPRIV) &&
|
||||
q->elevator->type->ops.finish_request)
|
||||
q->elevator->type->ops.finish_request(rq);
|
||||
blk_mq_finish_request(rq);
|
||||
|
||||
if (unlikely(laptop_mode && !blk_rq_is_passthrough(rq)))
|
||||
laptop_io_completion(q->disk->bdi);
|
||||
@@ -747,16 +761,11 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
|
||||
/*
|
||||
* Partial zone append completions cannot be supported as the
|
||||
* BIO fragments may end up not being written sequentially.
|
||||
* For such case, force the completed nbytes to be equal to
|
||||
* the BIO size so that bio_advance() sets the BIO remaining
|
||||
* size to 0 and we end up calling bio_endio() before returning.
|
||||
*/
|
||||
if (bio->bi_iter.bi_size != nbytes) {
|
||||
if (bio->bi_iter.bi_size != nbytes)
|
||||
bio->bi_status = BLK_STS_IOERR;
|
||||
nbytes = bio->bi_iter.bi_size;
|
||||
} else {
|
||||
else
|
||||
bio->bi_iter.bi_sector = rq->__sector;
|
||||
}
|
||||
}
|
||||
|
||||
bio_advance(bio, nbytes);
|
||||
@@ -1025,6 +1034,8 @@ inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
|
||||
if (blk_mq_need_time_stamp(rq))
|
||||
__blk_mq_end_request_acct(rq, ktime_get_ns());
|
||||
|
||||
blk_mq_finish_request(rq);
|
||||
|
||||
if (rq->end_io) {
|
||||
rq_qos_done(rq->q, rq);
|
||||
if (rq->end_io(rq, error) == RQ_END_IO_FREE)
|
||||
@@ -1079,6 +1090,8 @@ void blk_mq_end_request_batch(struct io_comp_batch *iob)
|
||||
if (iob->need_ts)
|
||||
__blk_mq_end_request_acct(rq, now);
|
||||
|
||||
blk_mq_finish_request(rq);
|
||||
|
||||
rq_qos_done(rq->q, rq);
|
||||
|
||||
/*
|
||||
|
||||
@@ -680,6 +680,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
t->zone_write_granularity = max(t->zone_write_granularity,
|
||||
b->zone_write_granularity);
|
||||
t->zoned = max(t->zoned, b->zoned);
|
||||
if (!t->zoned) {
|
||||
t->zone_write_granularity = 0;
|
||||
t->max_zone_append_sectors = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_stack_limits);
|
||||
|
||||
@@ -622,9 +622,8 @@ static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
|
||||
struct request_queue *q = hctx->queue;
|
||||
struct deadline_data *dd = q->elevator->elevator_data;
|
||||
struct blk_mq_tags *tags = hctx->sched_tags;
|
||||
unsigned int shift = tags->bitmap_tags.sb.shift;
|
||||
|
||||
dd->async_depth = max(1U, 3 * (1U << shift) / 4);
|
||||
dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
|
||||
|
||||
sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, dd->async_depth);
|
||||
}
|
||||
|
||||
@@ -208,8 +208,10 @@ void spk_do_flush(void)
|
||||
wake_up_process(speakup_task);
|
||||
}
|
||||
|
||||
void synth_write(const char *buf, size_t count)
|
||||
void synth_write(const char *_buf, size_t count)
|
||||
{
|
||||
const unsigned char *buf = (const unsigned char *) _buf;
|
||||
|
||||
while (count--)
|
||||
synth_buffer_add(*buf++);
|
||||
synth_start();
|
||||
|
||||
@@ -671,11 +671,6 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
|
||||
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||
struct ahci_host_priv *hpriv)
|
||||
{
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) {
|
||||
dev_info(&pdev->dev, "ASM1166 has only six ports\n");
|
||||
hpriv->saved_port_map = 0x3f;
|
||||
}
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
|
||||
dev_info(&pdev->dev, "JMB361 has only one port\n");
|
||||
hpriv->saved_port_map = 1;
|
||||
|
||||
@@ -711,8 +711,10 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
|
||||
ehc->saved_ncq_enabled |= 1 << devno;
|
||||
|
||||
/* If we are resuming, wake up the device */
|
||||
if (ap->pflags & ATA_PFLAG_RESUMING)
|
||||
if (ap->pflags & ATA_PFLAG_RESUMING) {
|
||||
dev->flags |= ATA_DFLAG_RESUMING;
|
||||
ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3089,6 +3091,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev->flags &= ~ATA_DFLAG_RESUMING;
|
||||
*r_failed_dev = dev;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4652,6 +4652,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
bool do_resume;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&ap->scsi_scan_mutex);
|
||||
@@ -4673,7 +4674,15 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
if (scsi_device_get(sdev))
|
||||
continue;
|
||||
|
||||
do_resume = dev->flags & ATA_DFLAG_RESUMING;
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
if (do_resume) {
|
||||
ret = scsi_resume_device(sdev);
|
||||
if (ret == -EWOULDBLOCK)
|
||||
goto unlock;
|
||||
dev->flags &= ~ATA_DFLAG_RESUMING;
|
||||
}
|
||||
ret = scsi_rescan_device(sdev);
|
||||
scsi_device_put(sdev);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
@@ -362,8 +362,10 @@ void dev_pm_enable_wake_irq_complete(struct device *dev)
|
||||
return;
|
||||
|
||||
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
|
||||
wirq->status & WAKE_IRQ_DEDICATED_REVERSE)
|
||||
wirq->status & WAKE_IRQ_DEDICATED_REVERSE) {
|
||||
enable_irq(wirq->irq);
|
||||
wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1557,6 +1557,7 @@ static struct clk_regmap_div nss_ubi0_div_clk_src = {
|
||||
|
||||
static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
|
||||
F(24000000, P_XO, 1, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct clk_parent_data gcc_xo_gpll0_core_pi_sleep_clk[] = {
|
||||
@@ -1737,6 +1738,7 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
|
||||
F(160000000, P_GPLL0, 5, 0, 0),
|
||||
F(216000000, P_GPLL6, 5, 0, 0),
|
||||
F(308570000, P_GPLL6, 3.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_div2[] = {
|
||||
|
||||
@@ -973,6 +973,7 @@ static struct clk_rcg2 pcie0_axi_clk_src = {
|
||||
|
||||
static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
|
||||
F(19200000, P_XO, 1, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 pcie0_aux_clk_src = {
|
||||
@@ -1078,6 +1079,7 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
|
||||
F(19200000, P_XO, 1, 0, 0),
|
||||
F(160000000, P_GPLL0, 5, 0, 0),
|
||||
F(308570000, P_GPLL6, 3.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 sdcc1_ice_core_clk_src = {
|
||||
|
||||
@@ -4038,3 +4038,4 @@ module_exit(gcc_sdm845_exit);
|
||||
MODULE_DESCRIPTION("QTI GCC SDM845 Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:gcc-sdm845");
|
||||
MODULE_SOFTDEP("pre: rpmhpd");
|
||||
|
||||
@@ -334,6 +334,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = {
|
||||
F(333430000, P_MMPLL1, 3.5, 0, 0),
|
||||
F(400000000, P_MMPLL0, 2, 0, 0),
|
||||
F(466800000, P_MMPLL1, 2.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 mmss_axi_clk_src = {
|
||||
@@ -358,6 +359,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = {
|
||||
F(150000000, P_GPLL0, 4, 0, 0),
|
||||
F(228570000, P_MMPLL0, 3.5, 0, 0),
|
||||
F(320000000, P_MMPLL0, 2.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 ocmemnoc_clk_src = {
|
||||
|
||||
@@ -279,6 +279,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = {
|
||||
F(291750000, P_MMPLL1, 4, 0, 0),
|
||||
F(400000000, P_MMPLL0, 2, 0, 0),
|
||||
F(466800000, P_MMPLL1, 2.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 mmss_axi_clk_src = {
|
||||
@@ -303,6 +304,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = {
|
||||
F(150000000, P_GPLL0, 4, 0, 0),
|
||||
F(291750000, P_MMPLL1, 4, 0, 0),
|
||||
F(400000000, P_MMPLL0, 2, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct clk_rcg2 ocmemnoc_clk_src = {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
|
||||
#define GT_CONTROL_AUTO_INC BIT(3) /* banked */
|
||||
#define GT_CONTROL_PRESCALER_SHIFT 8
|
||||
#define GT_CONTROL_PRESCALER_MAX 0xF
|
||||
#define GT_CONTROL_PRESCALER_MAX 0xFF
|
||||
#define GT_CONTROL_PRESCALER_MASK (GT_CONTROL_PRESCALER_MAX << \
|
||||
GT_CONTROL_PRESCALER_SHIFT)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user