mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-15 05:11:32 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
This commit is contained in:
commit
aaf9253025
@ -3523,6 +3523,12 @@
|
||||
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
|
||||
See Documentation/blockdev/ramdisk.txt.
|
||||
|
||||
random.trust_cpu={on,off}
|
||||
[KNL] Enable or disable trusting the use of the
|
||||
CPU's random number generator (if available) to
|
||||
fully seed the kernel's CRNG. Default is controlled
|
||||
by CONFIG_RANDOM_TRUST_CPU.
|
||||
|
||||
ras=option[,option,...] [KNL] RAS-specific options
|
||||
|
||||
cec_disable [X86]
|
||||
|
@ -3,7 +3,6 @@
|
||||
Required properties:
|
||||
- compatible :
|
||||
- "fsl,imx7ulp-lpi2c" for LPI2C compatible with the one integrated on i.MX7ULP soc
|
||||
- "fsl,imx8dv-lpi2c" for LPI2C compatible with the one integrated on i.MX8DV soc
|
||||
- reg : address and length of the lpi2c master registers
|
||||
- interrupts : lpi2c interrupt
|
||||
- clocks : lpi2c clock specifier
|
||||
@ -11,7 +10,7 @@ Required properties:
|
||||
Examples:
|
||||
|
||||
lpi2c7: lpi2c7@40a50000 {
|
||||
compatible = "fsl,imx8dv-lpi2c";
|
||||
compatible = "fsl,imx7ulp-lpi2c";
|
||||
reg = <0x40A50000 0x10000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -86,7 +86,7 @@ pkg-config
|
||||
|
||||
The build system, as of 4.18, requires pkg-config to check for installed
|
||||
kconfig tools and to determine flags settings for use in
|
||||
'make {menu,n,g,x}config'. Previously pkg-config was being used but not
|
||||
'make {g,x}config'. Previously pkg-config was being used but not
|
||||
verified or documented.
|
||||
|
||||
Flex
|
||||
|
@ -97,6 +97,11 @@ parameters may be changed at runtime by the command
|
||||
allowing boot to proceed. none ignores them, expecting
|
||||
user space to do the scan.
|
||||
|
||||
scsi_mod.use_blk_mq=
|
||||
[SCSI] use blk-mq I/O path by default
|
||||
See SCSI_MQ_DEFAULT in drivers/scsi/Kconfig.
|
||||
Format: <y/n>
|
||||
|
||||
sim710= [SCSI,HW]
|
||||
See header of drivers/scsi/sim710.c.
|
||||
|
||||
|
@ -2311,6 +2311,7 @@ F: drivers/clocksource/cadence_ttc_timer.c
|
||||
F: drivers/i2c/busses/i2c-cadence.c
|
||||
F: drivers/mmc/host/sdhci-of-arasan.c
|
||||
F: drivers/edac/synopsys_edac.c
|
||||
F: drivers/i2c/busses/i2c-xiic.c
|
||||
|
||||
ARM64 PORT (AARCH64 ARCHITECTURE)
|
||||
M: Catalin Marinas <catalin.marinas@arm.com>
|
||||
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 19
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc2
|
||||
EXTRAVERSION = -rc3
|
||||
NAME = Merciless Moray
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -9,6 +9,7 @@
|
||||
config ARC
|
||||
def_bool y
|
||||
select ARC_TIMERS
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SYNC_DMA_FOR_CPU
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
@ -28,8 +29,12 @@ config ARC
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_FUTEX_CMPXCHG if FUTEX
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_IOREMAP_PROT
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZMA
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_MEMBLOCK
|
||||
@ -44,11 +49,6 @@ config ARC
|
||||
select OF_EARLY_FLATTREE
|
||||
select OF_RESERVED_MEM
|
||||
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZMA
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
|
||||
config ARCH_HAS_CACHE_LINE_SIZE
|
||||
def_bool y
|
||||
|
@ -43,10 +43,7 @@ ifdef CONFIG_ARC_CURR_IN_REG
|
||||
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
|
||||
endif
|
||||
|
||||
upto_gcc44 := $(call cc-ifversion, -le, 0404, y)
|
||||
atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
|
||||
|
||||
cflags-$(atleast_gcc44) += -fsection-anchors
|
||||
cflags-y += -fsection-anchors
|
||||
|
||||
cflags-$(CONFIG_ARC_HAS_LLSC) += -mlock
|
||||
cflags-$(CONFIG_ARC_HAS_SWAPE) += -mswape
|
||||
@ -82,11 +79,6 @@ cflags-$(disable_small_data) += -mno-sdata -fcall-used-gp
|
||||
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mbig-endian
|
||||
ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
|
||||
|
||||
# STAR 9000518362: (fixed with binutils shipping with gcc 4.8)
|
||||
# arc-linux-uclibc-ld (buildroot) or arceb-elf32-ld (EZChip) don't accept
|
||||
# --build-id w/o "-marclinux". Default arc-elf32-ld is OK
|
||||
ldflags-$(upto_gcc44) += -marclinux
|
||||
|
||||
LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
|
||||
|
||||
# Modules with short calls might break for calls into builtin-kernel
|
||||
|
@ -93,6 +93,32 @@
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Mark DMA peripherals connected via IOC port as dma-coherent. We do
|
||||
* it via overlay because peripherals defined in axs10x_mb.dtsi are
|
||||
* used for both AXS101 and AXS103 boards and only AXS103 has IOC (so
|
||||
* only AXS103 board has HW-coherent DMA peripherals)
|
||||
* We don't need to mark pgu@17000 as dma-coherent because it uses
|
||||
* external DMA buffer located outside of IOC aperture.
|
||||
*/
|
||||
axs10x_mb {
|
||||
ethernet@0x18000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
ehci@0x40000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
ohci@0x60000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
mmc@0x15000 {
|
||||
dma-coherent;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* The DW APB ICTL intc on MB is connected to CPU intc via a
|
||||
* DT "invisible" DW APB GPIO block, configured to simply pass thru
|
||||
|
@ -100,6 +100,32 @@
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Mark DMA peripherals connected via IOC port as dma-coherent. We do
|
||||
* it via overlay because peripherals defined in axs10x_mb.dtsi are
|
||||
* used for both AXS101 and AXS103 boards and only AXS103 has IOC (so
|
||||
* only AXS103 board has HW-coherent DMA peripherals)
|
||||
* We don't need to mark pgu@17000 as dma-coherent because it uses
|
||||
* external DMA buffer located outside of IOC aperture.
|
||||
*/
|
||||
axs10x_mb {
|
||||
ethernet@0x18000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
ehci@0x40000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
ohci@0x60000 {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
mmc@0x15000 {
|
||||
dma-coherent;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* This INTC is actually connected to DW APB GPIO
|
||||
* which acts as a wire between MB INTC and CPU INTC.
|
||||
|
@ -9,6 +9,10 @@
|
||||
*/
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
ethernet = &gmac;
|
||||
};
|
||||
|
||||
axs10x_mb {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
@ -68,7 +72,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
ethernet@0x18000 {
|
||||
gmac: ethernet@0x18000 {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "snps,dwmac";
|
||||
reg = < 0x18000 0x2000 >;
|
||||
@ -81,6 +85,7 @@
|
||||
max-speed = <100>;
|
||||
resets = <&creg_rst 5>;
|
||||
reset-names = "stmmaceth";
|
||||
mac-address = [00 00 00 00 00 00]; /* Filled in by U-Boot */
|
||||
};
|
||||
|
||||
ehci@0x40000 {
|
||||
|
@ -25,6 +25,10 @@
|
||||
bootargs = "earlycon=uart8250,mmio32,0xf0005000,115200n8 console=ttyS0,115200n8 debug print-fatal-signals=1";
|
||||
};
|
||||
|
||||
aliases {
|
||||
ethernet = &gmac;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -163,7 +167,7 @@
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
ethernet@8000 {
|
||||
gmac: ethernet@8000 {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "snps,dwmac";
|
||||
reg = <0x8000 0x2000>;
|
||||
@ -176,6 +180,8 @@
|
||||
phy-handle = <&phy0>;
|
||||
resets = <&cgu_rst HSDK_ETH_RESET>;
|
||||
reset-names = "stmmaceth";
|
||||
mac-address = [00 00 00 00 00 00]; /* Filled in by U-Boot */
|
||||
dma-coherent;
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
@ -194,12 +200,14 @@
|
||||
compatible = "snps,hsdk-v1.0-ohci", "generic-ohci";
|
||||
reg = <0x60000 0x100>;
|
||||
interrupts = <15>;
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
ehci@40000 {
|
||||
compatible = "snps,hsdk-v1.0-ehci", "generic-ehci";
|
||||
reg = <0x40000 0x100>;
|
||||
interrupts = <15>;
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
mmc@a000 {
|
||||
@ -212,6 +220,7 @@
|
||||
clock-names = "biu", "ciu";
|
||||
interrupts = <12>;
|
||||
bus-width = <4>;
|
||||
dma-coherent;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -63,7 +61,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
CONFIG_MOUSE_SERIAL=y
|
||||
CONFIG_MOUSE_SYNAPTICS_USB=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
|
@ -1,5 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -64,7 +62,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
CONFIG_MOUSE_SERIAL=y
|
||||
CONFIG_MOUSE_SYNAPTICS_USB=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
|
@ -1,5 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -65,7 +63,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
CONFIG_MOUSE_SERIAL=y
|
||||
CONFIG_MOUSE_SYNAPTICS_USB=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
@ -57,7 +56,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
@ -60,7 +59,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
|
@ -59,7 +59,6 @@ CONFIG_NETCONSOLE=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
@ -44,7 +43,6 @@ CONFIG_LXT_PHY=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_ARC=y
|
||||
CONFIG_SERIAL_ARC_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
@ -45,7 +44,6 @@ CONFIG_DEVTMPFS=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_ARC=y
|
||||
CONFIG_SERIAL_ARC_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
@ -44,7 +43,6 @@ CONFIG_DEVTMPFS=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_ARC=y
|
||||
CONFIG_SERIAL_ARC_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -48,7 +47,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -47,7 +46,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
@ -58,7 +57,6 @@ CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -57,7 +57,6 @@ CONFIG_STMMAC_ETH=y
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_IKCONFIG=y
|
||||
@ -53,7 +52,6 @@ CONFIG_NATIONAL_PHY=y
|
||||
CONFIG_MOUSE_PS2_TOUCHKIT=y
|
||||
CONFIG_SERIO_ARC_PS2=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
|
@ -1,5 +1,4 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_IKCONFIG=y
|
||||
|
@ -84,7 +84,7 @@ static inline int atomic_fetch_##op(int i, atomic_t *v) \
|
||||
"1: llock %[orig], [%[ctr]] \n" \
|
||||
" " #asm_op " %[val], %[orig], %[i] \n" \
|
||||
" scond %[val], [%[ctr]] \n" \
|
||||
" \n" \
|
||||
" bnz 1b \n" \
|
||||
: [val] "=&r" (val), \
|
||||
[orig] "=&r" (orig) \
|
||||
: [ctr] "r" (&v->counter), \
|
||||
|
13
arch/arc/include/asm/dma-mapping.h
Normal file
13
arch/arc/include/asm/dma-mapping.h
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// (C) 2018 Synopsys, Inc. (www.synopsys.com)
|
||||
|
||||
#ifndef ASM_ARC_DMA_MAPPING_H
|
||||
#define ASM_ARC_DMA_MAPPING_H
|
||||
|
||||
#include <asm-generic/dma-mapping.h>
|
||||
|
||||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
const struct iommu_ops *iommu, bool coherent);
|
||||
#define arch_setup_dma_ops arch_setup_dma_ops
|
||||
|
||||
#endif
|
@ -83,9 +83,6 @@ done:
|
||||
static void show_faulting_vma(unsigned long address, char *buf)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct inode *inode;
|
||||
unsigned long ino = 0;
|
||||
dev_t dev = 0;
|
||||
char *nm = buf;
|
||||
struct mm_struct *active_mm = current->active_mm;
|
||||
|
||||
@ -99,12 +96,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
|
||||
* if the container VMA is not found
|
||||
*/
|
||||
if (vma && (vma->vm_start <= address)) {
|
||||
struct file *file = vma->vm_file;
|
||||
if (file) {
|
||||
nm = file_path(file, buf, PAGE_SIZE - 1);
|
||||
inode = file_inode(vma->vm_file);
|
||||
dev = inode->i_sb->s_dev;
|
||||
ino = inode->i_ino;
|
||||
if (vma->vm_file) {
|
||||
nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
|
||||
if (IS_ERR(nm))
|
||||
nm = "?";
|
||||
}
|
||||
pr_info(" @off 0x%lx in [%s]\n"
|
||||
" VMA: 0x%08lx to 0x%08lx\n",
|
||||
|
@ -65,7 +65,7 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
||||
|
||||
n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n",
|
||||
perip_base,
|
||||
IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency "));
|
||||
IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) "));
|
||||
|
||||
return buf;
|
||||
}
|
||||
@ -896,15 +896,6 @@ static void __dma_cache_wback_slc(phys_addr_t start, unsigned long sz)
|
||||
slc_op(start, sz, OP_FLUSH);
|
||||
}
|
||||
|
||||
/*
|
||||
* DMA ops for systems with IOC
|
||||
* IOC hardware snoops all DMA traffic keeping the caches consistent with
|
||||
* memory - eliding need for any explicit cache maintenance of DMA buffers
|
||||
*/
|
||||
static void __dma_cache_wback_inv_ioc(phys_addr_t start, unsigned long sz) {}
|
||||
static void __dma_cache_inv_ioc(phys_addr_t start, unsigned long sz) {}
|
||||
static void __dma_cache_wback_ioc(phys_addr_t start, unsigned long sz) {}
|
||||
|
||||
/*
|
||||
* Exported DMA API
|
||||
*/
|
||||
@ -1153,6 +1144,19 @@ noinline void __init arc_ioc_setup(void)
|
||||
{
|
||||
unsigned int ioc_base, mem_sz;
|
||||
|
||||
/*
|
||||
* As for today we don't support both IOC and ZONE_HIGHMEM enabled
|
||||
* simultaneously. This happens because as of today IOC aperture covers
|
||||
* only ZONE_NORMAL (low mem) and any dma transactions outside this
|
||||
* region won't be HW coherent.
|
||||
* If we want to use both IOC and ZONE_HIGHMEM we can use
|
||||
* bounce_buffer to handle dma transactions to HIGHMEM.
|
||||
* Also it is possible to modify dma_direct cache ops or increase IOC
|
||||
* aperture size if we are planning to use HIGHMEM without PAE.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_HIGHMEM))
|
||||
panic("IOC and HIGHMEM can't be used simultaneously");
|
||||
|
||||
/* Flush + invalidate + disable L1 dcache */
|
||||
__dc_disable();
|
||||
|
||||
@ -1264,11 +1268,7 @@ void __init arc_cache_init_master(void)
|
||||
if (is_isa_arcv2() && ioc_enable)
|
||||
arc_ioc_setup();
|
||||
|
||||
if (is_isa_arcv2() && ioc_enable) {
|
||||
__dma_cache_wback_inv = __dma_cache_wback_inv_ioc;
|
||||
__dma_cache_inv = __dma_cache_inv_ioc;
|
||||
__dma_cache_wback = __dma_cache_wback_ioc;
|
||||
} else if (is_isa_arcv2() && l2_line_sz && slc_enable) {
|
||||
if (is_isa_arcv2() && l2_line_sz && slc_enable) {
|
||||
__dma_cache_wback_inv = __dma_cache_wback_inv_slc;
|
||||
__dma_cache_inv = __dma_cache_inv_slc;
|
||||
__dma_cache_wback = __dma_cache_wback_slc;
|
||||
@ -1277,6 +1277,12 @@ void __init arc_cache_init_master(void)
|
||||
__dma_cache_inv = __dma_cache_inv_l1;
|
||||
__dma_cache_wback = __dma_cache_wback_l1;
|
||||
}
|
||||
/*
|
||||
* In case of IOC (say IOC+SLC case), pointers above could still be set
|
||||
* but end up not being relevant as the first function in chain is not
|
||||
* called at all for @dma_direct_ops
|
||||
* arch_sync_dma_for_cpu() -> dma_cache_*() -> __dma_cache_*()
|
||||
*/
|
||||
}
|
||||
|
||||
void __ref arc_cache_init(void)
|
||||
|
@ -6,20 +6,17 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DMA Coherent API Notes
|
||||
*
|
||||
* I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
|
||||
* implemented by accessing it using a kernel virtual address, with
|
||||
* Cache bit off in the TLB entry.
|
||||
*
|
||||
* The default DMA address == Phy address which is 0x8000_0000 based.
|
||||
*/
|
||||
|
||||
#include <linux/dma-noncoherent.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
/*
|
||||
* ARCH specific callbacks for generic noncoherent DMA ops (dma/noncoherent.c)
|
||||
* - hardware IOC not available (or "dma-coherent" not set for device in DT)
|
||||
* - But still handle both coherent and non-coherent requests from caller
|
||||
*
|
||||
* For DMA coherent hardware (IOC) generic code suffices
|
||||
*/
|
||||
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t gfp, unsigned long attrs)
|
||||
{
|
||||
@ -27,42 +24,29 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
struct page *page;
|
||||
phys_addr_t paddr;
|
||||
void *kvaddr;
|
||||
int need_coh = 1, need_kvaddr = 0;
|
||||
bool need_coh = !(attrs & DMA_ATTR_NON_CONSISTENT);
|
||||
|
||||
/*
|
||||
* __GFP_HIGHMEM flag is cleared by upper layer functions
|
||||
* (in include/linux/dma-mapping.h) so we should never get a
|
||||
* __GFP_HIGHMEM here.
|
||||
*/
|
||||
BUG_ON(gfp & __GFP_HIGHMEM);
|
||||
|
||||
page = alloc_pages(gfp, order);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* IOC relies on all data (even coherent DMA data) being in cache
|
||||
* Thus allocate normal cached memory
|
||||
*
|
||||
* The gains with IOC are two pronged:
|
||||
* -For streaming data, elides need for cache maintenance, saving
|
||||
* cycles in flush code, and bus bandwidth as all the lines of a
|
||||
* buffer need to be flushed out to memory
|
||||
* -For coherent data, Read/Write to buffers terminate early in cache
|
||||
* (vs. always going to memory - thus are faster)
|
||||
*/
|
||||
if ((is_isa_arcv2() && ioc_enable) ||
|
||||
(attrs & DMA_ATTR_NON_CONSISTENT))
|
||||
need_coh = 0;
|
||||
|
||||
/*
|
||||
* - A coherent buffer needs MMU mapping to enforce non-cachability
|
||||
* - A highmem page needs a virtual handle (hence MMU mapping)
|
||||
* independent of cachability
|
||||
*/
|
||||
if (PageHighMem(page) || need_coh)
|
||||
need_kvaddr = 1;
|
||||
|
||||
/* This is linear addr (0x8000_0000 based) */
|
||||
paddr = page_to_phys(page);
|
||||
|
||||
*dma_handle = paddr;
|
||||
|
||||
/* This is kernel Virtual address (0x7000_0000 based) */
|
||||
if (need_kvaddr) {
|
||||
/*
|
||||
* A coherent buffer needs MMU mapping to enforce non-cachability.
|
||||
* kvaddr is kernel Virtual address (0x7000_0000 based).
|
||||
*/
|
||||
if (need_coh) {
|
||||
kvaddr = ioremap_nocache(paddr, size);
|
||||
if (kvaddr == NULL) {
|
||||
__free_pages(page, order);
|
||||
@ -93,12 +77,8 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr,
|
||||
{
|
||||
phys_addr_t paddr = dma_handle;
|
||||
struct page *page = virt_to_page(paddr);
|
||||
int is_non_coh = 1;
|
||||
|
||||
is_non_coh = (attrs & DMA_ATTR_NON_CONSISTENT) ||
|
||||
(is_isa_arcv2() && ioc_enable);
|
||||
|
||||
if (PageHighMem(page) || !is_non_coh)
|
||||
if (!(attrs & DMA_ATTR_NON_CONSISTENT))
|
||||
iounmap((void __force __iomem *)vaddr);
|
||||
|
||||
__free_pages(page, get_order(size));
|
||||
@ -185,3 +165,23 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Plug in coherent or noncoherent dma ops
|
||||
*/
|
||||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
const struct iommu_ops *iommu, bool coherent)
|
||||
{
|
||||
/*
|
||||
* IOC hardware snoops all DMA traffic keeping the caches consistent
|
||||
* with memory - eliding need for any explicit cache maintenance of
|
||||
* DMA buffers - so we can use dma_direct cache ops.
|
||||
*/
|
||||
if (is_isa_arcv2() && ioc_enable && coherent) {
|
||||
set_dma_ops(dev, &dma_direct_ops);
|
||||
dev_info(dev, "use dma_direct_ops cache ops\n");
|
||||
} else {
|
||||
set_dma_ops(dev, &dma_noncoherent_ops);
|
||||
dev_info(dev, "use dma_noncoherent_ops cache ops\n");
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,6 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
int kvm_unmap_hva_range(struct kvm *kvm,
|
||||
unsigned long start, unsigned long end);
|
||||
void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
|
||||
|
@ -46,6 +46,7 @@
|
||||
pinctrl-0 = <&mmc0_pins>;
|
||||
vmmc-supply = <®_cldo1>;
|
||||
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
|
||||
bus-width = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -56,6 +57,7 @@
|
||||
vqmmc-supply = <®_bldo2>;
|
||||
non-removable;
|
||||
cap-mmc-hw-reset;
|
||||
bus-width = <8>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -61,8 +61,7 @@ struct kvm_arch {
|
||||
u64 vmid_gen;
|
||||
u32 vmid;
|
||||
|
||||
/* 1-level 2nd stage table and lock */
|
||||
spinlock_t pgd_lock;
|
||||
/* 1-level 2nd stage table, protected by kvm->mmu_lock */
|
||||
pgd_t *pgd;
|
||||
|
||||
/* VTTBR value associated with above pgd and vmid */
|
||||
@ -357,7 +356,6 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
int kvm_unmap_hva_range(struct kvm *kvm,
|
||||
unsigned long start, unsigned long end);
|
||||
void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
|
||||
|
@ -98,8 +98,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
|
||||
val = read_sysreg(cpacr_el1);
|
||||
val |= CPACR_EL1_TTA;
|
||||
val &= ~CPACR_EL1_ZEN;
|
||||
if (!update_fp_enabled(vcpu))
|
||||
if (!update_fp_enabled(vcpu)) {
|
||||
val &= ~CPACR_EL1_FPEN;
|
||||
__activate_traps_fpsimd32(vcpu);
|
||||
}
|
||||
|
||||
write_sysreg(val, cpacr_el1);
|
||||
|
||||
@ -114,8 +116,10 @@ static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
|
||||
|
||||
val = CPTR_EL2_DEFAULT;
|
||||
val |= CPTR_EL2_TTA | CPTR_EL2_TZ;
|
||||
if (!update_fp_enabled(vcpu))
|
||||
if (!update_fp_enabled(vcpu)) {
|
||||
val |= CPTR_EL2_TFP;
|
||||
__activate_traps_fpsimd32(vcpu);
|
||||
}
|
||||
|
||||
write_sysreg(val, cptr_el2);
|
||||
}
|
||||
@ -129,7 +133,6 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
|
||||
if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE))
|
||||
write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2);
|
||||
|
||||
__activate_traps_fpsimd32(vcpu);
|
||||
if (has_vhe())
|
||||
activate_traps_vhe(vcpu);
|
||||
else
|
||||
|
@ -985,8 +985,9 @@ int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
|
||||
|
||||
pmd = READ_ONCE(*pmdp);
|
||||
|
||||
/* No-op for empty entry and WARN_ON for valid entry */
|
||||
if (!pmd_present(pmd) || !pmd_table(pmd)) {
|
||||
if (!pmd_present(pmd))
|
||||
return 1;
|
||||
if (!pmd_table(pmd)) {
|
||||
VM_WARN_ON(!pmd_table(pmd));
|
||||
return 1;
|
||||
}
|
||||
@ -1007,8 +1008,9 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
||||
|
||||
pud = READ_ONCE(*pudp);
|
||||
|
||||
/* No-op for empty entry and WARN_ON for valid entry */
|
||||
if (!pud_present(pud) || !pud_table(pud)) {
|
||||
if (!pud_present(pud))
|
||||
return 1;
|
||||
if (!pud_table(pud)) {
|
||||
VM_WARN_ON(!pud_table(pud));
|
||||
return 1;
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ void __init cf_bootmem_alloc(void)
|
||||
high_memory = (void *)_ramend;
|
||||
|
||||
/* Reserve kernel text/data/bss */
|
||||
memblock_reserve(memstart, memstart - _rambase);
|
||||
memblock_reserve(_rambase, memstart - _rambase);
|
||||
|
||||
m68k_virt_to_node_shift = fls(_ramend - 1) - 6;
|
||||
module_fixup(NULL, __start_fixup, __stop_fixup);
|
||||
|
@ -931,7 +931,6 @@ enum kvm_mips_fault_result kvm_trap_emul_gva_fault(struct kvm_vcpu *vcpu,
|
||||
bool write);
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
int kvm_unmap_hva_range(struct kvm *kvm,
|
||||
unsigned long start, unsigned long end);
|
||||
void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
|
||||
|
@ -40,6 +40,7 @@ struct ltq_dma_channel {
|
||||
int desc; /* the current descriptor */
|
||||
struct ltq_dma_desc *desc_base; /* the descriptor base */
|
||||
int phys; /* physical addr */
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
@ -20,6 +21,7 @@
|
||||
|
||||
#include <asm/abi.h>
|
||||
#include <asm/mips-cps.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
/* Kernel-provided data used by the VDSO. */
|
||||
@ -128,12 +130,30 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
vvar_size = gic_size + PAGE_SIZE;
|
||||
size = vvar_size + image->size;
|
||||
|
||||
/*
|
||||
* Find a region that's large enough for us to perform the
|
||||
* colour-matching alignment below.
|
||||
*/
|
||||
if (cpu_has_dc_aliases)
|
||||
size += shm_align_mask + 1;
|
||||
|
||||
base = get_unmapped_area(NULL, 0, size, 0, 0);
|
||||
if (IS_ERR_VALUE(base)) {
|
||||
ret = base;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we suffer from dcache aliasing, ensure that the VDSO data page
|
||||
* mapping is coloured the same as the kernel's mapping of that memory.
|
||||
* This ensures that when the kernel updates the VDSO data userland
|
||||
* will observe it without requiring cache invalidations.
|
||||
*/
|
||||
if (cpu_has_dc_aliases) {
|
||||
base = __ALIGN_MASK(base, shm_align_mask);
|
||||
base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask;
|
||||
}
|
||||
|
||||
data_addr = base + gic_size;
|
||||
vdso_addr = data_addr + PAGE_SIZE;
|
||||
|
||||
|
@ -512,16 +512,6 @@ static int kvm_unmap_hva_handler(struct kvm *kvm, gfn_t gfn, gfn_t gfn_end,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
|
||||
{
|
||||
unsigned long end = hva + PAGE_SIZE;
|
||||
|
||||
handle_hva_to_gpa(kvm, hva, end, &kvm_unmap_hva_handler, NULL);
|
||||
|
||||
kvm_mips_callbacks->flush_shadow_all(kvm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
|
||||
{
|
||||
handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL);
|
||||
|
@ -130,7 +130,7 @@ ltq_dma_alloc(struct ltq_dma_channel *ch)
|
||||
unsigned long flags;
|
||||
|
||||
ch->desc = 0;
|
||||
ch->desc_base = dma_zalloc_coherent(NULL,
|
||||
ch->desc_base = dma_zalloc_coherent(ch->dev,
|
||||
LTQ_DESC_NUM * LTQ_DESC_SIZE,
|
||||
&ch->phys, GFP_ATOMIC);
|
||||
|
||||
@ -182,7 +182,7 @@ ltq_dma_free(struct ltq_dma_channel *ch)
|
||||
if (!ch->desc_base)
|
||||
return;
|
||||
ltq_dma_close(ch);
|
||||
dma_free_coherent(NULL, LTQ_DESC_NUM * LTQ_DESC_SIZE,
|
||||
dma_free_coherent(ch->dev, LTQ_DESC_NUM * LTQ_DESC_SIZE,
|
||||
ch->desc_base, ch->phys);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ltq_dma_free);
|
||||
|
@ -40,6 +40,10 @@ config NDS32
|
||||
select NO_IOPORT_MAP
|
||||
select RTC_LIB
|
||||
select THREAD_INFO_IN_TASK
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
help
|
||||
Andes(nds32) Linux support.
|
||||
|
||||
|
@ -5,6 +5,10 @@ KBUILD_DEFCONFIG := defconfig
|
||||
|
||||
comma = ,
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
arch-y += -malways-save-lp -mno-relax
|
||||
endif
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-option, -mno-sched-prolog-epilog)
|
||||
KBUILD_CFLAGS += -mcmodel=large
|
||||
|
||||
|
@ -121,9 +121,9 @@ struct elf32_hdr;
|
||||
*/
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#ifdef __NDS32_EB__
|
||||
#define ELF_DATA ELFDATA2MSB;
|
||||
#define ELF_DATA ELFDATA2MSB
|
||||
#else
|
||||
#define ELF_DATA ELFDATA2LSB;
|
||||
#define ELF_DATA ELFDATA2LSB
|
||||
#endif
|
||||
#define ELF_ARCH EM_NDS32
|
||||
#define USE_ELF_CORE_DUMP
|
||||
|
46
arch/nds32/include/asm/ftrace.h
Normal file
46
arch/nds32/include/asm/ftrace.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __ASM_NDS32_FTRACE_H
|
||||
#define __ASM_NDS32_FTRACE_H
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
|
||||
#define HAVE_FUNCTION_GRAPH_FP_TEST
|
||||
|
||||
#define MCOUNT_ADDR ((unsigned long)(_mcount))
|
||||
/* mcount call is composed of three instructions:
|
||||
* sethi + ori + jral
|
||||
*/
|
||||
#define MCOUNT_INSN_SIZE 12
|
||||
|
||||
extern void _mcount(unsigned long parent_ip);
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
#define FTRACE_ADDR ((unsigned long)_ftrace_caller)
|
||||
|
||||
#ifdef __NDS32_EL__
|
||||
#define INSN_NOP 0x09000040
|
||||
#define INSN_SIZE(insn) (((insn & 0x00000080) == 0) ? 4 : 2)
|
||||
#define IS_SETHI(insn) ((insn & 0x000000fe) == 0x00000046)
|
||||
#define ENDIAN_CONVERT(insn) be32_to_cpu(insn)
|
||||
#else /* __NDS32_EB__ */
|
||||
#define INSN_NOP 0x40000009
|
||||
#define INSN_SIZE(insn) (((insn & 0x80000000) == 0) ? 4 : 2)
|
||||
#define IS_SETHI(insn) ((insn & 0xfe000000) == 0x46000000)
|
||||
#define ENDIAN_CONVERT(insn) (insn)
|
||||
#endif
|
||||
|
||||
extern void _ftrace_caller(unsigned long parent_ip);
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
struct dyn_arch_ftrace {
|
||||
};
|
||||
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#endif /* __ASM_NDS32_FTRACE_H */
|
@ -17,6 +17,7 @@
|
||||
#else
|
||||
#define FP_OFFSET (-2)
|
||||
#endif
|
||||
#define LP_OFFSET (-1)
|
||||
|
||||
extern void __init early_trap_init(void);
|
||||
static inline void GIE_ENABLE(void)
|
||||
|
@ -38,7 +38,7 @@ struct exception_table_entry {
|
||||
extern int fixup_exception(struct pt_regs *regs);
|
||||
|
||||
#define KERNEL_DS ((mm_segment_t) { ~0UL })
|
||||
#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
|
||||
#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
|
||||
|
||||
#define get_ds() (KERNEL_DS)
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
@ -49,11 +49,11 @@ static inline void set_fs(mm_segment_t fs)
|
||||
current_thread_info()->addr_limit = fs;
|
||||
}
|
||||
|
||||
#define segment_eq(a, b) ((a) == (b))
|
||||
#define segment_eq(a, b) ((a) == (b))
|
||||
|
||||
#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
|
||||
|
||||
#define access_ok(type, addr, size) \
|
||||
#define access_ok(type, addr, size) \
|
||||
__range_ok((unsigned long)addr, (unsigned long)size)
|
||||
/*
|
||||
* Single-value transfer routines. They automatically use the right
|
||||
@ -75,70 +75,73 @@ static inline void set_fs(mm_segment_t fs)
|
||||
* versions are void (ie, don't return a value as such).
|
||||
*/
|
||||
|
||||
#define get_user(x,p) \
|
||||
({ \
|
||||
long __e = -EFAULT; \
|
||||
if(likely(access_ok(VERIFY_READ, p, sizeof(*p)))) { \
|
||||
__e = __get_user(x,p); \
|
||||
} else \
|
||||
x = 0; \
|
||||
__e; \
|
||||
})
|
||||
#define __get_user(x,ptr) \
|
||||
#define get_user __get_user \
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
({ \
|
||||
long __gu_err = 0; \
|
||||
__get_user_err((x),(ptr),__gu_err); \
|
||||
__get_user_check((x), (ptr), __gu_err); \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
#define __get_user_error(x,ptr,err) \
|
||||
#define __get_user_error(x, ptr, err) \
|
||||
({ \
|
||||
__get_user_err((x),(ptr),err); \
|
||||
(void) 0; \
|
||||
__get_user_check((x), (ptr), (err)); \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define __get_user_err(x,ptr,err) \
|
||||
#define __get_user_check(x, ptr, err) \
|
||||
({ \
|
||||
const __typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
might_fault(); \
|
||||
if (access_ok(VERIFY_READ, __p, sizeof(*__p))) { \
|
||||
__get_user_err((x), __p, (err)); \
|
||||
} else { \
|
||||
(x) = 0; (err) = -EFAULT; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define __get_user_err(x, ptr, err) \
|
||||
do { \
|
||||
unsigned long __gu_addr = (unsigned long)(ptr); \
|
||||
unsigned long __gu_val; \
|
||||
__chk_user_ptr(ptr); \
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: \
|
||||
__get_user_asm("lbi",__gu_val,__gu_addr,err); \
|
||||
__get_user_asm("lbi", __gu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 2: \
|
||||
__get_user_asm("lhi",__gu_val,__gu_addr,err); \
|
||||
__get_user_asm("lhi", __gu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 4: \
|
||||
__get_user_asm("lwi",__gu_val,__gu_addr,err); \
|
||||
__get_user_asm("lwi", __gu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 8: \
|
||||
__get_user_asm_dword(__gu_val,__gu_addr,err); \
|
||||
__get_user_asm_dword(__gu_val, (ptr), (err)); \
|
||||
break; \
|
||||
default: \
|
||||
BUILD_BUG(); \
|
||||
break; \
|
||||
} \
|
||||
(x) = (__typeof__(*(ptr)))__gu_val; \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
} while (0)
|
||||
|
||||
#define __get_user_asm(inst,x,addr,err) \
|
||||
asm volatile( \
|
||||
"1: "inst" %1,[%2]\n" \
|
||||
"2:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"3: move %0, %3\n" \
|
||||
" move %1, #0\n" \
|
||||
" b 2b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 3b\n" \
|
||||
" .previous" \
|
||||
: "+r" (err), "=&r" (x) \
|
||||
: "r" (addr), "i" (-EFAULT) \
|
||||
: "cc")
|
||||
#define __get_user_asm(inst, x, addr, err) \
|
||||
__asm__ __volatile__ ( \
|
||||
"1: "inst" %1,[%2]\n" \
|
||||
"2:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"3: move %0, %3\n" \
|
||||
" move %1, #0\n" \
|
||||
" b 2b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 3b\n" \
|
||||
" .previous" \
|
||||
: "+r" (err), "=&r" (x) \
|
||||
: "r" (addr), "i" (-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#ifdef __NDS32_EB__
|
||||
#define __gu_reg_oper0 "%H1"
|
||||
@ -149,61 +152,66 @@ do { \
|
||||
#endif
|
||||
|
||||
#define __get_user_asm_dword(x, addr, err) \
|
||||
asm volatile( \
|
||||
"\n1:\tlwi " __gu_reg_oper0 ",[%2]\n" \
|
||||
"\n2:\tlwi " __gu_reg_oper1 ",[%2+4]\n" \
|
||||
"3:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"4: move %0, %3\n" \
|
||||
" b 3b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 4b\n" \
|
||||
" .long 2b, 4b\n" \
|
||||
" .previous" \
|
||||
: "+r"(err), "=&r"(x) \
|
||||
: "r"(addr), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
#define put_user(x,p) \
|
||||
({ \
|
||||
long __e = -EFAULT; \
|
||||
if(likely(access_ok(VERIFY_WRITE, p, sizeof(*p)))) { \
|
||||
__e = __put_user(x,p); \
|
||||
} \
|
||||
__e; \
|
||||
})
|
||||
#define __put_user(x,ptr) \
|
||||
__asm__ __volatile__ ( \
|
||||
"\n1:\tlwi " __gu_reg_oper0 ",[%2]\n" \
|
||||
"\n2:\tlwi " __gu_reg_oper1 ",[%2+4]\n" \
|
||||
"3:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"4: move %0, %3\n" \
|
||||
" b 3b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 4b\n" \
|
||||
" .long 2b, 4b\n" \
|
||||
" .previous" \
|
||||
: "+r"(err), "=&r"(x) \
|
||||
: "r"(addr), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#define put_user __put_user \
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
long __pu_err = 0; \
|
||||
__put_user_err((x),(ptr),__pu_err); \
|
||||
__put_user_err((x), (ptr), __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
#define __put_user_error(x,ptr,err) \
|
||||
#define __put_user_error(x, ptr, err) \
|
||||
({ \
|
||||
__put_user_err((x),(ptr),err); \
|
||||
(void) 0; \
|
||||
__put_user_err((x), (ptr), (err)); \
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define __put_user_err(x,ptr,err) \
|
||||
#define __put_user_check(x, ptr, err) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
might_fault(); \
|
||||
if (access_ok(VERIFY_WRITE, __p, sizeof(*__p))) { \
|
||||
__put_user_err((x), __p, (err)); \
|
||||
} else { \
|
||||
(err) = -EFAULT; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define __put_user_err(x, ptr, err) \
|
||||
do { \
|
||||
unsigned long __pu_addr = (unsigned long)(ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__chk_user_ptr(ptr); \
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: \
|
||||
__put_user_asm("sbi",__pu_val,__pu_addr,err); \
|
||||
__put_user_asm("sbi", __pu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 2: \
|
||||
__put_user_asm("shi",__pu_val,__pu_addr,err); \
|
||||
__put_user_asm("shi", __pu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 4: \
|
||||
__put_user_asm("swi",__pu_val,__pu_addr,err); \
|
||||
__put_user_asm("swi", __pu_val, (ptr), (err)); \
|
||||
break; \
|
||||
case 8: \
|
||||
__put_user_asm_dword(__pu_val,__pu_addr,err); \
|
||||
__put_user_asm_dword(__pu_val, (ptr), (err)); \
|
||||
break; \
|
||||
default: \
|
||||
BUILD_BUG(); \
|
||||
@ -211,22 +219,22 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_asm(inst,x,addr,err) \
|
||||
asm volatile( \
|
||||
"1: "inst" %1,[%2]\n" \
|
||||
"2:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"3: move %0, %3\n" \
|
||||
" b 2b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 3b\n" \
|
||||
" .previous" \
|
||||
: "+r" (err) \
|
||||
: "r" (x), "r" (addr), "i" (-EFAULT) \
|
||||
: "cc")
|
||||
#define __put_user_asm(inst, x, addr, err) \
|
||||
__asm__ __volatile__ ( \
|
||||
"1: "inst" %1,[%2]\n" \
|
||||
"2:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"3: move %0, %3\n" \
|
||||
" b 2b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 3b\n" \
|
||||
" .previous" \
|
||||
: "+r" (err) \
|
||||
: "r" (x), "r" (addr), "i" (-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#ifdef __NDS32_EB__
|
||||
#define __pu_reg_oper0 "%H2"
|
||||
@ -237,23 +245,24 @@ do { \
|
||||
#endif
|
||||
|
||||
#define __put_user_asm_dword(x, addr, err) \
|
||||
asm volatile( \
|
||||
"\n1:\tswi " __pu_reg_oper0 ",[%1]\n" \
|
||||
"\n2:\tswi " __pu_reg_oper1 ",[%1+4]\n" \
|
||||
"3:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"4: move %0, %3\n" \
|
||||
" b 3b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 4b\n" \
|
||||
" .long 2b, 4b\n" \
|
||||
" .previous" \
|
||||
: "+r"(err) \
|
||||
: "r"(addr), "r"(x), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
__asm__ __volatile__ ( \
|
||||
"\n1:\tswi " __pu_reg_oper0 ",[%1]\n" \
|
||||
"\n2:\tswi " __pu_reg_oper1 ",[%1+4]\n" \
|
||||
"3:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"4: move %0, %3\n" \
|
||||
" b 3b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 1b, 4b\n" \
|
||||
" .long 2b, 4b\n" \
|
||||
" .previous" \
|
||||
: "+r"(err) \
|
||||
: "r"(addr), "r"(x), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
extern unsigned long __arch_clear_user(void __user * addr, unsigned long n);
|
||||
extern long strncpy_from_user(char *dest, const char __user * src, long count);
|
||||
extern __must_check long strlen_user(const char __user * str);
|
||||
|
@ -21,3 +21,9 @@ extra-y := head.o vmlinux.lds
|
||||
|
||||
|
||||
obj-y += vdso/
|
||||
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
|
||||
endif
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
void __iomem *atl2c_base;
|
||||
static const struct of_device_id atl2c_ids[] __initconst = {
|
||||
{.compatible = "andestech,atl2c",}
|
||||
{.compatible = "andestech,atl2c",},
|
||||
{}
|
||||
};
|
||||
|
||||
static int __init atl2c_of_init(void)
|
||||
|
@ -118,7 +118,7 @@ common_exception_handler:
|
||||
/* interrupt */
|
||||
2:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
jal trace_hardirqs_off
|
||||
jal __trace_hardirqs_off
|
||||
#endif
|
||||
move $r0, $sp
|
||||
sethi $lp, hi20(ret_from_intr)
|
||||
|
@ -138,8 +138,8 @@ no_work_pending:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
lwi $p0, [$sp+(#IPSW_OFFSET)]
|
||||
andi $p0, $p0, #0x1
|
||||
la $r10, trace_hardirqs_off
|
||||
la $r9, trace_hardirqs_on
|
||||
la $r10, __trace_hardirqs_off
|
||||
la $r9, __trace_hardirqs_on
|
||||
cmovz $r9, $p0, $r10
|
||||
jral $r9
|
||||
#endif
|
||||
|
309
arch/nds32/kernel/ftrace.c
Normal file
309
arch/nds32/kernel/ftrace.c
Normal file
@ -0,0 +1,309 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||
extern void (*ftrace_trace_function)(unsigned long, unsigned long,
|
||||
struct ftrace_ops*, struct pt_regs*);
|
||||
extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
|
||||
extern void ftrace_graph_caller(void);
|
||||
|
||||
noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct pt_regs *regs)
|
||||
{
|
||||
__asm__ (""); /* avoid to optimize as pure function */
|
||||
}
|
||||
|
||||
noinline void _mcount(unsigned long parent_ip)
|
||||
{
|
||||
/* save all state by the compiler prologue */
|
||||
|
||||
unsigned long ip = (unsigned long)__builtin_return_address(0);
|
||||
|
||||
if (ftrace_trace_function != ftrace_stub)
|
||||
ftrace_trace_function(ip - MCOUNT_INSN_SIZE, parent_ip,
|
||||
NULL, NULL);
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
if (ftrace_graph_return != (trace_func_graph_ret_t)ftrace_stub
|
||||
|| ftrace_graph_entry != ftrace_graph_entry_stub)
|
||||
ftrace_graph_caller();
|
||||
#endif
|
||||
|
||||
/* restore all state by the compiler epilogue */
|
||||
}
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
|
||||
#else /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct pt_regs *regs)
|
||||
{
|
||||
__asm__ (""); /* avoid to optimize as pure function */
|
||||
}
|
||||
|
||||
noinline void __naked _mcount(unsigned long parent_ip)
|
||||
{
|
||||
__asm__ (""); /* avoid to optimize as pure function */
|
||||
}
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
|
||||
#define XSTR(s) STR(s)
|
||||
#define STR(s) #s
|
||||
void _ftrace_caller(unsigned long parent_ip)
|
||||
{
|
||||
/* save all state needed by the compiler prologue */
|
||||
|
||||
/*
|
||||
* prepare arguments for real tracing function
|
||||
* first arg : __builtin_return_address(0) - MCOUNT_INSN_SIZE
|
||||
* second arg : parent_ip
|
||||
*/
|
||||
__asm__ __volatile__ (
|
||||
"move $r1, %0 \n\t"
|
||||
"addi $r0, %1, #-" XSTR(MCOUNT_INSN_SIZE) "\n\t"
|
||||
:
|
||||
: "r" (parent_ip), "r" (__builtin_return_address(0)));
|
||||
|
||||
/* a placeholder for the call to a real tracing function */
|
||||
__asm__ __volatile__ (
|
||||
"ftrace_call: \n\t"
|
||||
"nop \n\t"
|
||||
"nop \n\t"
|
||||
"nop \n\t");
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* a placeholder for the call to ftrace_graph_caller */
|
||||
__asm__ __volatile__ (
|
||||
"ftrace_graph_call: \n\t"
|
||||
"nop \n\t"
|
||||
"nop \n\t"
|
||||
"nop \n\t");
|
||||
#endif
|
||||
/* restore all state needed by the compiler epilogue */
|
||||
}
|
||||
|
||||
int __init ftrace_dyn_arch_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ftrace_arch_code_modify_prepare(void)
|
||||
{
|
||||
set_all_modules_text_rw();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ftrace_arch_code_modify_post_process(void)
|
||||
{
|
||||
set_all_modules_text_ro();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long gen_sethi_insn(unsigned long addr)
|
||||
{
|
||||
unsigned long opcode = 0x46000000;
|
||||
unsigned long imm = addr >> 12;
|
||||
unsigned long rt_num = 0xf << 20;
|
||||
|
||||
return ENDIAN_CONVERT(opcode | rt_num | imm);
|
||||
}
|
||||
|
||||
static unsigned long gen_ori_insn(unsigned long addr)
|
||||
{
|
||||
unsigned long opcode = 0x58000000;
|
||||
unsigned long imm = addr & 0x0000fff;
|
||||
unsigned long rt_num = 0xf << 20;
|
||||
unsigned long ra_num = 0xf << 15;
|
||||
|
||||
return ENDIAN_CONVERT(opcode | rt_num | ra_num | imm);
|
||||
}
|
||||
|
||||
static unsigned long gen_jral_insn(unsigned long addr)
|
||||
{
|
||||
unsigned long opcode = 0x4a000001;
|
||||
unsigned long rt_num = 0x1e << 20;
|
||||
unsigned long rb_num = 0xf << 10;
|
||||
|
||||
return ENDIAN_CONVERT(opcode | rt_num | rb_num);
|
||||
}
|
||||
|
||||
static void ftrace_gen_call_insn(unsigned long *call_insns,
|
||||
unsigned long addr)
|
||||
{
|
||||
call_insns[0] = gen_sethi_insn(addr); /* sethi $r15, imm20u */
|
||||
call_insns[1] = gen_ori_insn(addr); /* ori $r15, $r15, imm15u */
|
||||
call_insns[2] = gen_jral_insn(addr); /* jral $lp, $r15 */
|
||||
}
|
||||
|
||||
static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
|
||||
unsigned long *new_insn, bool validate)
|
||||
{
|
||||
unsigned long orig_insn[3];
|
||||
|
||||
if (validate) {
|
||||
if (probe_kernel_read(orig_insn, (void *)pc, MCOUNT_INSN_SIZE))
|
||||
return -EFAULT;
|
||||
if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (probe_kernel_write((void *)pc, new_insn, MCOUNT_INSN_SIZE))
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
|
||||
unsigned long *new_insn, bool validate)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __ftrace_modify_code(pc, old_insn, new_insn, validate);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
{
|
||||
unsigned long pc = (unsigned long)&ftrace_call;
|
||||
unsigned long old_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
unsigned long new_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
|
||||
if (func != ftrace_stub)
|
||||
ftrace_gen_call_insn(new_insn, (unsigned long)func);
|
||||
|
||||
return ftrace_modify_code(pc, old_insn, new_insn, false);
|
||||
}
|
||||
|
||||
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
unsigned long pc = rec->ip;
|
||||
unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
|
||||
ftrace_gen_call_insn(call_insn, addr);
|
||||
|
||||
return ftrace_modify_code(pc, nop_insn, call_insn, true);
|
||||
}
|
||||
|
||||
int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
|
||||
unsigned long addr)
|
||||
{
|
||||
unsigned long pc = rec->ip;
|
||||
unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
|
||||
ftrace_gen_call_insn(call_insn, addr);
|
||||
|
||||
return ftrace_modify_code(pc, call_insn, nop_insn, true);
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
|
||||
unsigned long frame_pointer)
|
||||
{
|
||||
unsigned long return_hooker = (unsigned long)&return_to_handler;
|
||||
struct ftrace_graph_ent trace;
|
||||
unsigned long old;
|
||||
int err;
|
||||
|
||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return;
|
||||
|
||||
old = *parent;
|
||||
|
||||
trace.func = self_addr;
|
||||
trace.depth = current->curr_ret_stack + 1;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace))
|
||||
return;
|
||||
|
||||
err = ftrace_push_return_trace(old, self_addr, &trace.depth,
|
||||
frame_pointer, NULL);
|
||||
|
||||
if (err == -EBUSY)
|
||||
return;
|
||||
|
||||
*parent = return_hooker;
|
||||
}
|
||||
|
||||
noinline void ftrace_graph_caller(void)
|
||||
{
|
||||
unsigned long *parent_ip =
|
||||
(unsigned long *)(__builtin_frame_address(2) - 4);
|
||||
|
||||
unsigned long selfpc =
|
||||
(unsigned long)(__builtin_return_address(1) - MCOUNT_INSN_SIZE);
|
||||
|
||||
unsigned long frame_pointer =
|
||||
(unsigned long)__builtin_frame_address(3);
|
||||
|
||||
prepare_ftrace_return(parent_ip, selfpc, frame_pointer);
|
||||
}
|
||||
|
||||
extern unsigned long ftrace_return_to_handler(unsigned long frame_pointer);
|
||||
void __naked return_to_handler(void)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
/* save state needed by the ABI */
|
||||
"smw.adm $r0,[$sp],$r1,#0x0 \n\t"
|
||||
|
||||
/* get original return address */
|
||||
"move $r0, $fp \n\t"
|
||||
"bal ftrace_return_to_handler\n\t"
|
||||
"move $lp, $r0 \n\t"
|
||||
|
||||
/* restore state nedded by the ABI */
|
||||
"lmw.bim $r0,[$sp],$r1,#0x0 \n\t");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
extern unsigned long ftrace_graph_call;
|
||||
|
||||
static int ftrace_modify_graph_caller(bool enable)
|
||||
{
|
||||
unsigned long pc = (unsigned long)&ftrace_graph_call;
|
||||
unsigned long nop_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
unsigned long call_insn[3] = {INSN_NOP, INSN_NOP, INSN_NOP};
|
||||
|
||||
ftrace_gen_call_insn(call_insn, (unsigned long)ftrace_graph_caller);
|
||||
|
||||
if (enable)
|
||||
return ftrace_modify_code(pc, nop_insn, call_insn, true);
|
||||
else
|
||||
return ftrace_modify_code(pc, call_insn, nop_insn, true);
|
||||
}
|
||||
|
||||
int ftrace_enable_ftrace_graph_caller(void)
|
||||
{
|
||||
return ftrace_modify_graph_caller(true);
|
||||
}
|
||||
|
||||
int ftrace_disable_ftrace_graph_caller(void)
|
||||
{
|
||||
return ftrace_modify_graph_caller(false);
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
noinline void __trace_hardirqs_off(void)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
}
|
||||
noinline void __trace_hardirqs_on(void)
|
||||
{
|
||||
trace_hardirqs_on();
|
||||
}
|
||||
#endif /* CONFIG_TRACE_IRQFLAGS */
|
@ -40,7 +40,7 @@ void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
|
||||
|
||||
tmp2 = tmp & loc_mask;
|
||||
if (partial_in_place) {
|
||||
tmp &= (!loc_mask);
|
||||
tmp &= (~loc_mask);
|
||||
tmp =
|
||||
tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
|
||||
} else {
|
||||
@ -70,7 +70,7 @@ void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
|
||||
|
||||
tmp2 = tmp & loc_mask;
|
||||
if (partial_in_place) {
|
||||
tmp &= (!loc_mask);
|
||||
tmp &= (~loc_mask);
|
||||
tmp =
|
||||
tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
|
||||
} else {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
void save_stack_trace(struct stack_trace *trace)
|
||||
{
|
||||
@ -16,6 +17,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
||||
unsigned long *fpn;
|
||||
int skip = trace->skip;
|
||||
int savesched;
|
||||
int graph_idx = 0;
|
||||
|
||||
if (tsk == current) {
|
||||
__asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
|
||||
@ -29,10 +31,12 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
||||
&& (fpn >= (unsigned long *)TASK_SIZE)) {
|
||||
unsigned long lpp, fpp;
|
||||
|
||||
lpp = fpn[-1];
|
||||
lpp = fpn[LP_OFFSET];
|
||||
fpp = fpn[FP_OFFSET];
|
||||
if (!__kernel_text_address(lpp))
|
||||
break;
|
||||
else
|
||||
lpp = ftrace_graph_ret_addr(tsk, &graph_idx, lpp, NULL);
|
||||
|
||||
if (savesched || !in_sched_functions(lpp)) {
|
||||
if (skip) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm/unistd.h>
|
||||
@ -94,28 +95,6 @@ static void dump_instr(struct pt_regs *regs)
|
||||
set_fs(fs);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
#include <linux/ftrace.h>
|
||||
static void
|
||||
get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
|
||||
{
|
||||
if (*addr == (unsigned long)return_to_handler) {
|
||||
int index = tsk->curr_ret_stack;
|
||||
|
||||
if (tsk->ret_stack && index >= *graph) {
|
||||
index -= *graph;
|
||||
*addr = tsk->ret_stack[index].ret;
|
||||
(*graph)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LOOP_TIMES (100)
|
||||
static void __dump(struct task_struct *tsk, unsigned long *base_reg)
|
||||
{
|
||||
@ -126,7 +105,8 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg)
|
||||
while (!kstack_end(base_reg)) {
|
||||
ret_addr = *base_reg++;
|
||||
if (__kernel_text_address(ret_addr)) {
|
||||
get_real_ret_addr(&ret_addr, tsk, &graph);
|
||||
ret_addr = ftrace_graph_ret_addr(
|
||||
tsk, &graph, ret_addr, NULL);
|
||||
print_ip_sym(ret_addr);
|
||||
}
|
||||
if (--cnt < 0)
|
||||
@ -137,15 +117,12 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg)
|
||||
!((unsigned long)base_reg & 0x3) &&
|
||||
((unsigned long)base_reg >= TASK_SIZE)) {
|
||||
unsigned long next_fp;
|
||||
#if !defined(NDS32_ABI_2)
|
||||
ret_addr = base_reg[0];
|
||||
next_fp = base_reg[1];
|
||||
#else
|
||||
ret_addr = base_reg[-1];
|
||||
ret_addr = base_reg[LP_OFFSET];
|
||||
next_fp = base_reg[FP_OFFSET];
|
||||
#endif
|
||||
if (__kernel_text_address(ret_addr)) {
|
||||
get_real_ret_addr(&ret_addr, tsk, &graph);
|
||||
|
||||
ret_addr = ftrace_graph_ret_addr(
|
||||
tsk, &graph, ret_addr, NULL);
|
||||
print_ip_sym(ret_addr);
|
||||
}
|
||||
if (--cnt < 0)
|
||||
@ -196,11 +173,10 @@ void die(const char *str, struct pt_regs *regs, int err)
|
||||
pr_emerg("CPU: %i\n", smp_processor_id());
|
||||
show_regs(regs);
|
||||
pr_emerg("Process %s (pid: %d, stack limit = 0x%p)\n",
|
||||
tsk->comm, tsk->pid, task_thread_info(tsk) + 1);
|
||||
tsk->comm, tsk->pid, end_of_stack(tsk));
|
||||
|
||||
if (!user_mode(regs) || in_interrupt()) {
|
||||
dump_mem("Stack: ", regs->sp,
|
||||
THREAD_SIZE + (unsigned long)task_thread_info(tsk));
|
||||
dump_mem("Stack: ", regs->sp, (regs->sp + PAGE_SIZE) & PAGE_MASK);
|
||||
dump_instr(regs);
|
||||
dump_stack();
|
||||
}
|
||||
|
@ -13,14 +13,26 @@ OUTPUT_ARCH(nds32)
|
||||
ENTRY(_stext_lma)
|
||||
jiffies = jiffies_64;
|
||||
|
||||
#if defined(CONFIG_GCOV_KERNEL)
|
||||
#define NDS32_EXIT_KEEP(x) x
|
||||
#else
|
||||
#define NDS32_EXIT_KEEP(x)
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
_stext_lma = TEXTADDR - LOAD_OFFSET;
|
||||
. = TEXTADDR;
|
||||
__init_begin = .;
|
||||
HEAD_TEXT_SECTION
|
||||
.exit.text : {
|
||||
NDS32_EXIT_KEEP(EXIT_TEXT)
|
||||
}
|
||||
INIT_TEXT_SECTION(PAGE_SIZE)
|
||||
INIT_DATA_SECTION(16)
|
||||
.exit.data : {
|
||||
NDS32_EXIT_KEEP(EXIT_DATA)
|
||||
}
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
__init_end = .;
|
||||
|
||||
|
@ -358,7 +358,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
unsigned long pp, key;
|
||||
unsigned long v, orig_v, gr;
|
||||
__be64 *hptep;
|
||||
int index;
|
||||
long int index;
|
||||
int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
|
||||
|
||||
if (kvm_is_radix(vcpu->kvm))
|
||||
|
@ -725,10 +725,10 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
gpa, shift);
|
||||
kvmppc_radix_tlbie_page(kvm, gpa, shift);
|
||||
if ((old & _PAGE_DIRTY) && memslot->dirty_bitmap) {
|
||||
unsigned long npages = 1;
|
||||
unsigned long psize = PAGE_SIZE;
|
||||
if (shift)
|
||||
npages = 1ul << (shift - PAGE_SHIFT);
|
||||
kvmppc_update_dirty_map(memslot, gfn, npages);
|
||||
psize = 1ul << shift;
|
||||
kvmppc_update_dirty_map(memslot, gfn, psize);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -85,15 +85,8 @@ atomic_t hart_lottery;
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
static void __init setup_initrd(void)
|
||||
{
|
||||
extern char __initramfs_start[];
|
||||
extern unsigned long __initramfs_size;
|
||||
unsigned long size;
|
||||
|
||||
if (__initramfs_size > 0) {
|
||||
initrd_start = (unsigned long)(&__initramfs_start);
|
||||
initrd_end = initrd_start + __initramfs_size;
|
||||
}
|
||||
|
||||
if (initrd_start >= initrd_end) {
|
||||
printk(KERN_INFO "initrd not found or empty");
|
||||
goto disable;
|
||||
|
@ -16,7 +16,13 @@ typedef struct {
|
||||
unsigned long asce;
|
||||
unsigned long asce_limit;
|
||||
unsigned long vdso_base;
|
||||
/* The mmu context allocates 4K page tables. */
|
||||
/*
|
||||
* The following bitfields need a down_write on the mm
|
||||
* semaphore when they are written to. As they are only
|
||||
* written once, they can be read without a lock.
|
||||
*
|
||||
* The mmu context allocates 4K page tables.
|
||||
*/
|
||||
unsigned int alloc_pgste:1;
|
||||
/* The mmu context uses extended page tables. */
|
||||
unsigned int has_pgste:1;
|
||||
|
@ -695,7 +695,9 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
|
||||
r = -EINVAL;
|
||||
else {
|
||||
r = 0;
|
||||
down_write(&kvm->mm->mmap_sem);
|
||||
kvm->mm->context.allow_gmap_hpage_1m = 1;
|
||||
up_write(&kvm->mm->mmap_sem);
|
||||
/*
|
||||
* We might have to create fake 4k page
|
||||
* tables. To avoid that the hardware works on
|
||||
|
@ -280,9 +280,11 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
if (rc)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc == -EFAULT)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
vcpu->run->s.regs.gprs[reg1] &= ~0xff;
|
||||
vcpu->run->s.regs.gprs[reg1] |= key;
|
||||
return 0;
|
||||
@ -324,9 +326,11 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
if (rc < 0)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc == -EFAULT)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
kvm_s390_set_psw_cc(vcpu, rc);
|
||||
return 0;
|
||||
}
|
||||
@ -390,12 +394,12 @@ static int handle_sske(struct kvm_vcpu *vcpu)
|
||||
FAULT_FLAG_WRITE, &unlocked);
|
||||
rc = !rc ? -EAGAIN : rc;
|
||||
}
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc == -EFAULT)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc >= 0)
|
||||
start += PAGE_SIZE;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (m3 & (SSKE_MC | SSKE_MR)) {
|
||||
@ -1002,13 +1006,15 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
|
||||
FAULT_FLAG_WRITE, &unlocked);
|
||||
rc = !rc ? -EAGAIN : rc;
|
||||
}
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc == -EFAULT)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (rc >= 0)
|
||||
start += PAGE_SIZE;
|
||||
if (rc == -EAGAIN)
|
||||
continue;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
if (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) {
|
||||
if (psw_bits(vcpu->arch.sie_block->gpsw).eaba == PSW_BITS_AMODE_64BIT) {
|
||||
|
@ -173,7 +173,8 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
|
||||
return set_validity_icpt(scb_s, 0x0039U);
|
||||
|
||||
/* copy only the wrapping keys */
|
||||
if (read_guest_real(vcpu, crycb_addr + 72, &vsie_page->crycb, 56))
|
||||
if (read_guest_real(vcpu, crycb_addr + 72,
|
||||
vsie_page->crycb.dea_wrapping_key_mask, 56))
|
||||
return set_validity_icpt(scb_s, 0x0035U);
|
||||
|
||||
scb_s->ecb3 |= ecb3_flags;
|
||||
|
@ -80,11 +80,11 @@ static __always_inline void arch_atomic_sub(int i, atomic_t *v)
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define arch_atomic_sub_and_test arch_atomic_sub_and_test
|
||||
static __always_inline bool arch_atomic_sub_and_test(int i, atomic_t *v)
|
||||
{
|
||||
GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", e);
|
||||
}
|
||||
#define arch_atomic_sub_and_test arch_atomic_sub_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic_inc - increment atomic variable
|
||||
@ -92,12 +92,12 @@ static __always_inline bool arch_atomic_sub_and_test(int i, atomic_t *v)
|
||||
*
|
||||
* Atomically increments @v by 1.
|
||||
*/
|
||||
#define arch_atomic_inc arch_atomic_inc
|
||||
static __always_inline void arch_atomic_inc(atomic_t *v)
|
||||
{
|
||||
asm volatile(LOCK_PREFIX "incl %0"
|
||||
: "+m" (v->counter));
|
||||
}
|
||||
#define arch_atomic_inc arch_atomic_inc
|
||||
|
||||
/**
|
||||
* arch_atomic_dec - decrement atomic variable
|
||||
@ -105,12 +105,12 @@ static __always_inline void arch_atomic_inc(atomic_t *v)
|
||||
*
|
||||
* Atomically decrements @v by 1.
|
||||
*/
|
||||
#define arch_atomic_dec arch_atomic_dec
|
||||
static __always_inline void arch_atomic_dec(atomic_t *v)
|
||||
{
|
||||
asm volatile(LOCK_PREFIX "decl %0"
|
||||
: "+m" (v->counter));
|
||||
}
|
||||
#define arch_atomic_dec arch_atomic_dec
|
||||
|
||||
/**
|
||||
* arch_atomic_dec_and_test - decrement and test
|
||||
@ -120,11 +120,11 @@ static __always_inline void arch_atomic_dec(atomic_t *v)
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
#define arch_atomic_dec_and_test arch_atomic_dec_and_test
|
||||
static __always_inline bool arch_atomic_dec_and_test(atomic_t *v)
|
||||
{
|
||||
GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", e);
|
||||
}
|
||||
#define arch_atomic_dec_and_test arch_atomic_dec_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic_inc_and_test - increment and test
|
||||
@ -134,11 +134,11 @@ static __always_inline bool arch_atomic_dec_and_test(atomic_t *v)
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define arch_atomic_inc_and_test arch_atomic_inc_and_test
|
||||
static __always_inline bool arch_atomic_inc_and_test(atomic_t *v)
|
||||
{
|
||||
GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", e);
|
||||
}
|
||||
#define arch_atomic_inc_and_test arch_atomic_inc_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic_add_negative - add and test if negative
|
||||
@ -149,11 +149,11 @@ static __always_inline bool arch_atomic_inc_and_test(atomic_t *v)
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
#define arch_atomic_add_negative arch_atomic_add_negative
|
||||
static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v)
|
||||
{
|
||||
GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", s);
|
||||
}
|
||||
#define arch_atomic_add_negative arch_atomic_add_negative
|
||||
|
||||
/**
|
||||
* arch_atomic_add_return - add integer and return
|
||||
|
@ -205,12 +205,12 @@ static inline long long arch_atomic64_sub(long long i, atomic64_t *v)
|
||||
*
|
||||
* Atomically increments @v by 1.
|
||||
*/
|
||||
#define arch_atomic64_inc arch_atomic64_inc
|
||||
static inline void arch_atomic64_inc(atomic64_t *v)
|
||||
{
|
||||
__alternative_atomic64(inc, inc_return, /* no output */,
|
||||
"S" (v) : "memory", "eax", "ecx", "edx");
|
||||
}
|
||||
#define arch_atomic64_inc arch_atomic64_inc
|
||||
|
||||
/**
|
||||
* arch_atomic64_dec - decrement atomic64 variable
|
||||
@ -218,12 +218,12 @@ static inline void arch_atomic64_inc(atomic64_t *v)
|
||||
*
|
||||
* Atomically decrements @v by 1.
|
||||
*/
|
||||
#define arch_atomic64_dec arch_atomic64_dec
|
||||
static inline void arch_atomic64_dec(atomic64_t *v)
|
||||
{
|
||||
__alternative_atomic64(dec, dec_return, /* no output */,
|
||||
"S" (v) : "memory", "eax", "ecx", "edx");
|
||||
}
|
||||
#define arch_atomic64_dec arch_atomic64_dec
|
||||
|
||||
/**
|
||||
* arch_atomic64_add_unless - add unless the number is a given value
|
||||
@ -245,7 +245,6 @@ static inline int arch_atomic64_add_unless(atomic64_t *v, long long a,
|
||||
return (int)a;
|
||||
}
|
||||
|
||||
#define arch_atomic64_inc_not_zero arch_atomic64_inc_not_zero
|
||||
static inline int arch_atomic64_inc_not_zero(atomic64_t *v)
|
||||
{
|
||||
int r;
|
||||
@ -253,8 +252,8 @@ static inline int arch_atomic64_inc_not_zero(atomic64_t *v)
|
||||
"S" (v) : "ecx", "edx", "memory");
|
||||
return r;
|
||||
}
|
||||
#define arch_atomic64_inc_not_zero arch_atomic64_inc_not_zero
|
||||
|
||||
#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
|
||||
static inline long long arch_atomic64_dec_if_positive(atomic64_t *v)
|
||||
{
|
||||
long long r;
|
||||
@ -262,6 +261,7 @@ static inline long long arch_atomic64_dec_if_positive(atomic64_t *v)
|
||||
"S" (v) : "ecx", "memory");
|
||||
return r;
|
||||
}
|
||||
#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
|
||||
|
||||
#undef alternative_atomic64
|
||||
#undef __alternative_atomic64
|
||||
|
@ -71,11 +71,11 @@ static inline void arch_atomic64_sub(long i, atomic64_t *v)
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define arch_atomic64_sub_and_test arch_atomic64_sub_and_test
|
||||
static inline bool arch_atomic64_sub_and_test(long i, atomic64_t *v)
|
||||
{
|
||||
GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", e);
|
||||
}
|
||||
#define arch_atomic64_sub_and_test arch_atomic64_sub_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic64_inc - increment atomic64 variable
|
||||
@ -83,13 +83,13 @@ static inline bool arch_atomic64_sub_and_test(long i, atomic64_t *v)
|
||||
*
|
||||
* Atomically increments @v by 1.
|
||||
*/
|
||||
#define arch_atomic64_inc arch_atomic64_inc
|
||||
static __always_inline void arch_atomic64_inc(atomic64_t *v)
|
||||
{
|
||||
asm volatile(LOCK_PREFIX "incq %0"
|
||||
: "=m" (v->counter)
|
||||
: "m" (v->counter));
|
||||
}
|
||||
#define arch_atomic64_inc arch_atomic64_inc
|
||||
|
||||
/**
|
||||
* arch_atomic64_dec - decrement atomic64 variable
|
||||
@ -97,13 +97,13 @@ static __always_inline void arch_atomic64_inc(atomic64_t *v)
|
||||
*
|
||||
* Atomically decrements @v by 1.
|
||||
*/
|
||||
#define arch_atomic64_dec arch_atomic64_dec
|
||||
static __always_inline void arch_atomic64_dec(atomic64_t *v)
|
||||
{
|
||||
asm volatile(LOCK_PREFIX "decq %0"
|
||||
: "=m" (v->counter)
|
||||
: "m" (v->counter));
|
||||
}
|
||||
#define arch_atomic64_dec arch_atomic64_dec
|
||||
|
||||
/**
|
||||
* arch_atomic64_dec_and_test - decrement and test
|
||||
@ -113,11 +113,11 @@ static __always_inline void arch_atomic64_dec(atomic64_t *v)
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
#define arch_atomic64_dec_and_test arch_atomic64_dec_and_test
|
||||
static inline bool arch_atomic64_dec_and_test(atomic64_t *v)
|
||||
{
|
||||
GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", e);
|
||||
}
|
||||
#define arch_atomic64_dec_and_test arch_atomic64_dec_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic64_inc_and_test - increment and test
|
||||
@ -127,11 +127,11 @@ static inline bool arch_atomic64_dec_and_test(atomic64_t *v)
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define arch_atomic64_inc_and_test arch_atomic64_inc_and_test
|
||||
static inline bool arch_atomic64_inc_and_test(atomic64_t *v)
|
||||
{
|
||||
GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", e);
|
||||
}
|
||||
#define arch_atomic64_inc_and_test arch_atomic64_inc_and_test
|
||||
|
||||
/**
|
||||
* arch_atomic64_add_negative - add and test if negative
|
||||
@ -142,11 +142,11 @@ static inline bool arch_atomic64_inc_and_test(atomic64_t *v)
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
#define arch_atomic64_add_negative arch_atomic64_add_negative
|
||||
static inline bool arch_atomic64_add_negative(long i, atomic64_t *v)
|
||||
{
|
||||
GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", s);
|
||||
}
|
||||
#define arch_atomic64_add_negative arch_atomic64_add_negative
|
||||
|
||||
/**
|
||||
* arch_atomic64_add_return - add and return
|
||||
|
@ -22,10 +22,20 @@ enum die_val {
|
||||
DIE_NMIUNKNOWN,
|
||||
};
|
||||
|
||||
enum show_regs_mode {
|
||||
SHOW_REGS_SHORT,
|
||||
/*
|
||||
* For when userspace crashed, but we don't think it's our fault, and
|
||||
* therefore don't print kernel registers.
|
||||
*/
|
||||
SHOW_REGS_USER,
|
||||
SHOW_REGS_ALL
|
||||
};
|
||||
|
||||
extern void die(const char *, struct pt_regs *,long);
|
||||
extern int __must_check __die(const char *, struct pt_regs *, long);
|
||||
extern void show_stack_regs(struct pt_regs *regs);
|
||||
extern void __show_regs(struct pt_regs *regs, int all);
|
||||
extern void __show_regs(struct pt_regs *regs, enum show_regs_mode);
|
||||
extern void show_iret_regs(struct pt_regs *regs);
|
||||
extern unsigned long oops_begin(void);
|
||||
extern void oops_end(unsigned long, struct pt_regs *, int signr);
|
||||
|
@ -1237,19 +1237,12 @@ enum emulation_result {
|
||||
#define EMULTYPE_NO_DECODE (1 << 0)
|
||||
#define EMULTYPE_TRAP_UD (1 << 1)
|
||||
#define EMULTYPE_SKIP (1 << 2)
|
||||
#define EMULTYPE_RETRY (1 << 3)
|
||||
#define EMULTYPE_NO_REEXECUTE (1 << 4)
|
||||
#define EMULTYPE_NO_UD_ON_FAIL (1 << 5)
|
||||
#define EMULTYPE_VMWARE (1 << 6)
|
||||
int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
|
||||
int emulation_type, void *insn, int insn_len);
|
||||
|
||||
static inline int emulate_instruction(struct kvm_vcpu *vcpu,
|
||||
int emulation_type)
|
||||
{
|
||||
return x86_emulate_instruction(vcpu, 0,
|
||||
emulation_type | EMULTYPE_NO_REEXECUTE, NULL, 0);
|
||||
}
|
||||
#define EMULTYPE_ALLOW_RETRY (1 << 3)
|
||||
#define EMULTYPE_NO_UD_ON_FAIL (1 << 4)
|
||||
#define EMULTYPE_VMWARE (1 << 5)
|
||||
int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
|
||||
int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
|
||||
void *insn, int insn_len);
|
||||
|
||||
void kvm_enable_efer_bits(u64);
|
||||
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
|
||||
@ -1450,7 +1443,6 @@ asmlinkage void kvm_spurious_fault(void);
|
||||
____kvm_handle_fault_on_reboot(insn, "")
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end);
|
||||
int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
|
||||
int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
|
||||
@ -1463,7 +1455,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
|
||||
void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu);
|
||||
|
||||
int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
|
||||
unsigned long ipi_bitmap_high, int min,
|
||||
unsigned long ipi_bitmap_high, u32 min,
|
||||
unsigned long icr, int op_64_bit);
|
||||
|
||||
u64 kvm_get_arch_capabilities(void);
|
||||
|
@ -1195,7 +1195,7 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
|
||||
return xchg(pmdp, pmd);
|
||||
} else {
|
||||
pmd_t old = *pmdp;
|
||||
*pmdp = pmd;
|
||||
WRITE_ONCE(*pmdp, pmd);
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
@ -55,15 +55,15 @@ struct mm_struct;
|
||||
void set_pte_vaddr_p4d(p4d_t *p4d_page, unsigned long vaddr, pte_t new_pte);
|
||||
void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte);
|
||||
|
||||
static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
WRITE_ONCE(*ptep, pte);
|
||||
}
|
||||
|
||||
static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
*ptep = native_make_pte(0);
|
||||
}
|
||||
|
||||
static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
*ptep = pte;
|
||||
native_set_pte(ptep, native_make_pte(0));
|
||||
}
|
||||
|
||||
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
@ -73,7 +73,7 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
|
||||
static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
|
||||
{
|
||||
*pmdp = pmd;
|
||||
WRITE_ONCE(*pmdp, pmd);
|
||||
}
|
||||
|
||||
static inline void native_pmd_clear(pmd_t *pmd)
|
||||
@ -109,7 +109,7 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
|
||||
|
||||
static inline void native_set_pud(pud_t *pudp, pud_t pud)
|
||||
{
|
||||
*pudp = pud;
|
||||
WRITE_ONCE(*pudp, pud);
|
||||
}
|
||||
|
||||
static inline void native_pud_clear(pud_t *pud)
|
||||
@ -137,13 +137,13 @@ static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
|
||||
pgd_t pgd;
|
||||
|
||||
if (pgtable_l5_enabled() || !IS_ENABLED(CONFIG_PAGE_TABLE_ISOLATION)) {
|
||||
*p4dp = p4d;
|
||||
WRITE_ONCE(*p4dp, p4d);
|
||||
return;
|
||||
}
|
||||
|
||||
pgd = native_make_pgd(native_p4d_val(p4d));
|
||||
pgd = pti_set_user_pgtbl((pgd_t *)p4dp, pgd);
|
||||
*p4dp = native_make_p4d(native_pgd_val(pgd));
|
||||
WRITE_ONCE(*p4dp, native_make_p4d(native_pgd_val(pgd)));
|
||||
}
|
||||
|
||||
static inline void native_p4d_clear(p4d_t *p4d)
|
||||
@ -153,7 +153,7 @@ static inline void native_p4d_clear(p4d_t *p4d)
|
||||
|
||||
static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
|
||||
{
|
||||
*pgdp = pti_set_user_pgtbl(pgdp, pgd);
|
||||
WRITE_ONCE(*pgdp, pti_set_user_pgtbl(pgdp, pgd));
|
||||
}
|
||||
|
||||
static inline void native_pgd_clear(pgd_t *pgd)
|
||||
|
@ -413,7 +413,7 @@ static int activate_managed(struct irq_data *irqd)
|
||||
if (WARN_ON_ONCE(cpumask_empty(vector_searchmask))) {
|
||||
/* Something in the core code broke! Survive gracefully */
|
||||
pr_err("Managed startup for irq %u, but no CPU\n", irqd->irq);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = assign_managed_vector(irqd, vector_searchmask);
|
||||
|
@ -504,6 +504,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
|
||||
struct microcode_amd *mc_amd;
|
||||
struct ucode_cpu_info *uci;
|
||||
struct ucode_patch *p;
|
||||
enum ucode_state ret;
|
||||
u32 rev, dummy;
|
||||
|
||||
BUG_ON(raw_smp_processor_id() != cpu);
|
||||
@ -521,9 +522,8 @@ static enum ucode_state apply_microcode_amd(int cpu)
|
||||
|
||||
/* need to apply patch? */
|
||||
if (rev >= mc_amd->hdr.patch_id) {
|
||||
c->microcode = rev;
|
||||
uci->cpu_sig.rev = rev;
|
||||
return UCODE_OK;
|
||||
ret = UCODE_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (__apply_microcode_amd(mc_amd)) {
|
||||
@ -531,13 +531,21 @@ static enum ucode_state apply_microcode_amd(int cpu)
|
||||
cpu, mc_amd->hdr.patch_id);
|
||||
return UCODE_ERROR;
|
||||
}
|
||||
pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
|
||||
mc_amd->hdr.patch_id);
|
||||
|
||||
uci->cpu_sig.rev = mc_amd->hdr.patch_id;
|
||||
c->microcode = mc_amd->hdr.patch_id;
|
||||
rev = mc_amd->hdr.patch_id;
|
||||
ret = UCODE_UPDATED;
|
||||
|
||||
return UCODE_UPDATED;
|
||||
pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
|
||||
|
||||
out:
|
||||
uci->cpu_sig.rev = rev;
|
||||
c->microcode = rev;
|
||||
|
||||
/* Update boot_cpu_data's revision too, if we're on the BSP: */
|
||||
if (c->cpu_index == boot_cpu_data.cpu_index)
|
||||
boot_cpu_data.microcode = rev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int install_equiv_cpu_table(const u8 *buf)
|
||||
|
@ -795,6 +795,7 @@ static enum ucode_state apply_microcode_intel(int cpu)
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
struct microcode_intel *mc;
|
||||
enum ucode_state ret;
|
||||
static int prev_rev;
|
||||
u32 rev;
|
||||
|
||||
@ -817,9 +818,8 @@ static enum ucode_state apply_microcode_intel(int cpu)
|
||||
*/
|
||||
rev = intel_get_microcode_revision();
|
||||
if (rev >= mc->hdr.rev) {
|
||||
uci->cpu_sig.rev = rev;
|
||||
c->microcode = rev;
|
||||
return UCODE_OK;
|
||||
ret = UCODE_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -848,10 +848,17 @@ static enum ucode_state apply_microcode_intel(int cpu)
|
||||
prev_rev = rev;
|
||||
}
|
||||
|
||||
uci->cpu_sig.rev = rev;
|
||||
c->microcode = rev;
|
||||
ret = UCODE_UPDATED;
|
||||
|
||||
return UCODE_UPDATED;
|
||||
out:
|
||||
uci->cpu_sig.rev = rev;
|
||||
c->microcode = rev;
|
||||
|
||||
/* Update boot_cpu_data's revision too, if we're on the BSP: */
|
||||
if (c->cpu_index == boot_cpu_data.cpu_index)
|
||||
boot_cpu_data.microcode = rev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||
|
@ -146,7 +146,7 @@ static void show_regs_if_on_stack(struct stack_info *info, struct pt_regs *regs,
|
||||
* they can be printed in the right context.
|
||||
*/
|
||||
if (!partial && on_stack(info, regs, sizeof(*regs))) {
|
||||
__show_regs(regs, 0);
|
||||
__show_regs(regs, SHOW_REGS_SHORT);
|
||||
|
||||
} else if (partial && on_stack(info, (void *)regs + IRET_FRAME_OFFSET,
|
||||
IRET_FRAME_SIZE)) {
|
||||
@ -344,7 +344,7 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
||||
oops_exit();
|
||||
|
||||
/* Executive summary in case the oops scrolled away */
|
||||
__show_regs(&exec_summary_regs, true);
|
||||
__show_regs(&exec_summary_regs, SHOW_REGS_ALL);
|
||||
|
||||
if (!signr)
|
||||
return;
|
||||
@ -407,14 +407,9 @@ void die(const char *str, struct pt_regs *regs, long err)
|
||||
|
||||
void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
bool all = true;
|
||||
|
||||
show_regs_print_info(KERN_DEFAULT);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_32))
|
||||
all = !user_mode(regs);
|
||||
|
||||
__show_regs(regs, all);
|
||||
__show_regs(regs, user_mode(regs) ? SHOW_REGS_USER : SHOW_REGS_ALL);
|
||||
|
||||
/*
|
||||
* When in-kernel, we also print out the stack at the time of the fault..
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include <asm/intel_rdt_sched.h>
|
||||
#include <asm/proto.h>
|
||||
|
||||
void __show_regs(struct pt_regs *regs, int all)
|
||||
void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
|
||||
{
|
||||
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
|
||||
unsigned long d0, d1, d2, d3, d6, d7;
|
||||
@ -85,7 +85,7 @@ void __show_regs(struct pt_regs *regs, int all)
|
||||
printk(KERN_DEFAULT "DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x EFLAGS: %08lx\n",
|
||||
(u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss, regs->flags);
|
||||
|
||||
if (!all)
|
||||
if (mode != SHOW_REGS_ALL)
|
||||
return;
|
||||
|
||||
cr0 = read_cr0();
|
||||
|
@ -62,7 +62,7 @@
|
||||
__visible DEFINE_PER_CPU(unsigned long, rsp_scratch);
|
||||
|
||||
/* Prints also some state that isn't saved in the pt_regs */
|
||||
void __show_regs(struct pt_regs *regs, int all)
|
||||
void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
|
||||
{
|
||||
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
|
||||
unsigned long d0, d1, d2, d3, d6, d7;
|
||||
@ -87,9 +87,17 @@ void __show_regs(struct pt_regs *regs, int all)
|
||||
printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n",
|
||||
regs->r13, regs->r14, regs->r15);
|
||||
|
||||
if (!all)
|
||||
if (mode == SHOW_REGS_SHORT)
|
||||
return;
|
||||
|
||||
if (mode == SHOW_REGS_USER) {
|
||||
rdmsrl(MSR_FS_BASE, fs);
|
||||
rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
|
||||
printk(KERN_DEFAULT "FS: %016lx GS: %016lx\n",
|
||||
fs, shadowgs);
|
||||
return;
|
||||
}
|
||||
|
||||
asm("movl %%ds,%0" : "=r" (ds));
|
||||
asm("movl %%cs,%0" : "=r" (cs));
|
||||
asm("movl %%es,%0" : "=r" (es));
|
||||
|
@ -1415,7 +1415,7 @@ static bool __init determine_cpu_tsc_frequencies(bool early)
|
||||
|
||||
static unsigned long __init get_loops_per_jiffy(void)
|
||||
{
|
||||
unsigned long lpj = tsc_khz * KHZ;
|
||||
u64 lpj = (u64)tsc_khz * KHZ;
|
||||
|
||||
do_div(lpj, HZ);
|
||||
return lpj;
|
||||
|
@ -548,7 +548,7 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
|
||||
}
|
||||
|
||||
int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
|
||||
unsigned long ipi_bitmap_high, int min,
|
||||
unsigned long ipi_bitmap_high, u32 min,
|
||||
unsigned long icr, int op_64_bit)
|
||||
{
|
||||
int i;
|
||||
@ -571,18 +571,31 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
|
||||
rcu_read_lock();
|
||||
map = rcu_dereference(kvm->arch.apic_map);
|
||||
|
||||
if (min > map->max_apic_id)
|
||||
goto out;
|
||||
/* Bits above cluster_size are masked in the caller. */
|
||||
for_each_set_bit(i, &ipi_bitmap_low, BITS_PER_LONG) {
|
||||
vcpu = map->phys_map[min + i]->vcpu;
|
||||
count += kvm_apic_set_irq(vcpu, &irq, NULL);
|
||||
for_each_set_bit(i, &ipi_bitmap_low,
|
||||
min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) {
|
||||
if (map->phys_map[min + i]) {
|
||||
vcpu = map->phys_map[min + i]->vcpu;
|
||||
count += kvm_apic_set_irq(vcpu, &irq, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
min += cluster_size;
|
||||
for_each_set_bit(i, &ipi_bitmap_high, BITS_PER_LONG) {
|
||||
vcpu = map->phys_map[min + i]->vcpu;
|
||||
count += kvm_apic_set_irq(vcpu, &irq, NULL);
|
||||
|
||||
if (min > map->max_apic_id)
|
||||
goto out;
|
||||
|
||||
for_each_set_bit(i, &ipi_bitmap_high,
|
||||
min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) {
|
||||
if (map->phys_map[min + i]) {
|
||||
vcpu = map->phys_map[min + i]->vcpu;
|
||||
count += kvm_apic_set_irq(vcpu, &irq, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return count;
|
||||
}
|
||||
|
@ -1853,11 +1853,6 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
|
||||
return kvm_handle_hva_range(kvm, hva, hva + 1, data, handler);
|
||||
}
|
||||
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
|
||||
{
|
||||
return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp);
|
||||
}
|
||||
|
||||
int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
|
||||
{
|
||||
return kvm_handle_hva_range(kvm, start, end, 0, kvm_unmap_rmapp);
|
||||
@ -5217,7 +5212,7 @@ static int make_mmu_pages_available(struct kvm_vcpu *vcpu)
|
||||
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
|
||||
void *insn, int insn_len)
|
||||
{
|
||||
int r, emulation_type = EMULTYPE_RETRY;
|
||||
int r, emulation_type = 0;
|
||||
enum emulation_result er;
|
||||
bool direct = vcpu->arch.mmu.direct_map;
|
||||
|
||||
@ -5230,10 +5225,8 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
|
||||
r = RET_PF_INVALID;
|
||||
if (unlikely(error_code & PFERR_RSVD_MASK)) {
|
||||
r = handle_mmio_page_fault(vcpu, cr2, direct);
|
||||
if (r == RET_PF_EMULATE) {
|
||||
emulation_type = 0;
|
||||
if (r == RET_PF_EMULATE)
|
||||
goto emulate;
|
||||
}
|
||||
}
|
||||
|
||||
if (r == RET_PF_INVALID) {
|
||||
@ -5260,8 +5253,19 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mmio_info_in_cache(vcpu, cr2, direct))
|
||||
emulation_type = 0;
|
||||
/*
|
||||
* vcpu->arch.mmu.page_fault returned RET_PF_EMULATE, but we can still
|
||||
* optimistically try to just unprotect the page and let the processor
|
||||
* re-execute the instruction that caused the page fault. Do not allow
|
||||
* retrying MMIO emulation, as it's not only pointless but could also
|
||||
* cause us to enter an infinite loop because the processor will keep
|
||||
* faulting on the non-existent MMIO address. Retrying an instruction
|
||||
* from a nested guest is also pointless and dangerous as we are only
|
||||
* explicitly shadowing L1's page tables, i.e. unprotecting something
|
||||
* for L1 isn't going to magically fix whatever issue cause L2 to fail.
|
||||
*/
|
||||
if (!mmio_info_in_cache(vcpu, cr2, direct) && !is_guest_mode(vcpu))
|
||||
emulation_type = EMULTYPE_ALLOW_RETRY;
|
||||
emulate:
|
||||
/*
|
||||
* On AMD platforms, under certain conditions insn_len may be zero on #NPF.
|
||||
|
@ -776,7 +776,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
if (!svm->next_rip) {
|
||||
if (emulate_instruction(vcpu, EMULTYPE_SKIP) !=
|
||||
if (kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) !=
|
||||
EMULATE_DONE)
|
||||
printk(KERN_DEBUG "%s: NOP\n", __func__);
|
||||
return;
|
||||
@ -2715,7 +2715,7 @@ static int gp_interception(struct vcpu_svm *svm)
|
||||
|
||||
WARN_ON_ONCE(!enable_vmware_backdoor);
|
||||
|
||||
er = emulate_instruction(vcpu,
|
||||
er = kvm_emulate_instruction(vcpu,
|
||||
EMULTYPE_VMWARE | EMULTYPE_NO_UD_ON_FAIL);
|
||||
if (er == EMULATE_USER_EXIT)
|
||||
return 0;
|
||||
@ -2819,7 +2819,7 @@ static int io_interception(struct vcpu_svm *svm)
|
||||
string = (io_info & SVM_IOIO_STR_MASK) != 0;
|
||||
in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
|
||||
if (string)
|
||||
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
|
||||
port = io_info >> 16;
|
||||
size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
|
||||
@ -3861,7 +3861,7 @@ static int iret_interception(struct vcpu_svm *svm)
|
||||
static int invlpg_interception(struct vcpu_svm *svm)
|
||||
{
|
||||
if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
|
||||
return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
|
||||
|
||||
kvm_mmu_invlpg(&svm->vcpu, svm->vmcb->control.exit_info_1);
|
||||
return kvm_skip_emulated_instruction(&svm->vcpu);
|
||||
@ -3869,13 +3869,13 @@ static int invlpg_interception(struct vcpu_svm *svm)
|
||||
|
||||
static int emulate_on_interception(struct vcpu_svm *svm)
|
||||
{
|
||||
return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int rsm_interception(struct vcpu_svm *svm)
|
||||
{
|
||||
return x86_emulate_instruction(&svm->vcpu, 0, 0,
|
||||
rsm_ins_bytes, 2) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction_from_buffer(&svm->vcpu,
|
||||
rsm_ins_bytes, 2) == EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int rdpmc_interception(struct vcpu_svm *svm)
|
||||
@ -4700,7 +4700,7 @@ static int avic_unaccelerated_access_interception(struct vcpu_svm *svm)
|
||||
ret = avic_unaccel_trap_write(svm);
|
||||
} else {
|
||||
/* Handling Fault */
|
||||
ret = (emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE);
|
||||
ret = (kvm_emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -6747,7 +6747,7 @@ e_free:
|
||||
static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec)
|
||||
{
|
||||
unsigned long vaddr, vaddr_end, next_vaddr;
|
||||
unsigned long dst_vaddr, dst_vaddr_end;
|
||||
unsigned long dst_vaddr;
|
||||
struct page **src_p, **dst_p;
|
||||
struct kvm_sev_dbg debug;
|
||||
unsigned long n;
|
||||
@ -6763,7 +6763,6 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec)
|
||||
size = debug.len;
|
||||
vaddr_end = vaddr + size;
|
||||
dst_vaddr = debug.dst_uaddr;
|
||||
dst_vaddr_end = dst_vaddr + size;
|
||||
|
||||
for (; vaddr < vaddr_end; vaddr = next_vaddr) {
|
||||
int len, s_off, d_off;
|
||||
|
@ -6983,7 +6983,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
|
||||
* Cause the #SS fault with 0 error code in VM86 mode.
|
||||
*/
|
||||
if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) {
|
||||
if (emulate_instruction(vcpu, 0) == EMULATE_DONE) {
|
||||
if (kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE) {
|
||||
if (vcpu->arch.halt_request) {
|
||||
vcpu->arch.halt_request = 0;
|
||||
return kvm_vcpu_halt(vcpu);
|
||||
@ -7054,7 +7054,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
|
||||
|
||||
if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) {
|
||||
WARN_ON_ONCE(!enable_vmware_backdoor);
|
||||
er = emulate_instruction(vcpu,
|
||||
er = kvm_emulate_instruction(vcpu,
|
||||
EMULTYPE_VMWARE | EMULTYPE_NO_UD_ON_FAIL);
|
||||
if (er == EMULATE_USER_EXIT)
|
||||
return 0;
|
||||
@ -7157,7 +7157,7 @@ static int handle_io(struct kvm_vcpu *vcpu)
|
||||
++vcpu->stat.io_exits;
|
||||
|
||||
if (string)
|
||||
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
|
||||
port = exit_qualification >> 16;
|
||||
size = (exit_qualification & 7) + 1;
|
||||
@ -7231,7 +7231,7 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
|
||||
static int handle_desc(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
|
||||
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int handle_cr(struct kvm_vcpu *vcpu)
|
||||
@ -7480,7 +7480,7 @@ static int handle_vmcall(struct kvm_vcpu *vcpu)
|
||||
|
||||
static int handle_invd(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int handle_invlpg(struct kvm_vcpu *vcpu)
|
||||
@ -7547,7 +7547,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
}
|
||||
}
|
||||
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
|
||||
@ -7704,8 +7704,8 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
|
||||
if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
else
|
||||
return x86_emulate_instruction(vcpu, gpa, EMULTYPE_SKIP,
|
||||
NULL, 0) == EMULATE_DONE;
|
||||
return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) ==
|
||||
EMULATE_DONE;
|
||||
}
|
||||
|
||||
return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0);
|
||||
@ -7748,7 +7748,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
|
||||
if (kvm_test_request(KVM_REQ_EVENT, vcpu))
|
||||
return 1;
|
||||
|
||||
err = emulate_instruction(vcpu, 0);
|
||||
err = kvm_emulate_instruction(vcpu, 0);
|
||||
|
||||
if (err == EMULATE_USER_EXIT) {
|
||||
++vcpu->stat.mmio_exits;
|
||||
@ -12537,8 +12537,11 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
|
||||
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
|
||||
bool from_vmentry = !!exit_qual;
|
||||
u32 dummy_exit_qual;
|
||||
u32 vmcs01_cpu_exec_ctrl;
|
||||
int r = 0;
|
||||
|
||||
vmcs01_cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
|
||||
|
||||
enter_guest_mode(vcpu);
|
||||
|
||||
if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
|
||||
@ -12574,6 +12577,25 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
|
||||
kvm_make_request(KVM_REQ_GET_VMCS12_PAGES, vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* If L1 had a pending IRQ/NMI until it executed
|
||||
* VMLAUNCH/VMRESUME which wasn't delivered because it was
|
||||
* disallowed (e.g. interrupts disabled), L0 needs to
|
||||
* evaluate if this pending event should cause an exit from L2
|
||||
* to L1 or delivered directly to L2 (e.g. In case L1 don't
|
||||
* intercept EXTERNAL_INTERRUPT).
|
||||
*
|
||||
* Usually this would be handled by L0 requesting a
|
||||
* IRQ/NMI window by setting VMCS accordingly. However,
|
||||
* this setting was done on VMCS01 and now VMCS02 is active
|
||||
* instead. Thus, we force L0 to perform pending event
|
||||
* evaluation by requesting a KVM_REQ_EVENT.
|
||||
*/
|
||||
if (vmcs01_cpu_exec_ctrl &
|
||||
(CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_VIRTUAL_NMI_PENDING)) {
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note no nested_vmx_succeed or nested_vmx_fail here. At this point
|
||||
* we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
|
||||
@ -13988,9 +14010,6 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
|
||||
check_vmentry_postreqs(vcpu, vmcs12, &exit_qual))
|
||||
return -EINVAL;
|
||||
|
||||
if (kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING)
|
||||
vmx->nested.nested_run_pending = 1;
|
||||
|
||||
vmx->nested.dirty_vmcs12 = true;
|
||||
ret = enter_vmx_non_root_mode(vcpu, NULL);
|
||||
if (ret)
|
||||
|
@ -4987,7 +4987,7 @@ int handle_ud(struct kvm_vcpu *vcpu)
|
||||
emul_type = 0;
|
||||
}
|
||||
|
||||
er = emulate_instruction(vcpu, emul_type);
|
||||
er = kvm_emulate_instruction(vcpu, emul_type);
|
||||
if (er == EMULATE_USER_EXIT)
|
||||
return 0;
|
||||
if (er != EMULATE_DONE)
|
||||
@ -5870,7 +5870,10 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2,
|
||||
gpa_t gpa = cr2;
|
||||
kvm_pfn_t pfn;
|
||||
|
||||
if (emulation_type & EMULTYPE_NO_REEXECUTE)
|
||||
if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
|
||||
return false;
|
||||
|
||||
if (WARN_ON_ONCE(is_guest_mode(vcpu)))
|
||||
return false;
|
||||
|
||||
if (!vcpu->arch.mmu.direct_map) {
|
||||
@ -5958,7 +5961,10 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
|
||||
*/
|
||||
vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0;
|
||||
|
||||
if (!(emulation_type & EMULTYPE_RETRY))
|
||||
if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
|
||||
return false;
|
||||
|
||||
if (WARN_ON_ONCE(is_guest_mode(vcpu)))
|
||||
return false;
|
||||
|
||||
if (x86_page_table_writing_insn(ctxt))
|
||||
@ -6276,7 +6282,19 @@ restart:
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x86_emulate_instruction);
|
||||
|
||||
int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type)
|
||||
{
|
||||
return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_emulate_instruction);
|
||||
|
||||
int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
|
||||
void *insn, int insn_len)
|
||||
{
|
||||
return x86_emulate_instruction(vcpu, 0, 0, insn, insn_len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer);
|
||||
|
||||
static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size,
|
||||
unsigned short port)
|
||||
@ -7734,7 +7752,7 @@ static inline int complete_emulated_io(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int r;
|
||||
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
|
||||
r = kvm_emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
|
||||
if (r != EMULATE_DONE)
|
||||
return 0;
|
||||
|
@ -274,6 +274,8 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
|
||||
bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn,
|
||||
int page_num);
|
||||
bool kvm_vector_hashing_enabled(void);
|
||||
int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
|
||||
int emulation_type, void *insn, int insn_len);
|
||||
|
||||
#define KVM_SUPPORTED_XCR0 (XFEATURE_MASK_FP | XFEATURE_MASK_SSE \
|
||||
| XFEATURE_MASK_YMM | XFEATURE_MASK_BNDREGS \
|
||||
|
@ -269,7 +269,7 @@ static void mop_up_one_pmd(struct mm_struct *mm, pgd_t *pgdp)
|
||||
if (pgd_val(pgd) != 0) {
|
||||
pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
|
||||
|
||||
*pgdp = native_make_pgd(0);
|
||||
pgd_clear(pgdp);
|
||||
|
||||
paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
|
||||
pmd_free(mm, pmd);
|
||||
@ -494,7 +494,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
int changed = !pte_same(*ptep, entry);
|
||||
|
||||
if (changed && dirty)
|
||||
*ptep = entry;
|
||||
set_pte(ptep, entry);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@ -509,7 +509,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma,
|
||||
VM_BUG_ON(address & ~HPAGE_PMD_MASK);
|
||||
|
||||
if (changed && dirty) {
|
||||
*pmdp = entry;
|
||||
set_pmd(pmdp, entry);
|
||||
/*
|
||||
* We had a write-protection fault here and changed the pmd
|
||||
* to to more permissive. No need to flush the TLB for that,
|
||||
@ -529,7 +529,7 @@ int pudp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
|
||||
VM_BUG_ON(address & ~HPAGE_PUD_MASK);
|
||||
|
||||
if (changed && dirty) {
|
||||
*pudp = entry;
|
||||
set_pud(pudp, entry);
|
||||
/*
|
||||
* We had a write-protection fault here and changed the pud
|
||||
* to to more permissive. No need to flush the TLB for that,
|
||||
|
@ -275,9 +275,9 @@ static void bfqg_and_blkg_get(struct bfq_group *bfqg)
|
||||
|
||||
void bfqg_and_blkg_put(struct bfq_group *bfqg)
|
||||
{
|
||||
bfqg_put(bfqg);
|
||||
|
||||
blkg_put(bfqg_to_blkg(bfqg));
|
||||
|
||||
bfqg_put(bfqg);
|
||||
}
|
||||
|
||||
/* @stats = 0 */
|
||||
|
@ -2015,7 +2015,8 @@ int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg)
|
||||
{
|
||||
if (unlikely(bio->bi_blkg))
|
||||
return -EBUSY;
|
||||
blkg_get(blkg);
|
||||
if (!blkg_try_get(blkg))
|
||||
return -ENODEV;
|
||||
bio->bi_blkg = blkg;
|
||||
return 0;
|
||||
}
|
||||
|
@ -310,28 +310,11 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
||||
}
|
||||
}
|
||||
|
||||
static void blkg_pd_offline(struct blkcg_gq *blkg)
|
||||
{
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(blkg->q->queue_lock);
|
||||
lockdep_assert_held(&blkg->blkcg->lock);
|
||||
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && !blkg->pd[i]->offline &&
|
||||
pol->pd_offline_fn) {
|
||||
pol->pd_offline_fn(blkg->pd[i]);
|
||||
blkg->pd[i]->offline = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void blkg_destroy(struct blkcg_gq *blkg)
|
||||
{
|
||||
struct blkcg *blkcg = blkg->blkcg;
|
||||
struct blkcg_gq *parent = blkg->parent;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(blkg->q->queue_lock);
|
||||
lockdep_assert_held(&blkcg->lock);
|
||||
@ -340,6 +323,13 @@ static void blkg_destroy(struct blkcg_gq *blkg)
|
||||
WARN_ON_ONCE(list_empty(&blkg->q_node));
|
||||
WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node));
|
||||
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && pol->pd_offline_fn)
|
||||
pol->pd_offline_fn(blkg->pd[i]);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
blkg_rwstat_add_aux(&parent->stat_bytes, &blkg->stat_bytes);
|
||||
blkg_rwstat_add_aux(&parent->stat_ios, &blkg->stat_ios);
|
||||
@ -382,7 +372,6 @@ static void blkg_destroy_all(struct request_queue *q)
|
||||
struct blkcg *blkcg = blkg->blkcg;
|
||||
|
||||
spin_lock(&blkcg->lock);
|
||||
blkg_pd_offline(blkg);
|
||||
blkg_destroy(blkg);
|
||||
spin_unlock(&blkcg->lock);
|
||||
}
|
||||
@ -1053,59 +1042,64 @@ static struct cftype blkcg_legacy_files[] = {
|
||||
{ } /* terminate */
|
||||
};
|
||||
|
||||
/*
|
||||
* blkcg destruction is a three-stage process.
|
||||
*
|
||||
* 1. Destruction starts. The blkcg_css_offline() callback is invoked
|
||||
* which offlines writeback. Here we tie the next stage of blkg destruction
|
||||
* to the completion of writeback associated with the blkcg. This lets us
|
||||
* avoid punting potentially large amounts of outstanding writeback to root
|
||||
* while maintaining any ongoing policies. The next stage is triggered when
|
||||
* the nr_cgwbs count goes to zero.
|
||||
*
|
||||
* 2. When the nr_cgwbs count goes to zero, blkcg_destroy_blkgs() is called
|
||||
* and handles the destruction of blkgs. Here the css reference held by
|
||||
* the blkg is put back eventually allowing blkcg_css_free() to be called.
|
||||
* This work may occur in cgwb_release_workfn() on the cgwb_release
|
||||
* workqueue. Any submitted ios that fail to get the blkg ref will be
|
||||
* punted to the root_blkg.
|
||||
*
|
||||
* 3. Once the blkcg ref count goes to zero, blkcg_css_free() is called.
|
||||
* This finally frees the blkcg.
|
||||
*/
|
||||
|
||||
/**
|
||||
* blkcg_css_offline - cgroup css_offline callback
|
||||
* @css: css of interest
|
||||
*
|
||||
* This function is called when @css is about to go away and responsible
|
||||
* for offlining all blkgs pd and killing all wbs associated with @css.
|
||||
* blkgs pd offline should be done while holding both q and blkcg locks.
|
||||
* As blkcg lock is nested inside q lock, this function performs reverse
|
||||
* double lock dancing.
|
||||
*
|
||||
* This is the blkcg counterpart of ioc_release_fn().
|
||||
* This function is called when @css is about to go away. Here the cgwbs are
|
||||
* offlined first and only once writeback associated with the blkcg has
|
||||
* finished do we start step 2 (see above).
|
||||
*/
|
||||
static void blkcg_css_offline(struct cgroup_subsys_state *css)
|
||||
{
|
||||
struct blkcg *blkcg = css_to_blkcg(css);
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
|
||||
hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
|
||||
struct request_queue *q = blkg->q;
|
||||
|
||||
if (spin_trylock(q->queue_lock)) {
|
||||
blkg_pd_offline(blkg);
|
||||
spin_unlock(q->queue_lock);
|
||||
} else {
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
cpu_relax();
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
|
||||
/* this prevents anyone from attaching or migrating to this blkcg */
|
||||
wb_blkcg_offline(blkcg);
|
||||
|
||||
/* put the base cgwb reference allowing step 2 to be triggered */
|
||||
blkcg_cgwb_put(blkcg);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_destroy_all_blkgs - destroy all blkgs associated with a blkcg
|
||||
* blkcg_destroy_blkgs - responsible for shooting down blkgs
|
||||
* @blkcg: blkcg of interest
|
||||
*
|
||||
* This function is called when blkcg css is about to free and responsible for
|
||||
* destroying all blkgs associated with @blkcg.
|
||||
* blkgs should be removed while holding both q and blkcg locks. As blkcg lock
|
||||
* blkgs should be removed while holding both q and blkcg locks. As blkcg lock
|
||||
* is nested inside q lock, this function performs reverse double lock dancing.
|
||||
* Destroying the blkgs releases the reference held on the blkcg's css allowing
|
||||
* blkcg_css_free to eventually be called.
|
||||
*
|
||||
* This is the blkcg counterpart of ioc_release_fn().
|
||||
*/
|
||||
static void blkcg_destroy_all_blkgs(struct blkcg *blkcg)
|
||||
void blkcg_destroy_blkgs(struct blkcg *blkcg)
|
||||
{
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
|
||||
while (!hlist_empty(&blkcg->blkg_list)) {
|
||||
struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first,
|
||||
struct blkcg_gq,
|
||||
blkcg_node);
|
||||
struct blkcg_gq, blkcg_node);
|
||||
struct request_queue *q = blkg->q;
|
||||
|
||||
if (spin_trylock(q->queue_lock)) {
|
||||
@ -1117,6 +1111,7 @@ static void blkcg_destroy_all_blkgs(struct blkcg *blkcg)
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
}
|
||||
|
||||
@ -1125,8 +1120,6 @@ static void blkcg_css_free(struct cgroup_subsys_state *css)
|
||||
struct blkcg *blkcg = css_to_blkcg(css);
|
||||
int i;
|
||||
|
||||
blkcg_destroy_all_blkgs(blkcg);
|
||||
|
||||
mutex_lock(&blkcg_pol_mutex);
|
||||
|
||||
list_del(&blkcg->all_blkcgs_node);
|
||||
@ -1189,6 +1182,7 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
|
||||
INIT_HLIST_HEAD(&blkcg->blkg_list);
|
||||
#ifdef CONFIG_CGROUP_WRITEBACK
|
||||
INIT_LIST_HEAD(&blkcg->cgwb_list);
|
||||
refcount_set(&blkcg->cgwb_refcnt, 1);
|
||||
#endif
|
||||
list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs);
|
||||
|
||||
@ -1480,11 +1474,8 @@ void blkcg_deactivate_policy(struct request_queue *q,
|
||||
|
||||
list_for_each_entry(blkg, &q->blkg_list, q_node) {
|
||||
if (blkg->pd[pol->plid]) {
|
||||
if (!blkg->pd[pol->plid]->offline &&
|
||||
pol->pd_offline_fn) {
|
||||
if (pol->pd_offline_fn)
|
||||
pol->pd_offline_fn(blkg->pd[pol->plid]);
|
||||
blkg->pd[pol->plid]->offline = true;
|
||||
}
|
||||
pol->pd_free_fn(blkg->pd[pol->plid]);
|
||||
blkg->pd[pol->plid] = NULL;
|
||||
}
|
||||
|
@ -2163,9 +2163,12 @@ static inline bool bio_check_ro(struct bio *bio, struct hd_struct *part)
|
||||
{
|
||||
const int op = bio_op(bio);
|
||||
|
||||
if (part->policy && (op_is_write(op) && !op_is_flush(op))) {
|
||||
if (part->policy && op_is_write(op)) {
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||
return false;
|
||||
|
||||
WARN_ONCE(1,
|
||||
"generic_make_request: Trying to write "
|
||||
"to read-only block-device %s (partno %d)\n",
|
||||
|
@ -2129,8 +2129,9 @@ static inline void throtl_update_latency_buckets(struct throtl_data *td)
|
||||
static void blk_throtl_assoc_bio(struct throtl_grp *tg, struct bio *bio)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
|
||||
if (bio->bi_css)
|
||||
bio_associate_blkg(bio, tg_to_blkg(tg));
|
||||
/* fallback to root_blkg if we fail to get a blkg ref */
|
||||
if (bio->bi_css && (bio_associate_blkg(bio, tg_to_blkg(tg)) == -ENODEV))
|
||||
bio_associate_blkg(bio, bio->bi_disk->queue->root_blkg);
|
||||
bio_issue_init(&bio->bi_issue, bio_sectors(bio));
|
||||
#endif
|
||||
}
|
||||
|
@ -879,7 +879,7 @@ static void acpi_lpss_dismiss(struct device *dev)
|
||||
#define LPSS_GPIODEF0_DMA_LLP BIT(13)
|
||||
|
||||
static DEFINE_MUTEX(lpss_iosf_mutex);
|
||||
static bool lpss_iosf_d3_entered;
|
||||
static bool lpss_iosf_d3_entered = true;
|
||||
|
||||
static void lpss_iosf_enter_d3_state(void)
|
||||
{
|
||||
|
@ -35,11 +35,11 @@
|
||||
#include <linux/delay.h>
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/mpspec.h>
|
||||
#include <linux/dmi.h>
|
||||
#endif
|
||||
#include <linux/acpi_iort.h>
|
||||
#include <linux/pci.h>
|
||||
#include <acpi/apei.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "internal.h"
|
||||
@ -82,10 +82,6 @@ static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
|
||||
},
|
||||
{}
|
||||
};
|
||||
#else
|
||||
static const struct dmi_system_id dsdt_dmi_table[] __initconst = {
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
@ -1033,11 +1029,16 @@ void __init acpi_early_init(void)
|
||||
|
||||
acpi_permanent_mmap = true;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* If the machine falls into the DMI check table,
|
||||
* DSDT will be copied to memory
|
||||
* DSDT will be copied to memory.
|
||||
* Note that calling dmi_check_system() here on other architectures
|
||||
* would not be OK because only x86 initializes dmi early enough.
|
||||
* Thankfully only x86 systems need such quirks for now.
|
||||
*/
|
||||
dmi_check_system(dsdt_dmi_table);
|
||||
#endif
|
||||
|
||||
status = acpi_reallocate_root_table();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
@ -7394,4 +7394,4 @@ EXPORT_SYMBOL_GPL(ata_cable_unknown);
|
||||
EXPORT_SYMBOL_GPL(ata_cable_ignore);
|
||||
EXPORT_SYMBOL_GPL(ata_cable_sata);
|
||||
EXPORT_SYMBOL_GPL(ata_host_get);
|
||||
EXPORT_SYMBOL_GPL(ata_host_put);
|
||||
EXPORT_SYMBOL_GPL(ata_host_put);
|
||||
|
@ -416,26 +416,24 @@ static ssize_t show_valid_zones(struct device *dev,
|
||||
struct zone *default_zone;
|
||||
int nid;
|
||||
|
||||
/*
|
||||
* The block contains more than one zone can not be offlined.
|
||||
* This can happen e.g. for ZONE_DMA and ZONE_DMA32
|
||||
*/
|
||||
if (!test_pages_in_a_zone(start_pfn, start_pfn + nr_pages, &valid_start_pfn, &valid_end_pfn))
|
||||
return sprintf(buf, "none\n");
|
||||
|
||||
start_pfn = valid_start_pfn;
|
||||
nr_pages = valid_end_pfn - start_pfn;
|
||||
|
||||
/*
|
||||
* Check the existing zone. Make sure that we do that only on the
|
||||
* online nodes otherwise the page_zone is not reliable
|
||||
*/
|
||||
if (mem->state == MEM_ONLINE) {
|
||||
/*
|
||||
* The block contains more than one zone can not be offlined.
|
||||
* This can happen e.g. for ZONE_DMA and ZONE_DMA32
|
||||
*/
|
||||
if (!test_pages_in_a_zone(start_pfn, start_pfn + nr_pages,
|
||||
&valid_start_pfn, &valid_end_pfn))
|
||||
return sprintf(buf, "none\n");
|
||||
start_pfn = valid_start_pfn;
|
||||
strcat(buf, page_zone(pfn_to_page(start_pfn))->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nid = pfn_to_nid(start_pfn);
|
||||
nid = mem->nid;
|
||||
default_zone = zone_for_pfn_range(MMOP_ONLINE_KEEP, nid, start_pfn, nr_pages);
|
||||
strcat(buf, default_zone->name);
|
||||
|
||||
|
@ -1239,6 +1239,9 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
case NBD_SET_SOCK:
|
||||
return nbd_add_socket(nbd, arg, false);
|
||||
case NBD_SET_BLKSIZE:
|
||||
if (!arg || !is_power_of_2(arg) || arg < 512 ||
|
||||
arg > PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
nbd_size_set(nbd, arg,
|
||||
div_s64(config->bytesize, arg));
|
||||
return 0;
|
||||
|
@ -4207,11 +4207,13 @@ static ssize_t rbd_parent_show(struct device *dev,
|
||||
|
||||
count += sprintf(&buf[count], "%s"
|
||||
"pool_id %llu\npool_name %s\n"
|
||||
"pool_ns %s\n"
|
||||
"image_id %s\nimage_name %s\n"
|
||||
"snap_id %llu\nsnap_name %s\n"
|
||||
"overlap %llu\n",
|
||||
!count ? "" : "\n", /* first? */
|
||||
spec->pool_id, spec->pool_name,
|
||||
spec->pool_ns ?: "",
|
||||
spec->image_id, spec->image_name ?: "(unknown)",
|
||||
spec->snap_id, spec->snap_name,
|
||||
rbd_dev->parent_overlap);
|
||||
@ -4584,47 +4586,177 @@ static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
|
||||
&rbd_dev->header.features);
|
||||
}
|
||||
|
||||
struct parent_image_info {
|
||||
u64 pool_id;
|
||||
const char *pool_ns;
|
||||
const char *image_id;
|
||||
u64 snap_id;
|
||||
|
||||
bool has_overlap;
|
||||
u64 overlap;
|
||||
};
|
||||
|
||||
/*
|
||||
* The caller is responsible for @pii.
|
||||
*/
|
||||
static int decode_parent_image_spec(void **p, void *end,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
u8 struct_v;
|
||||
u32 struct_len;
|
||||
int ret;
|
||||
|
||||
ret = ceph_start_decoding(p, end, 1, "ParentImageSpec",
|
||||
&struct_v, &struct_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ceph_decode_64_safe(p, end, pii->pool_id, e_inval);
|
||||
pii->pool_ns = ceph_extract_encoded_string(p, end, NULL, GFP_KERNEL);
|
||||
if (IS_ERR(pii->pool_ns)) {
|
||||
ret = PTR_ERR(pii->pool_ns);
|
||||
pii->pool_ns = NULL;
|
||||
return ret;
|
||||
}
|
||||
pii->image_id = ceph_extract_encoded_string(p, end, NULL, GFP_KERNEL);
|
||||
if (IS_ERR(pii->image_id)) {
|
||||
ret = PTR_ERR(pii->image_id);
|
||||
pii->image_id = NULL;
|
||||
return ret;
|
||||
}
|
||||
ceph_decode_64_safe(p, end, pii->snap_id, e_inval);
|
||||
return 0;
|
||||
|
||||
e_inval:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __get_parent_info(struct rbd_device *rbd_dev,
|
||||
struct page *req_page,
|
||||
struct page *reply_page,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
|
||||
size_t reply_len = PAGE_SIZE;
|
||||
void *p, *end;
|
||||
int ret;
|
||||
|
||||
ret = ceph_osdc_call(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
|
||||
"rbd", "parent_get", CEPH_OSD_FLAG_READ,
|
||||
req_page, sizeof(u64), reply_page, &reply_len);
|
||||
if (ret)
|
||||
return ret == -EOPNOTSUPP ? 1 : ret;
|
||||
|
||||
p = page_address(reply_page);
|
||||
end = p + reply_len;
|
||||
ret = decode_parent_image_spec(&p, end, pii);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ceph_osdc_call(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
|
||||
"rbd", "parent_overlap_get", CEPH_OSD_FLAG_READ,
|
||||
req_page, sizeof(u64), reply_page, &reply_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
p = page_address(reply_page);
|
||||
end = p + reply_len;
|
||||
ceph_decode_8_safe(&p, end, pii->has_overlap, e_inval);
|
||||
if (pii->has_overlap)
|
||||
ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
|
||||
|
||||
return 0;
|
||||
|
||||
e_inval:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller is responsible for @pii.
|
||||
*/
|
||||
static int __get_parent_info_legacy(struct rbd_device *rbd_dev,
|
||||
struct page *req_page,
|
||||
struct page *reply_page,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
|
||||
size_t reply_len = PAGE_SIZE;
|
||||
void *p, *end;
|
||||
int ret;
|
||||
|
||||
ret = ceph_osdc_call(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
|
||||
"rbd", "get_parent", CEPH_OSD_FLAG_READ,
|
||||
req_page, sizeof(u64), reply_page, &reply_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
p = page_address(reply_page);
|
||||
end = p + reply_len;
|
||||
ceph_decode_64_safe(&p, end, pii->pool_id, e_inval);
|
||||
pii->image_id = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL);
|
||||
if (IS_ERR(pii->image_id)) {
|
||||
ret = PTR_ERR(pii->image_id);
|
||||
pii->image_id = NULL;
|
||||
return ret;
|
||||
}
|
||||
ceph_decode_64_safe(&p, end, pii->snap_id, e_inval);
|
||||
pii->has_overlap = true;
|
||||
ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
|
||||
|
||||
return 0;
|
||||
|
||||
e_inval:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int get_parent_info(struct rbd_device *rbd_dev,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
struct page *req_page, *reply_page;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
req_page = alloc_page(GFP_KERNEL);
|
||||
if (!req_page)
|
||||
return -ENOMEM;
|
||||
|
||||
reply_page = alloc_page(GFP_KERNEL);
|
||||
if (!reply_page) {
|
||||
__free_page(req_page);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p = page_address(req_page);
|
||||
ceph_encode_64(&p, rbd_dev->spec->snap_id);
|
||||
ret = __get_parent_info(rbd_dev, req_page, reply_page, pii);
|
||||
if (ret > 0)
|
||||
ret = __get_parent_info_legacy(rbd_dev, req_page, reply_page,
|
||||
pii);
|
||||
|
||||
__free_page(req_page);
|
||||
__free_page(reply_page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
{
|
||||
struct rbd_spec *parent_spec;
|
||||
size_t size;
|
||||
void *reply_buf = NULL;
|
||||
__le64 snapid;
|
||||
void *p;
|
||||
void *end;
|
||||
u64 pool_id;
|
||||
char *image_id;
|
||||
u64 snap_id;
|
||||
u64 overlap;
|
||||
struct parent_image_info pii = { 0 };
|
||||
int ret;
|
||||
|
||||
parent_spec = rbd_spec_alloc();
|
||||
if (!parent_spec)
|
||||
return -ENOMEM;
|
||||
|
||||
size = sizeof (__le64) + /* pool_id */
|
||||
sizeof (__le32) + RBD_IMAGE_ID_LEN_MAX + /* image_id */
|
||||
sizeof (__le64) + /* snap_id */
|
||||
sizeof (__le64); /* overlap */
|
||||
reply_buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!reply_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
snapid = cpu_to_le64(rbd_dev->spec->snap_id);
|
||||
ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
|
||||
&rbd_dev->header_oloc, "get_parent",
|
||||
&snapid, sizeof(snapid), reply_buf, size);
|
||||
dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
|
||||
if (ret < 0)
|
||||
ret = get_parent_info(rbd_dev, &pii);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
p = reply_buf;
|
||||
end = reply_buf + ret;
|
||||
ret = -ERANGE;
|
||||
ceph_decode_64_safe(&p, end, pool_id, out_err);
|
||||
if (pool_id == CEPH_NOPOOL) {
|
||||
dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
|
||||
__func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id,
|
||||
pii.has_overlap, pii.overlap);
|
||||
|
||||
if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) {
|
||||
/*
|
||||
* Either the parent never existed, or we have
|
||||
* record of it but the image got flattened so it no
|
||||
@ -4633,6 +4765,10 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
* overlap to 0. The effect of this is that all new
|
||||
* requests will be treated as if the image had no
|
||||
* parent.
|
||||
*
|
||||
* If !pii.has_overlap, the parent image spec is not
|
||||
* applicable. It's there to avoid duplication in each
|
||||
* snapshot record.
|
||||
*/
|
||||
if (rbd_dev->parent_overlap) {
|
||||
rbd_dev->parent_overlap = 0;
|
||||
@ -4647,51 +4783,36 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
/* The ceph file layout needs to fit pool id in 32 bits */
|
||||
|
||||
ret = -EIO;
|
||||
if (pool_id > (u64)U32_MAX) {
|
||||
if (pii.pool_id > (u64)U32_MAX) {
|
||||
rbd_warn(NULL, "parent pool id too large (%llu > %u)",
|
||||
(unsigned long long)pool_id, U32_MAX);
|
||||
(unsigned long long)pii.pool_id, U32_MAX);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
image_id = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL);
|
||||
if (IS_ERR(image_id)) {
|
||||
ret = PTR_ERR(image_id);
|
||||
goto out_err;
|
||||
}
|
||||
ceph_decode_64_safe(&p, end, snap_id, out_err);
|
||||
ceph_decode_64_safe(&p, end, overlap, out_err);
|
||||
|
||||
/*
|
||||
* The parent won't change (except when the clone is
|
||||
* flattened, already handled that). So we only need to
|
||||
* record the parent spec we have not already done so.
|
||||
*/
|
||||
if (!rbd_dev->parent_spec) {
|
||||
parent_spec->pool_id = pool_id;
|
||||
parent_spec->image_id = image_id;
|
||||
parent_spec->snap_id = snap_id;
|
||||
|
||||
/* TODO: support cloning across namespaces */
|
||||
if (rbd_dev->spec->pool_ns) {
|
||||
parent_spec->pool_ns = kstrdup(rbd_dev->spec->pool_ns,
|
||||
GFP_KERNEL);
|
||||
if (!parent_spec->pool_ns) {
|
||||
ret = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
parent_spec->pool_id = pii.pool_id;
|
||||
if (pii.pool_ns && *pii.pool_ns) {
|
||||
parent_spec->pool_ns = pii.pool_ns;
|
||||
pii.pool_ns = NULL;
|
||||
}
|
||||
parent_spec->image_id = pii.image_id;
|
||||
pii.image_id = NULL;
|
||||
parent_spec->snap_id = pii.snap_id;
|
||||
|
||||
rbd_dev->parent_spec = parent_spec;
|
||||
parent_spec = NULL; /* rbd_dev now owns this */
|
||||
} else {
|
||||
kfree(image_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* We always update the parent overlap. If it's zero we issue
|
||||
* a warning, as we will proceed as if there was no parent.
|
||||
*/
|
||||
if (!overlap) {
|
||||
if (!pii.overlap) {
|
||||
if (parent_spec) {
|
||||
/* refresh, careful to warn just once */
|
||||
if (rbd_dev->parent_overlap)
|
||||
@ -4702,14 +4823,14 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
|
||||
}
|
||||
}
|
||||
rbd_dev->parent_overlap = overlap;
|
||||
rbd_dev->parent_overlap = pii.overlap;
|
||||
|
||||
out:
|
||||
ret = 0;
|
||||
out_err:
|
||||
kfree(reply_buf);
|
||||
kfree(pii.pool_ns);
|
||||
kfree(pii.image_id);
|
||||
rbd_spec_put(parent_spec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -566,5 +566,5 @@ config RANDOM_TRUST_CPU
|
||||
that CPU manufacturer (perhaps with the insistence or mandate
|
||||
of a Nation State's intelligence or law enforcement agencies)
|
||||
has not installed a hidden back door to compromise the CPU's
|
||||
random number generation facilities.
|
||||
|
||||
random number generation facilities. This can also be configured
|
||||
at boot with "random.trust_cpu=on/off".
|
||||
|
@ -779,6 +779,13 @@ static struct crng_state **crng_node_pool __read_mostly;
|
||||
|
||||
static void invalidate_batched_entropy(void);
|
||||
|
||||
static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
|
||||
static int __init parse_trust_cpu(char *arg)
|
||||
{
|
||||
return kstrtobool(arg, &trust_cpu);
|
||||
}
|
||||
early_param("random.trust_cpu", parse_trust_cpu);
|
||||
|
||||
static void crng_initialize(struct crng_state *crng)
|
||||
{
|
||||
int i;
|
||||
@ -799,12 +806,10 @@ static void crng_initialize(struct crng_state *crng)
|
||||
}
|
||||
crng->state[i] ^= rv;
|
||||
}
|
||||
#ifdef CONFIG_RANDOM_TRUST_CPU
|
||||
if (arch_init) {
|
||||
if (trust_cpu && arch_init) {
|
||||
crng_init = 2;
|
||||
pr_notice("random: crng done (trusting CPU's manufacturer)\n");
|
||||
}
|
||||
#endif
|
||||
crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user