summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arc/Kconfig6
-rw-r--r--arch/arc/Makefile17
-rw-r--r--arch/arc/boot/dts/angel4.dts5
-rw-r--r--arch/arc/boot/dts/nsimosci.dts7
-rw-r--r--arch/arc/configs/fpga_defconfig1
-rw-r--r--arch/arc/configs/fpga_noramfs_defconfig1
-rw-r--r--arch/arc/configs/nsimosci_defconfig1
-rw-r--r--arch/arc/include/asm/arcregs.h89
-rw-r--r--arch/arc/include/asm/atomic.h4
-rw-r--r--arch/arc/include/asm/bitops.h4
-rw-r--r--arch/arc/include/asm/bug.h7
-rw-r--r--arch/arc/include/asm/cache.h2
-rw-r--r--arch/arc/include/asm/current.h4
-rw-r--r--arch/arc/include/asm/irqflags.h4
-rw-r--r--arch/arc/include/asm/kgdb.h32
-rw-r--r--arch/arc/include/asm/processor.h13
-rw-r--r--arch/arc/include/asm/setup.h1
-rw-r--r--arch/arc/include/asm/smp.h10
-rw-r--r--arch/arc/include/asm/string.h3
-rw-r--r--arch/arc/include/asm/syscalls.h4
-rw-r--r--arch/arc/include/asm/thread_info.h4
-rw-r--r--arch/arc/include/asm/unaligned.h2
-rw-r--r--arch/arc/kernel/Makefile2
-rw-r--r--arch/arc/kernel/disasm.c4
-rw-r--r--arch/arc/kernel/head.S10
-rw-r--r--arch/arc/kernel/kgdb.c5
-rw-r--r--arch/arc/kernel/perf_event.c22
-rw-r--r--arch/arc/kernel/setup.c272
-rw-r--r--arch/arc/kernel/smp.c2
-rw-r--r--arch/arc/mm/cache_arc700.c14
-rw-r--r--arch/arc/mm/tlb.c8
-rw-r--r--arch/arc/plat-arcfpga/Kconfig13
-rw-r--r--arch/arc/plat-arcfpga/include/plat/irq.h27
-rw-r--r--arch/arc/plat-arcfpga/include/plat/memmap.h29
-rw-r--r--arch/arc/plat-arcfpga/platform.c61
-rw-r--r--arch/arc/plat-arcfpga/smp.c3
-rw-r--r--arch/arc/plat-tb10x/Kconfig1
-rw-r--r--arch/arc/plat-tb10x/tb10x.c13
-rw-r--r--arch/arm/configs/multi_v7_defconfig1
-rw-r--r--arch/arm/mach-highbank/highbank.c2
-rw-r--r--arch/arm64/kernel/efi.c44
-rw-r--r--arch/ia64/kernel/efi.c6
-rw-r--r--arch/powerpc/configs/pseries_le_defconfig7
-rw-r--r--arch/powerpc/include/asm/eeh.h3
-rw-r--r--arch/powerpc/include/asm/perf_event.h2
-rw-r--r--arch/powerpc/include/asm/reg.h3
-rw-r--r--arch/powerpc/include/asm/syscall.h2
-rw-r--r--arch/powerpc/kernel/dma.c8
-rw-r--r--arch/powerpc/kernel/eeh.c19
-rw-r--r--arch/powerpc/kernel/eeh_driver.c12
-rw-r--r--arch/powerpc/kernel/eeh_pe.c10
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S5
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/misc.S4
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c2
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/rtas_pci.c30
-rw-r--r--arch/powerpc/kernel/setup_64.c32
-rw-r--r--arch/powerpc/kernel/stacktrace.c2
-rw-r--r--arch/powerpc/mm/numa.c41
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c2
-rw-r--r--arch/powerpc/platforms/powernv/eeh-powernv.c57
-rw-r--r--arch/powerpc/platforms/powernv/opal.c21
-rw-r--r--arch/powerpc/platforms/powernv/pci.c2
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c22
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c4
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c11
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h3
-rw-r--r--arch/powerpc/sysdev/msi_bitmap.c66
-rw-r--r--arch/s390/include/uapi/asm/unistd.h3
-rw-r--r--arch/s390/kernel/compat_wrapper.c1
-rw-r--r--arch/s390/kernel/syscalls.S1
-rw-r--r--arch/s390/kernel/uprobes.c2
-rw-r--r--arch/s390/lib/probes.c2
-rw-r--r--arch/s390/mm/pgtable.c6
-rw-r--r--arch/sparc/include/asm/oplib_64.h3
-rw-r--r--arch/sparc/include/asm/setup.h2
-rw-r--r--arch/sparc/kernel/entry.h3
-rw-r--r--arch/sparc/kernel/head_64.S40
-rw-r--r--arch/sparc/kernel/hvtramp.S1
-rw-r--r--arch/sparc/kernel/setup_64.c28
-rw-r--r--arch/sparc/kernel/trampoline_64.S12
-rw-r--r--arch/sparc/mm/gup.c30
-rw-r--r--arch/sparc/prom/cif.S5
-rw-r--r--arch/sparc/prom/init_64.c6
-rw-r--r--arch/sparc/prom/p1275.c2
-rw-r--r--arch/x86/boot/compressed/eboot.c32
-rw-r--r--arch/x86/include/asm/efi.h31
-rw-r--r--arch/x86/include/asm/kvm_host.h16
-rw-r--r--arch/x86/include/uapi/asm/vmx.h2
-rw-r--r--arch/x86/kvm/emulate.c250
-rw-r--r--arch/x86/kvm/i8254.c2
-rw-r--r--arch/x86/kvm/paging_tmpl.h2
-rw-r--r--arch/x86/kvm/svm.c8
-rw-r--r--arch/x86/kvm/vmx.c24
-rw-r--r--arch/x86/kvm/x86.c38
-rw-r--r--arch/x86/platform/efi/efi-bgrt.c36
-rw-r--r--arch/x86/platform/efi/efi.c52
-rw-r--r--arch/x86/platform/efi/efi_32.c12
-rw-r--r--arch/x86/platform/efi/efi_64.c6
-rw-r--r--arch/x86/platform/efi/efi_stub_32.S4
-rw-r--r--arch/x86/platform/intel-mid/intel_mid_weak_decls.h7
-rw-r--r--arch/x86/xen/enlighten.c3
-rw-r--r--arch/x86/xen/mmu.c5
-rw-r--r--arch/x86/xen/p2m.c83
-rw-r--r--arch/x86/xen/setup.c1
-rw-r--r--arch/x86/xen/time.c2
107 files changed, 1018 insertions, 879 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 9596b0ab108d..fe44b2494609 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -9,6 +9,7 @@
config ARC
def_bool y
select BUILDTIME_EXTABLE_SORT
+ select COMMON_CLK
select CLONE_BACKWARDS
# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
select DEVTMPFS if !INITRAMFS_SOURCE=""
@@ -73,9 +74,6 @@ config STACKTRACE_SUPPORT
config HAVE_LATENCYTOP_SUPPORT
def_bool y
-config NO_DMA
- def_bool n
-
source "init/Kconfig"
source "kernel/Kconfig.freezer"
@@ -354,7 +352,7 @@ config ARC_CURR_IN_REG
kernel mode. This saves memory access for each such access
-config ARC_MISALIGN_ACCESS
+config ARC_EMUL_UNALIGNED
bool "Emulate unaligned memory access (userspace only)"
select SYSCTL_ARCH_UNALIGN_NO_WARN
select SYSCTL_ARCH_UNALIGN_ALLOW
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 8c0b1aa56f7e..10bc3d4e8a44 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -25,7 +25,6 @@ ifdef CONFIG_ARC_CURR_IN_REG
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
endif
-upto_gcc42 := $(call cc-ifversion, -le, 0402, y)
upto_gcc44 := $(call cc-ifversion, -le, 0404, y)
atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
atleast_gcc48 := $(call cc-ifversion, -ge, 0408, y)
@@ -60,25 +59,11 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
# --build-id w/o "-marclinux". Default arc-elf32-ld is OK
ldflags-$(upto_gcc44) += -marclinux
-ARC_LIBGCC := -mA7
-cflags-$(CONFIG_ARC_HAS_HW_MPY) += -multcost=16
-
ifndef CONFIG_ARC_HAS_HW_MPY
cflags-y += -mno-mpy
-
-# newlib for ARC700 assumes MPY to be always present, which is generally true
-# However, if someone really doesn't want MPY, we need to use the 600 ver
-# which coupled with -mno-mpy will use mpy emulation
-# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
-# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
-
- ifeq ($(upto_gcc42),y)
- ARC_LIBGCC := -marc600
- cflags-y += -multcost=30
- endif
endif
-LIBGCC := $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
# Modules with short calls might break for calls into builtin-kernel
KBUILD_CFLAGS_MODULE += -mlong-calls
diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
index 6b57475967a6..757e0c62c4f9 100644
--- a/arch/arc/boot/dts/angel4.dts
+++ b/arch/arc/boot/dts/angel4.dts
@@ -24,11 +24,6 @@
serial0 = &arcuart0;
};
- memory {
- device_type = "memory";
- reg = <0x00000000 0x10000000>; /* 256M */
- };
-
fpga {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts
index 4f31b2eb5cdf..cfaedd9c61c9 100644
--- a/arch/arc/boot/dts/nsimosci.dts
+++ b/arch/arc/boot/dts/nsimosci.dts
@@ -20,18 +20,13 @@
/* this is for console on PGU */
/* bootargs = "console=tty0 consoleblank=0"; */
/* this is for console on serial */
- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
+ bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug";
};
aliases {
serial0 = &uart0;
};
- memory {
- device_type = "memory";
- reg = <0x80000000 0x10000000>; /* 256M */
- };
-
fpga {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig
index e283aa586934..ef4d3bc7b6c0 100644
--- a/arch/arc/configs/fpga_defconfig
+++ b/arch/arc/configs/fpga_defconfig
@@ -23,7 +23,6 @@ CONFIG_MODULES=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
# CONFIG_ARC_HAS_RTSC is not set
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
CONFIG_PREEMPT=y
diff --git a/arch/arc/configs/fpga_noramfs_defconfig b/arch/arc/configs/fpga_noramfs_defconfig
index 5276a52f6a2f..49c93011ab96 100644
--- a/arch/arc/configs/fpga_noramfs_defconfig
+++ b/arch/arc/configs/fpga_noramfs_defconfig
@@ -20,7 +20,6 @@ CONFIG_MODULES=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
# CONFIG_ARC_HAS_RTSC is not set
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
CONFIG_PREEMPT=y
diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig
index c01ba35a4eff..278dacf2a3f9 100644
--- a/arch/arc/configs/nsimosci_defconfig
+++ b/arch/arc/configs/nsimosci_defconfig
@@ -21,7 +21,6 @@ CONFIG_MODULES=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
# CONFIG_ARC_IDE is not set
# CONFIG_ARCTANGENT_EMAC is not set
# CONFIG_ARC_HAS_RTSC is not set
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 372466b371bf..be33db8a2ee3 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -9,19 +9,16 @@
#ifndef _ASM_ARC_ARCREGS_H
#define _ASM_ARC_ARCREGS_H
-#ifdef __KERNEL__
-
/* Build Configuration Registers */
#define ARC_REG_DCCMBASE_BCR 0x61 /* DCCM Base Addr */
#define ARC_REG_CRC_BCR 0x62
-#define ARC_REG_DVFB_BCR 0x64
-#define ARC_REG_EXTARITH_BCR 0x65
#define ARC_REG_VECBASE_BCR 0x68
#define ARC_REG_PERIBASE_BCR 0x69
-#define ARC_REG_FP_BCR 0x6B /* Single-Precision FPU */
-#define ARC_REG_DPFP_BCR 0x6C /* Dbl Precision FPU */
+#define ARC_REG_FP_BCR 0x6B /* ARCompact: Single-Precision FPU */
+#define ARC_REG_DPFP_BCR 0x6C /* ARCompact: Dbl Precision FPU */
#define ARC_REG_DCCM_BCR 0x74 /* DCCM Present + SZ */
#define ARC_REG_TIMERS_BCR 0x75
+#define ARC_REG_AP_BCR 0x76
#define ARC_REG_ICCM_BCR 0x78
#define ARC_REG_XY_MEM_BCR 0x79
#define ARC_REG_MAC_BCR 0x7a
@@ -31,6 +28,9 @@
#define ARC_REG_MIXMAX_BCR 0x7e
#define ARC_REG_BARREL_BCR 0x7f
#define ARC_REG_D_UNCACH_BCR 0x6A
+#define ARC_REG_BPU_BCR 0xc0
+#define ARC_REG_ISA_CFG_BCR 0xc1
+#define ARC_REG_SMART_BCR 0xFF
/* status32 Bits Positions */
#define STATUS_AE_BIT 5 /* Exception active */
@@ -191,14 +191,6 @@
#define PAGES_TO_KB(n_pages) ((n_pages) << (PAGE_SHIFT - 10))
#define PAGES_TO_MB(n_pages) (PAGES_TO_KB(n_pages) >> 10)
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
-/* These DPFP regs need to be saved/restored across ctx-sw */
-struct arc_fpu {
- struct {
- unsigned int l, h;
- } aux_dpfp[2];
-};
-#endif
/*
***************************************************************
@@ -212,27 +204,19 @@ struct bcr_identity {
#endif
};
-#define EXTN_SWAP_VALID 0x1
-#define EXTN_NORM_VALID 0x2
-#define EXTN_MINMAX_VALID 0x2
-#define EXTN_BARREL_VALID 0x2
-
-struct bcr_extn {
+struct bcr_isa {
#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int pad:20, crc:1, ext_arith:2, mul:2, barrel:2, minmax:2,
- norm:2, swap:1;
+ unsigned int pad1:23, atomic1:1, ver:8;
#else
- unsigned int swap:1, norm:2, minmax:2, barrel:2, mul:2, ext_arith:2,
- crc:1, pad:20;
+ unsigned int ver:8, atomic1:1, pad1:23;
#endif
};
-/* DSP Options Ref Manual */
-struct bcr_extn_mac_mul {
+struct bcr_mpy {
#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int pad:16, type:8, ver:8;
+ unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
#else
- unsigned int ver:8, type:8, pad:16;
+ unsigned int ver:8, type:2, cycles:2, dsp:4, x1616:8, pad:8;
#endif
};
@@ -251,6 +235,7 @@ struct bcr_perip {
unsigned int pad:8, sz:8, pad2:8, start:8;
#endif
};
+
struct bcr_iccm {
#ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int base:16, pad:5, sz:3, ver:8;
@@ -277,8 +262,8 @@ struct bcr_dccm {
#endif
};
-/* Both SP and DP FPU BCRs have same format */
-struct bcr_fp {
+/* ARCompact: Both SP and DP FPU BCRs have same format */
+struct bcr_fp_arcompact {
#ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int fast:1, ver:8;
#else
@@ -286,6 +271,30 @@ struct bcr_fp {
#endif
};
+struct bcr_timer {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int pad2:15, rtsc:1, pad1:6, t1:1, t0:1, ver:8;
+#else
+ unsigned int ver:8, t0:1, t1:1, pad1:6, rtsc:1, pad2:15;
+#endif
+};
+
+struct bcr_bpu_arcompact {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int pad2:19, fam:1, pad:2, ent:2, ver:8;
+#else
+ unsigned int ver:8, ent:2, pad:2, fam:1, pad2:19;
+#endif
+};
+
+struct bcr_generic {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int pad:24, ver:8;
+#else
+ unsigned int ver:8, pad:24;
+#endif
+};
+
/*
*******************************************************************
* Generic structures to hold build configuration used at runtime
@@ -299,6 +308,10 @@ struct cpuinfo_arc_cache {
unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
};
+struct cpuinfo_arc_bpu {
+ unsigned int ver, full, num_cache, num_pred;
+};
+
struct cpuinfo_arc_ccm {
unsigned int base_addr, sz;
};
@@ -306,21 +319,25 @@ struct cpuinfo_arc_ccm {
struct cpuinfo_arc {
struct cpuinfo_arc_cache icache, dcache;
struct cpuinfo_arc_mmu mmu;
+ struct cpuinfo_arc_bpu bpu;
struct bcr_identity core;
- unsigned int timers;
+ struct bcr_isa isa;
+ struct bcr_timer timers;
unsigned int vec_base;
unsigned int uncached_base;
struct cpuinfo_arc_ccm iccm, dccm;
- struct bcr_extn extn;
+ struct {
+ unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
+ fpu_sp:1, fpu_dp:1, pad2:6,
+ debug:1, ap:1, smart:1, rtt:1, pad3:4,
+ pad4:8;
+ } extn;
+ struct bcr_mpy extn_mpy;
struct bcr_extn_xymem extn_xymem;
- struct bcr_extn_mac_mul extn_mac_mul;
- struct bcr_fp fp, dpfp;
};
extern struct cpuinfo_arc cpuinfo_arc700[];
#endif /* __ASEMBLY__ */
-#endif /* __KERNEL__ */
-
#endif /* _ASM_ARC_ARCREGS_H */
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index 173f303a868f..067551b6920a 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -9,8 +9,6 @@
#ifndef _ASM_ARC_ATOMIC_H
#define _ASM_ARC_ATOMIC_H
-#ifdef __KERNEL__
-
#ifndef __ASSEMBLY__
#include <linux/types.h>
@@ -170,5 +168,3 @@ ATOMIC_OP(and, &=, and)
#endif
#endif
-
-#endif
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index ebc0cf3164dc..1a5bf07eefe2 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -13,8 +13,6 @@
#error only <linux/bitops.h> can be included directly
#endif
-#ifdef __KERNEL__
-
#ifndef __ASSEMBLY__
#include <linux/types.h>
@@ -508,6 +506,4 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
#endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
#endif
diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h
index 5b18e94c6678..ea022d47896c 100644
--- a/arch/arc/include/asm/bug.h
+++ b/arch/arc/include/asm/bug.h
@@ -21,10 +21,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
unsigned long address);
void die(const char *str, struct pt_regs *regs, unsigned long address);
-#define BUG() do { \
- dump_stack(); \
- pr_warn("Kernel BUG in %s: %s: %d!\n", \
- __FILE__, __func__, __LINE__); \
+#define BUG() do { \
+ pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+ dump_stack(); \
} while (0)
#define HAVE_ARCH_BUG
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index b3c750979aa1..7861255da32d 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -20,7 +20,7 @@
#define CACHE_LINE_MASK (~(L1_CACHE_BYTES - 1))
/*
- * ARC700 doesn't cache any access in top 256M.
+ * ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
* Ideal for wiring memory mapped peripherals as we don't need to do
* explicit uncached accesses (LD.di/ST.di) hence more portable drivers
*/
diff --git a/arch/arc/include/asm/current.h b/arch/arc/include/asm/current.h
index 87b918585c4a..c2453ee62801 100644
--- a/arch/arc/include/asm/current.h
+++ b/arch/arc/include/asm/current.h
@@ -12,8 +12,6 @@
#ifndef _ASM_ARC_CURRENT_H
#define _ASM_ARC_CURRENT_H
-#ifdef __KERNEL__
-
#ifndef __ASSEMBLY__
#ifdef CONFIG_ARC_CURR_IN_REG
@@ -27,6 +25,4 @@ register struct task_struct *curr_arc asm("r25");
#endif /* ! __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
#endif /* _ASM_ARC_CURRENT_H */
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index 587df8236e8b..742816f1b210 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -15,8 +15,6 @@
* -Conditionally disable interrupts (if they are not enabled, don't disable)
*/
-#ifdef __KERNEL__
-
#include <asm/arcregs.h>
/* status32 Reg bits related to Interrupt Handling */
@@ -169,6 +167,4 @@ static inline int arch_irqs_disabled(void)
#endif /* __ASSEMBLY__ */
-#endif /* KERNEL */
-
#endif
diff --git a/arch/arc/include/asm/kgdb.h b/arch/arc/include/asm/kgdb.h
index b65fca7ffeb5..fea931634136 100644
--- a/arch/arc/include/asm/kgdb.h
+++ b/arch/arc/include/asm/kgdb.h
@@ -19,7 +19,7 @@
* register API yet */
#undef DBG_MAX_REG_NUM
-#define GDB_MAX_REGS 39
+#define GDB_MAX_REGS 87
#define BREAK_INSTR_SIZE 2
#define CACHE_FLUSH_IS_SAFE 1
@@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void)
extern void kgdb_trap(struct pt_regs *regs);
-enum arc700_linux_regnums {
+/* This is the numbering of registers according to the GDB. See GDB's
+ * arc-tdep.h for details.
+ *
+ * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */
+enum arc_linux_regnums {
_R0 = 0,
_R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
_R25, _R26,
- _BTA = 27,
- _LP_START = 28,
- _LP_END = 29,
- _LP_COUNT = 30,
- _STATUS32 = 31,
- _BLINK = 32,
- _FP = 33,
- __SP = 34,
- _EFA = 35,
- _RET = 36,
- _ORIG_R8 = 37,
- _STOP_PC = 38
+ _FP = 27,
+ __SP = 28,
+ _R30 = 30,
+ _BLINK = 31,
+ _LP_COUNT = 60,
+ _STOP_PC = 64,
+ _RET = 64,
+ _LP_START = 65,
+ _LP_END = 66,
+ _STATUS32 = 67,
+ _ECR = 76,
+ _BTA = 82,
};
#else
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 82588f3ba77f..210fe97464c3 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -14,12 +14,19 @@
#ifndef __ASM_ARC_PROCESSOR_H
#define __ASM_ARC_PROCESSOR_H
-#ifdef __KERNEL__
-
#ifndef __ASSEMBLY__
#include <asm/ptrace.h>
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+/* These DPFP regs need to be saved/restored across ctx-sw */
+struct arc_fpu {
+ struct {
+ unsigned int l, h;
+ } aux_dpfp[2];
+};
+#endif
+
/* Arch specific stuff which needs to be saved per task.
* However these items are not so important so as to earn a place in
* struct thread_info
@@ -128,6 +135,4 @@ extern unsigned int get_wchan(struct task_struct *p);
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif /* __KERNEL__ */
-
#endif /* __ASM_ARC_PROCESSOR_H */
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index e10f8cef56a8..6e3ef5ba4f74 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -29,7 +29,6 @@ struct cpuinfo_data {
};
extern int root_mountflags, end_mem;
-extern int running_on_hw;
void setup_processor(void);
void __init setup_arch_memory(void);
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 5d06eee43ea9..3845b9e94f69 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -59,7 +59,15 @@ struct plat_smp_ops {
/* TBD: stop exporting it for direct population by platform */
extern struct plat_smp_ops plat_smp_ops;
-#endif /* CONFIG_SMP */
+#else /* CONFIG_SMP */
+
+static inline void smp_init_cpus(void) {}
+static inline const char *arc_platform_smp_cpuinfo(void)
+{
+ return "";
+}
+
+#endif /* !CONFIG_SMP */
/*
* ARC700 doesn't support atomic Read-Modify-Write ops.
diff --git a/arch/arc/include/asm/string.h b/arch/arc/include/asm/string.h
index 87676c8f1412..95822b550a18 100644
--- a/arch/arc/include/asm/string.h
+++ b/arch/arc/include/asm/string.h
@@ -17,8 +17,6 @@
#include <linux/types.h>
-#ifdef __KERNEL__
-
#define __HAVE_ARCH_MEMSET
#define __HAVE_ARCH_MEMCPY
#define __HAVE_ARCH_MEMCMP
@@ -36,5 +34,4 @@ extern char *strcpy(char *dest, const char *src);
extern int strcmp(const char *cs, const char *ct);
extern __kernel_size_t strlen(const char *);
-#endif /* __KERNEL__ */
#endif /* _ASM_ARC_STRING_H */
diff --git a/arch/arc/include/asm/syscalls.h b/arch/arc/include/asm/syscalls.h
index dd785befe7fd..e56f9fcc5581 100644
--- a/arch/arc/include/asm/syscalls.h
+++ b/arch/arc/include/asm/syscalls.h
@@ -9,8 +9,6 @@
#ifndef _ASM_ARC_SYSCALLS_H
#define _ASM_ARC_SYSCALLS_H 1
-#ifdef __KERNEL__
-
#include <linux/compiler.h>
#include <linux/linkage.h>
#include <linux/types.h>
@@ -22,6 +20,4 @@ int sys_arc_gettls(void);
#include <asm-generic/syscalls.h>
-#endif /* __KERNEL__ */
-
#endif
diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h
index 45be21672011..02bc5ec0fb2e 100644
--- a/arch/arc/include/asm/thread_info.h
+++ b/arch/arc/include/asm/thread_info.h
@@ -16,8 +16,6 @@
#ifndef _ASM_THREAD_INFO_H
#define _ASM_THREAD_INFO_H
-#ifdef __KERNEL__
-
#include <asm/page.h>
#ifdef CONFIG_16KSTACKS
@@ -114,6 +112,4 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
* syscall, so all that reamins to be tested is _TIF_WORK_MASK
*/
-#endif /* __KERNEL__ */
-
#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h
index 3e5f071bc00c..6da6b4edaeda 100644
--- a/arch/arc/include/asm/unaligned.h
+++ b/arch/arc/include/asm/unaligned.h
@@ -14,7 +14,7 @@
#include <asm-generic/unaligned.h>
#include <asm/ptrace.h>
-#ifdef CONFIG_ARC_MISALIGN_ACCESS
+#ifdef CONFIG_ARC_EMUL_UNALIGNED
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
struct callee_regs *cregs);
#else
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 8004b4fa6461..113f2033da9f 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
+obj-$(CONFIG_ARC_EMUL_UNALIGNED) += unaligned.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index b8a549c4f540..3b7cd4864ba2 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <asm/disasm.h>
-#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
+#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
defined(CONFIG_KPROBES)
/* disasm_instr: Analyses instruction at addr, stores
@@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
return instr.is_branch;
}
-#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
+#endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 4d2481bd8b98..b0e8666fdccc 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -91,16 +91,6 @@ stext:
st r0, [@uboot_tag]
st r2, [@uboot_arg]
- ; Identify if running on ISS vs Silicon
- ; IDENTITY Reg [ 3 2 1 0 ]
- ; (chip-id) ^^^^^ ==> 0xffff for ISS
- lr r0, [identity]
- lsr r3, r0, 16
- cmp r3, 0xffff
- mov.z r4, 0
- mov.nz r4, 1
- st r4, [@running_on_hw]
-
; setup "current" tsk and optionally cache it in dedicated r25
mov r9, @init_task
SET_CURR_TASK_ON_CPU r9, r0 ; r9 = tsk, r0 = scratch
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c
index a2ff5c5d1450..ecf6a7869375 100644
--- a/arch/arc/kernel/kgdb.c
+++ b/arch/arc/kernel/kgdb.c
@@ -158,11 +158,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
return -1;
}
-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-{
- return instruction_pointer(regs);
-}
-
int kgdb_arch_init(void)
{
single_step_data.armed = 0;
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index b9a5685a990e..ae1c485cbc68 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -244,25 +244,23 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
pr_err("This core does not have performance counters!\n");
return -ENODEV;
}
+ BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
- arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
- GFP_KERNEL);
+ READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
+ if (!cc_bcr.v) {
+ pr_err("Performance counters exist, but no countable conditions?\n");
+ return -ENODEV;
+ }
+
+ arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
if (!arc_pmu)
return -ENOMEM;
arc_pmu->n_counters = pct_bcr.c;
- BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
-
arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
- pr_info("ARC PMU found with %d counters of size %d bits\n",
- arc_pmu->n_counters, arc_pmu->counter_size);
-
- READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-
- if (!cc_bcr.v)
- pr_err("Strange! Performance counters exist, but no countable conditions?\n");
- pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
+ pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
+ arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
cc_name.str[8] = 0;
for (i = 0; i < PERF_COUNT_HW_MAX; i++)
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 119dddb752b2..252bf603db9c 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -13,7 +13,9 @@
#include <linux/console.h>
#include <linux/module.h>
#include <linux/cpu.h>
+#include <linux/clk-provider.h>
#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
#include <linux/cache.h>
#include <asm/sections.h>
#include <asm/arcregs.h>
@@ -24,11 +26,10 @@
#include <asm/unwind.h>
#include <asm/clk.h>
#include <asm/mach_desc.h>
+#include <asm/smp.h>
#define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x))
-int running_on_hw = 1; /* vs. on ISS */
-
/* Part of U-boot ABI: see head.S */
int __initdata uboot_tag;
char __initdata *uboot_arg;
@@ -42,26 +43,26 @@ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
static void read_arc_build_cfg_regs(void)
{
struct bcr_perip uncached_space;
+ struct bcr_generic bcr;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
FIX_PTR(cpu);
READ_BCR(AUX_IDENTITY, cpu->core);
+ READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
- cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR);
+ READ_BCR(ARC_REG_TIMERS_BCR, cpu->timers);
cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
cpu->uncached_base = uncached_space.start << 24;
- cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR);
- cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR);
- cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR);
- cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR);
- cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR);
- READ_BCR(ARC_REG_MAC_BCR, cpu->extn_mac_mul);
+ READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
- cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
- cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
+ cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR) > 1 ? 1 : 0; /* 2,3 */
+ cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR) > 1 ? 1 : 0; /* 2,3 */
+ cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0; /* 1,3 */
+ cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
+ cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
/* Note that we read the CCM BCRs independent of kernel config
* This is to catch the cases where user doesn't know that
@@ -95,43 +96,76 @@ static void read_arc_build_cfg_regs(void)
read_decode_mmu_bcr();
read_decode_cache_bcr();
- READ_BCR(ARC_REG_FP_BCR, cpu->fp);
- READ_BCR(ARC_REG_DPFP_BCR, cpu->dpfp);
+ {
+ struct bcr_fp_arcompact sp, dp;
+ struct bcr_bpu_arcompact bpu;
+
+ READ_BCR(ARC_REG_FP_BCR, sp);
+ READ_BCR(ARC_REG_DPFP_BCR, dp);
+ cpu->extn.fpu_sp = sp.ver ? 1 : 0;
+ cpu->extn.fpu_dp = dp.ver ? 1 : 0;
+
+ READ_BCR(ARC_REG_BPU_BCR, bpu);
+ cpu->bpu.ver = bpu.ver;
+ cpu->bpu.full = bpu.fam ? 1 : 0;
+ if (bpu.ent) {
+ cpu->bpu.num_cache = 256 << (bpu.ent - 1);
+ cpu->bpu.num_pred = 256 << (bpu.ent - 1);
+ }
+ }
+
+ READ_BCR(ARC_REG_AP_BCR, bcr);
+ cpu->extn.ap = bcr.ver ? 1 : 0;
+
+ READ_BCR(ARC_REG_SMART_BCR, bcr);
+ cpu->extn.smart = bcr.ver ? 1 : 0;
+
+ cpu->extn.debug = cpu->extn.ap | cpu->extn.smart;
}
static const struct cpuinfo_data arc_cpu_tbl[] = {
- { {0x10, "ARCTangent A5"}, 0x1F},
{ {0x20, "ARC 600" }, 0x2F},
{ {0x30, "ARC 700" }, 0x33},
{ {0x34, "ARC 700 R4.10"}, 0x34},
+ { {0x35, "ARC 700 R4.11"}, 0x35},
{ {0x00, NULL } }
};
+#define IS_AVAIL1(v, str) ((v) ? str : "")
+#define IS_USED(cfg) (IS_ENABLED(cfg) ? "" : "(not used) ")
+#define IS_AVAIL2(v, str, cfg) IS_AVAIL1(v, str), IS_AVAIL1(v, IS_USED(cfg))
+
static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
{
- int n = 0;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
struct bcr_identity *core = &cpu->core;
const struct cpuinfo_data *tbl;
- int be = 0;
-#ifdef CONFIG_CPU_BIG_ENDIAN
- be = 1;
-#endif
+ char *isa_nm;
+ int i, be, atomic;
+ int n = 0;
+
FIX_PTR(cpu);
+ {
+ isa_nm = "ARCompact";
+ be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
+
+ atomic = cpu->isa.atomic1;
+ if (!cpu->isa.ver) /* ISA BCR absent, use Kconfig info */
+ atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
+ }
+
n += scnprintf(buf + n, len - n,
- "\nARC IDENTITY\t: Family [%#02x]"
- " Cpu-id [%#02x] Chip-id [%#4x]\n",
- core->family, core->cpu_id,
- core->chip_id);
+ "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
+ core->family, core->cpu_id, core->chip_id);
for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
if ((core->family >= tbl->info.id) &&
(core->family <= tbl->up_range)) {
n += scnprintf(buf + n, len - n,
- "processor\t: %s %s\n",
- tbl->info.str,
- be ? "[Big Endian]" : "");
+ "processor [%d]\t: %s (%s ISA) %s\n",
+ cpu_id, tbl->info.str, isa_nm,
+ IS_AVAIL1(be, "[Big-Endian]"));
break;
}
}
@@ -143,34 +177,35 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
(unsigned int)(arc_get_core_freq() / 1000000),
(unsigned int)(arc_get_core_freq() / 10000) % 100);
- n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n",
- (cpu->timers & 0x200) ? "TIMER1" : "",
- (cpu->timers & 0x100) ? "TIMER0" : "");
+ n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
+ IS_AVAIL1(cpu->timers.t0, "Timer0 "),
+ IS_AVAIL1(cpu->timers.t1, "Timer1 "),
+ IS_AVAIL2(cpu->timers.rtsc, "64-bit RTSC ", CONFIG_ARC_HAS_RTSC));
- n += scnprintf(buf + n, len - n, "Vect Tbl Base\t: %#x\n",
- cpu->vec_base);
+ n += i = scnprintf(buf + n, len - n, "%s%s",
+ IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
- n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n",
- cpu->uncached_base);
+ if (i)
+ n += scnprintf(buf + n, len - n, "\n\t\t: ");
- return buf;
-}
+ n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
+ IS_AVAIL1(cpu->extn_mpy.ver, "mpy "),
+ IS_AVAIL1(cpu->extn.norm, "norm "),
+ IS_AVAIL1(cpu->extn.barrel, "barrel-shift "),
+ IS_AVAIL1(cpu->extn.swap, "swap "),
+ IS_AVAIL1(cpu->extn.minmax, "minmax "),
+ IS_AVAIL1(cpu->extn.crc, "crc "),
+ IS_AVAIL2(1, "swape", CONFIG_ARC_HAS_SWAPE));
-static const struct id_to_str mul_type_nm[] = {
- { 0x0, "N/A"},
- { 0x1, "32x32 (spl Result Reg)" },
- { 0x2, "32x32 (ANY Result Reg)" }
-};
+ if (cpu->bpu.ver)
+ n += scnprintf(buf + n, len - n,
+ "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n",
+ IS_AVAIL1(cpu->bpu.full, "full"),
+ IS_AVAIL1(!cpu->bpu.full, "partial"),
+ cpu->bpu.num_cache, cpu->bpu.num_pred);
-static const struct id_to_str mac_mul_nm[] = {
- {0x0, "N/A"},
- {0x1, "N/A"},
- {0x2, "Dual 16 x 16"},
- {0x3, "N/A"},
- {0x4, "32x16"},
- {0x5, "N/A"},
- {0x6, "Dual 16x16 and 32x16"}
-};
+ return buf;
+}
static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
{
@@ -178,67 +213,46 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
FIX_PTR(cpu);
-#define IS_AVAIL1(var, str) ((var) ? str : "")
-#define IS_AVAIL2(var, str) ((var == 0x2) ? str : "")
-#define IS_USED(cfg) (IS_ENABLED(cfg) ? "(in-use)" : "(not used)")
n += scnprintf(buf + n, len - n,
- "Extn [700-Base]\t: %s %s %s %s %s %s\n",
- IS_AVAIL2(cpu->extn.norm, "norm,"),
- IS_AVAIL2(cpu->extn.barrel, "barrel-shift,"),
- IS_AVAIL1(cpu->extn.swap, "swap,"),
- IS_AVAIL2(cpu->extn.minmax, "minmax,"),
- IS_AVAIL1(cpu->extn.crc, "crc,"),
- IS_AVAIL2(cpu->extn.ext_arith, "ext-arith"));
-
- n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s",
- mul_type_nm[cpu->extn.mul].str);
-
- n += scnprintf(buf + n, len - n, " MAC MPY: %s\n",
- mac_mul_nm[cpu->extn_mac_mul.type].str);
-
- if (cpu->core.family == 0x34) {
- n += scnprintf(buf + n, len - n,
- "Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n",
- IS_USED(CONFIG_ARC_HAS_LLSC),
- IS_USED(CONFIG_ARC_HAS_SWAPE),
- IS_USED(CONFIG_ARC_HAS_RTSC));
- }
-
- n += scnprintf(buf + n, len - n, "Extn [CCM]\t: %s",
- !(cpu->dccm.sz || cpu->iccm.sz) ? "N/A" : "");
-
- if (cpu->dccm.sz)
- n += scnprintf(buf + n, len - n, "DCCM: @ %x, %d KB ",
- cpu->dccm.base_addr, TO_KB(cpu->dccm.sz));
-
- if (cpu->iccm.sz)
- n += scnprintf(buf + n, len - n, "ICCM: @ %x, %d KB",
+ "Vector Table\t: %#x\nUncached Base\t: %#x\n",
+ cpu->vec_base, cpu->uncached_base);
+
+ if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
+ n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
+ IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
+ IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
+
+ if (cpu->extn.debug)
+ n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
+ IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+ IS_AVAIL1(cpu->extn.smart, "smaRT "),
+ IS_AVAIL1(cpu->extn.rtt, "RTT "));
+
+ if (cpu->dccm.sz || cpu->iccm.sz)
+ n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
+ cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
cpu->iccm.base_addr, TO_KB(cpu->iccm.sz));
- n += scnprintf(buf + n, len - n, "\nExtn [FPU]\t: %s",
- !(cpu->fp.ver || cpu->dpfp.ver) ? "N/A" : "");
-
- if (cpu->fp.ver)
- n += scnprintf(buf + n, len - n, "SP [v%d] %s",
- cpu->fp.ver, cpu->fp.fast ? "(fast)" : "");
-
- if (cpu->dpfp.ver)
- n += scnprintf(buf + n, len - n, "DP [v%d] %s",
- cpu->dpfp.ver, cpu->dpfp.fast ? "(fast)" : "");
-
- n += scnprintf(buf + n, len - n, "\n");
-
n += scnprintf(buf + n, len - n,
"OS ABI [v3]\t: no-legacy-syscalls\n");
return buf;
}
-static void arc_chk_ccms(void)
+static void arc_chk_core_config(void)
{
-#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+ int fpu_enabled;
+
+ if (!cpu->timers.t0)
+ panic("Timer0 is not present!\n");
+
+ if (!cpu->timers.t1)
+ panic("Timer1 is not present!\n");
+
+ if (IS_ENABLED(CONFIG_ARC_HAS_RTSC) && !cpu->timers.rtsc)
+ panic("RTSC is not present\n");
#ifdef CONFIG_ARC_HAS_DCCM
/*
@@ -256,33 +270,20 @@ static void arc_chk_ccms(void)
if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
panic("Linux built with incorrect ICCM Size\n");
#endif
-#endif
-}
-/*
- * Ensure that FP hardware and kernel config match
- * -If hardware contains DPFP, kernel needs to save/restore FPU state
- * across context switches
- * -If hardware lacks DPFP, but kernel configured to save FPU state then
- * kernel trying to access non-existant DPFP regs will crash
- *
- * We only check for Dbl precision Floating Point, because only DPFP
- * hardware has dedicated regs which need to be saved/restored on ctx-sw
- * (Single Precision uses core regs), thus kernel is kind of oblivious to it
- */
-static void arc_chk_fpu(void)
-{
- struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+ /*
+ * FP hardware/software config sanity
+ * -If hardware contains DPFP, kernel needs to save/restore FPU state
+ * -If not, it will crash trying to save/restore the non-existant regs
+ *
+ * (only DPDP checked since SP has no arch visible regs)
+ */
+ fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
- if (cpu->dpfp.ver) {
-#ifndef CONFIG_ARC_FPU_SAVE_RESTORE
- pr_warn("DPFP support broken in this kernel...\n");
-#endif
- } else {
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
- panic("H/w lacks DPFP support, apps won't work\n");
-#endif
- }
+ if (cpu->extn.fpu_dp && !fpu_enabled)
+ pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
+ else if (!cpu->extn.fpu_dp && fpu_enabled)
+ panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
}
/*
@@ -303,15 +304,11 @@ void setup_processor(void)
arc_mmu_init();
arc_cache_init();
- arc_chk_ccms();
printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
-
-#ifdef CONFIG_SMP
printk(arc_platform_smp_cpuinfo());
-#endif
- arc_chk_fpu();
+ arc_chk_core_config();
}
static inline int is_kernel(unsigned long addr)
@@ -360,11 +357,7 @@ void __init setup_arch(char **cmdline_p)
machine_desc->init_early();
setup_processor();
-
-#ifdef CONFIG_SMP
smp_init_cpus();
-#endif
-
setup_arch_memory();
/* copy flat DT out of .init and then unflatten it */
@@ -385,7 +378,13 @@ void __init setup_arch(char **cmdline_p)
static int __init customize_machine(void)
{
- /* Add platform devices */
+ of_clk_init(NULL);
+ /*
+ * Traverses flattened DeviceTree - registering platform devices
+ * (if any) complete with their resources
+ */
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
if (machine_desc->init_machine)
machine_desc->init_machine();
@@ -419,19 +418,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
- seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n",
+ seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
loops_per_jiffy / (500000 / HZ),
(loops_per_jiffy / (5000 / HZ)) % 100);
seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
-#ifdef CONFIG_SMP
seq_printf(m, arc_platform_smp_cpuinfo());
-#endif
free_page((unsigned long)str);
done:
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index dcd317c47d09..d01df0c517a2 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -101,7 +101,7 @@ void __weak arc_platform_smp_wait_to_boot(int cpu)
const char *arc_platform_smp_cpuinfo(void)
{
- return plat_smp_ops.info;
+ return plat_smp_ops.info ? : "";
}
/*
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 9e1142729fd1..8c3a3e02ba92 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -530,16 +530,9 @@ EXPORT_SYMBOL(dma_cache_wback);
*/
void flush_icache_range(unsigned long kstart, unsigned long kend)
{
- unsigned int tot_sz, off, sz;
- unsigned long phy, pfn;
+ unsigned int tot_sz;
- /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
-
- /* This is not the right API for user virtual address */
- if (kstart < TASK_SIZE) {
- BUG_ON("Flush icache range for user virtual addr space");
- return;
- }
+ WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
/* Shortcut for bigger flush ranges.
* Here we don't care if this was kernel virtual or phy addr
@@ -572,6 +565,9 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
* straddles across 2 virtual pages and hence need for loop
*/
while (tot_sz > 0) {
+ unsigned int off, sz;
+ unsigned long phy, pfn;
+
off = kstart % PAGE_SIZE;
pfn = vmalloc_to_pfn((void *)kstart);
phy = (pfn << PAGE_SHIFT) + off;
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index e1acf0ce5647..7f47d2a56f44 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -609,14 +609,12 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
int n = 0;
struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
- n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ",
- p_mmu->ver, TO_KB(p_mmu->pg_sz));
-
n += scnprintf(buf + n, len - n,
- "J-TLB %d (%dx%d), uDTLB %d, uITLB %d, %s\n",
+ "MMU [v%x]\t: %dk PAGE, JTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
+ p_mmu->ver, TO_KB(p_mmu->pg_sz),
p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
p_mmu->u_dtlb, p_mmu->u_itlb,
- IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : "");
+ IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
return buf;
}
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index b9f34cf55acf..217593a70751 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -8,7 +8,7 @@
menuconfig ARC_PLAT_FPGA_LEGACY
bool "\"Legacy\" ARC FPGA dev Boards"
- select ISS_SMP_EXTN if SMP
+ select ARC_HAS_COH_CACHES if SMP
help
Support for ARC development boards, provided by Synopsys.
These are based on FPGA or ISS. e.g.
@@ -18,17 +18,6 @@ menuconfig ARC_PLAT_FPGA_LEGACY
if ARC_PLAT_FPGA_LEGACY
-config ARC_BOARD_ANGEL4
- bool "ARC Angel4"
- default y
- help
- ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
-
-config ARC_BOARD_ML509
- bool "ML509"
- help
- ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
-
config ISS_SMP_EXTN
bool "ARC SMP Extensions (ISS Models only)"
default n
diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h
deleted file mode 100644
index 2c9dea690ac4..000000000000
--- a/arch/arc/plat-arcfpga/include/plat/irq.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * vineetg: Feb 2009
- * -For AA4 board, IRQ assignments to peripherals
- */
-
-#ifndef __PLAT_IRQ_H
-#define __PLAT_IRQ_H
-
-#define UART0_IRQ 5
-#define UART1_IRQ 10
-#define UART2_IRQ 11
-
-#define IDE_IRQ 13
-#define PCI_IRQ 14
-#define PS2_IRQ 15
-
-#ifdef CONFIG_SMP
-#define IDU_INTERRUPT_0 16
-#endif
-
-#endif
diff --git a/arch/arc/plat-arcfpga/include/plat/memmap.h b/arch/arc/plat-arcfpga/include/plat/memmap.h
deleted file mode 100644
index 5c78e6135a1f..000000000000
--- a/arch/arc/plat-arcfpga/include/plat/memmap.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * vineetg: Feb 2009
- * -For AA4 board, System Memory Map for Peripherals etc
- */
-
-#ifndef __PLAT_MEMMAP_H
-#define __PLAT_MEMMAP_H
-
-#define UART0_BASE 0xC0FC1000
-#define UART1_BASE 0xC0FC1100
-
-#define IDE_CONTROLLER_BASE 0xC0FC9000
-
-#define AHB_PCI_HOST_BRG_BASE 0xC0FD0000
-
-#define PGU_BASEADDR 0xC0FC8000
-#define VLCK_ADDR 0xC0FCF028
-
-#define BVCI_LAT_UNIT_BASE 0xC0FED000
-
-#define PS2_BASE_ADDR 0xC0FCC000
-
-#endif
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index 1038949a99a1..afc88254acc1 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -8,37 +8,9 @@
* published by the Free Software Foundation.
*/
-#include <linux/types.h>
#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/console.h>
-#include <linux/of_platform.h>
-#include <asm/setup.h>
-#include <asm/clk.h>
#include <asm/mach_desc.h>
-#include <plat/memmap.h>
#include <plat/smp.h>
-#include <plat/irq.h>
-
-static void __init plat_fpga_early_init(void)
-{
- pr_info("[plat-arcfpga]: registering early dev resources\n");
-
-#ifdef CONFIG_ISS_SMP_EXTN
- iss_model_init_early_smp();
-#endif
-}
-
-static void __init plat_fpga_populate_dev(void)
-{
- /*
- * Traverses flattened DeviceTree - registering platform devices
- * (if any) complete with their resources
- */
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
/*----------------------- Machine Descriptions ------------------------------
*
@@ -48,41 +20,26 @@ static void __init plat_fpga_populate_dev(void)
* callback set, by matching the DT compatible name.
*/
-static const char *aa4_compat[] __initconst = {
+static const char *legacy_fpga_compat[] __initconst = {
"snps,arc-angel4",
- NULL,
-};
-
-MACHINE_START(ANGEL4, "angel4")
- .dt_compat = aa4_compat,
- .init_early = plat_fpga_early_init,
- .init_machine = plat_fpga_populate_dev,
-#ifdef CONFIG_ISS_SMP_EXTN
- .init_smp = iss_model_init_smp,
-#endif
-MACHINE_END
-
-static const char *ml509_compat[] __initconst = {
"snps,arc-ml509",
NULL,
};
-MACHINE_START(ML509, "ml509")
- .dt_compat = ml509_compat,
- .init_early = plat_fpga_early_init,
- .init_machine = plat_fpga_populate_dev,
-#ifdef CONFIG_SMP
+MACHINE_START(LEGACY_FPGA, "legacy_fpga")
+ .dt_compat = legacy_fpga_compat,
+#ifdef CONFIG_ISS_SMP_EXTN
+ .init_early = iss_model_init_early_smp,
.init_smp = iss_model_init_smp,
#endif
MACHINE_END
-static const char *nsimosci_compat[] __initconst = {
+static const char *simulation_compat[] __initconst = {
+ "snps,nsim",
"snps,nsimosci",
NULL,
};
-MACHINE_START(NSIMOSCI, "nsimosci")
- .dt_compat = nsimosci_compat,
- .init_early = NULL,
- .init_machine = plat_fpga_populate_dev,
+MACHINE_START(SIMULATION, "simulation")
+ .dt_compat = simulation_compat,
MACHINE_END
diff --git a/arch/arc/plat-arcfpga/smp.c b/arch/arc/plat-arcfpga/smp.c
index 92bad9122077..64797ba3bbe3 100644
--- a/arch/arc/plat-arcfpga/smp.c
+++ b/arch/arc/plat-arcfpga/smp.c
@@ -13,9 +13,10 @@
#include <linux/smp.h>
#include <linux/irq.h>
-#include <plat/irq.h>
#include <plat/smp.h>
+#define IDU_INTERRUPT_0 16
+
static char smp_cpuinfo_buf[128];
/*
diff --git a/arch/arc/plat-tb10x/Kconfig b/arch/arc/plat-tb10x/Kconfig
index 6994c188dc88..d14b3d3c5dfd 100644
--- a/arch/arc/plat-tb10x/Kconfig
+++ b/arch/arc/plat-tb10x/Kconfig
@@ -18,7 +18,6 @@
menuconfig ARC_PLAT_TB10X
bool "Abilis TB10x"
- select COMMON_CLK
select PINCTRL
select PINCTRL_TB10X
select PINMUX
diff --git a/arch/arc/plat-tb10x/tb10x.c b/arch/arc/plat-tb10x/tb10x.c
index 06cb30929460..da0ac0960a4b 100644
--- a/arch/arc/plat-tb10x/tb10x.c
+++ b/arch/arc/plat-tb10x/tb10x.c
@@ -19,21 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
#include <linux/init.h>
-#include <linux/of_platform.h>
-#include <linux/clk-provider.h>
-#include <linux/pinctrl/consumer.h>
-
#include <asm/mach_desc.h>
-
-static void __init tb10x_platform_init(void)
-{
- of_clk_init(NULL);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
static const char *tb10x_compat[] __initdata = {
"abilis,arc-tb10x",
NULL,
@@ -41,5 +29,4 @@ static const char *tb10x_compat[] __initdata = {
MACHINE_START(TB10x, "tb10x")
.dt_compat = tb10x_compat,
- .init_machine = tb10x_platform_init,
MACHINE_END
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 491b7d5523bf..9702b140ae04 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -261,6 +261,7 @@ CONFIG_WATCHDOG=y
CONFIG_XILINX_WATCHDOG=y
CONFIG_ORION_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
+CONFIG_MESON_WATCHDOG=y
CONFIG_MFD_AS3722=y
CONFIG_MFD_BCM590XX=y
CONFIG_MFD_CROS_EC=y
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 8c35ae4ff176..07a09570175d 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -20,7 +20,7 @@
#include <linux/input.h>
#include <linux/io.h>
#include <linux/irqchip.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 03aaa99e1ea0..95c49ebc660d 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -89,7 +89,8 @@ static int __init uefi_init(void)
*/
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
pr_err("System table signature incorrect\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
}
if ((efi.systab->hdr.revision >> 16) < 2)
pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
@@ -103,6 +104,7 @@ static int __init uefi_init(void)
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
vendor[i] = c16[i];
vendor[i] = '\0';
+ early_memunmap(c16, sizeof(vendor));
}
pr_info("EFI v%u.%.02u by %s\n",
@@ -113,29 +115,11 @@ static int __init uefi_init(void)
if (retval == 0)
set_bit(EFI_CONFIG_TABLES, &efi.flags);
- early_memunmap(c16, sizeof(vendor));
+out:
early_memunmap(efi.systab, sizeof(efi_system_table_t));
-
return retval;
}
-static __initdata char memory_type_name[][32] = {
- {"Reserved"},
- {"Loader Code"},
- {"Loader Data"},
- {"Boot Code"},
- {"Boot Data"},
- {"Runtime Code"},
- {"Runtime Data"},
- {"Conventional Memory"},
- {"Unusable Memory"},
- {"ACPI Reclaim Memory"},
- {"ACPI Memory NVS"},
- {"Memory Mapped I/O"},
- {"MMIO Port Space"},
- {"PAL Code"},
-};
-
/*
* Return true for RAM regions we want to permanently reserve.
*/
@@ -166,10 +150,13 @@ static __init void reserve_regions(void)
paddr = md->phys_addr;
npages = md->num_pages;
- if (uefi_debug)
- pr_info(" 0x%012llx-0x%012llx [%s]",
+ if (uefi_debug) {
+ char buf[64];
+
+ pr_info(" 0x%012llx-0x%012llx %s",
paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
- memory_type_name[md->type]);
+ efi_md_typeattr_format(buf, sizeof(buf), md));
+ }
memrange_efi_to_native(&paddr, &npages);
size = npages << PAGE_SHIFT;
@@ -393,11 +380,16 @@ static int __init arm64_enter_virtual_mode(void)
return -1;
}
- pr_info("Remapping and enabling EFI services.\n");
-
- /* replace early memmap mapping with permanent mapping */
mapsize = memmap.map_end - memmap.map;
early_memunmap(memmap.map, mapsize);
+
+ if (efi_runtime_disabled()) {
+ pr_info("EFI runtime services will be disabled.\n");
+ return -1;
+ }
+
+ pr_info("Remapping and enabling EFI services.\n");
+ /* replace early memmap mapping with permanent mapping */
memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
mapsize);
memmap.map_end = memmap.map + mapsize;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 741b99c1a0b1..c52d7540dc05 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -568,6 +568,7 @@ efi_init (void)
{
const char *unit;
unsigned long size;
+ char buf[64];
md = p;
size = md->num_pages << EFI_PAGE_SHIFT;
@@ -586,9 +587,10 @@ efi_init (void)
unit = "KB";
}
- printk("mem%02d: type=%2u, attr=0x%016lx, "
+ printk("mem%02d: %s "
"range=[0x%016lx-0x%016lx) (%4lu%s)\n",
- i, md->type, md->attribute, md->phys_addr,
+ i, efi_md_typeattr_format(buf, sizeof(buf), md),
+ md->phys_addr,
md->phys_addr + efi_md_size(md), size, unit);
}
}
diff --git a/arch/powerpc/configs/pseries_le_defconfig b/arch/powerpc/configs/pseries_le_defconfig
index 63392f4b29a4..d2008887eb8c 100644
--- a/arch/powerpc/configs/pseries_le_defconfig
+++ b/arch/powerpc/configs/pseries_le_defconfig
@@ -48,7 +48,6 @@ CONFIG_KEXEC=y
CONFIG_IRQ_ALL_CPUS=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_CMA=y
CONFIG_PPC_64K_PAGES=y
CONFIG_PPC_SUBPAGE_PROT=y
CONFIG_SCHED_SMT=y
@@ -138,6 +137,7 @@ CONFIG_NETCONSOLE=y
CONFIG_NETPOLL_TRAP=y
CONFIG_TUN=m
CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
CONFIG_VORTEX=y
CONFIG_ACENIC=m
CONFIG_ACENIC_OMIT_TIGON_I=y
@@ -303,4 +303,9 @@ CONFIG_CRYPTO_LZO=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_NX=y
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 3b260efbfbf9..ca07f9c27335 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -71,9 +71,10 @@ struct device_node;
#define EEH_PE_ISOLATED (1 << 0) /* Isolated PE */
#define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */
-#define EEH_PE_RESET (1 << 2) /* PE reset in progress */
+#define EEH_PE_CFG_BLOCKED (1 << 2) /* Block config access */
#define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */
+#define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */
struct eeh_pe {
int type; /* PE type: PHB/Bus/Device */
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h
index 0bb23725b1e7..8bf1b6351716 100644
--- a/arch/powerpc/include/asm/perf_event.h
+++ b/arch/powerpc/include/asm/perf_event.h
@@ -34,7 +34,7 @@
do { \
(regs)->result = 0; \
(regs)->nip = __ip; \
- (regs)->gpr[1] = *(unsigned long *)__get_SP(); \
+ (regs)->gpr[1] = current_stack_pointer(); \
asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \
} while (0)
#endif
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index fe3f9488f321..c998279bd85b 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1265,8 +1265,7 @@ static inline unsigned long mfvtb (void)
#define proc_trap() asm volatile("trap")
-#define __get_SP() ({unsigned long sp; \
- asm volatile("mr %0,1": "=r" (sp)); sp;})
+extern unsigned long current_stack_pointer(void);
extern unsigned long scom970_read(unsigned int address);
extern void scom970_write(unsigned int address, unsigned long value);
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index 6fa2708da153..6240698fee9a 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -19,7 +19,7 @@
/* ftrace syscalls requires exporting the sys_call_table */
#ifdef CONFIG_FTRACE_SYSCALLS
-extern const unsigned long *sys_call_table;
+extern const unsigned long sys_call_table[];
#endif /* CONFIG_FTRACE_SYSCALLS */
static inline long syscall_get_nr(struct task_struct *task,
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index adac9dc54aee..484b2d4462c1 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -53,9 +53,16 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
#else
struct page *page;
int node = dev_to_node(dev);
+#ifdef CONFIG_FSL_SOC
u64 pfn = get_pfn_limit(dev);
int zone;
+ /*
+ * This code should be OK on other platforms, but we have drivers that
+ * don't set coherent_dma_mask. As a workaround we just ifdef it. This
+ * whole routine needs some serious cleanup.
+ */
+
zone = dma_pfn_limit_to_zone(pfn);
if (zone < 0) {
dev_err(dev, "%s: No suitable zone for pfn %#llx\n",
@@ -73,6 +80,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
break;
#endif
};
+#endif /* CONFIG_FSL_SOC */
/* ignore region specifiers */
flag &= ~(__GFP_HIGHMEM);
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index d543e4179c18..2248a1999c64 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -257,6 +257,13 @@ static void *eeh_dump_pe_log(void *data, void *flag)
struct eeh_dev *edev, *tmp;
size_t *plen = flag;
+ /* If the PE's config space is blocked, 0xFF's will be
+ * returned. It's pointless to collect the log in this
+ * case.
+ */
+ if (pe->state & EEH_PE_CFG_BLOCKED)
+ return NULL;
+
eeh_pe_for_each_dev(pe, edev, tmp)
*plen += eeh_dump_dev_log(edev, pci_regs_buf + *plen,
EEH_PCI_REGS_LOG_LEN - *plen);
@@ -673,18 +680,18 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
switch (state) {
case pcie_deassert_reset:
eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
break;
case pcie_hot_reset:
- eeh_pe_state_mark(pe, EEH_PE_RESET);
+ eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
eeh_ops->reset(pe, EEH_RESET_HOT);
break;
case pcie_warm_reset:
- eeh_pe_state_mark(pe, EEH_PE_RESET);
+ eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
break;
default:
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
return -EINVAL;
};
@@ -1523,7 +1530,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
switch (option) {
case EEH_RESET_DEACTIVATE:
ret = eeh_ops->reset(pe, option);
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
if (ret)
break;
@@ -1538,7 +1545,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
*/
eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
- eeh_pe_state_mark(pe, EEH_PE_RESET);
+ eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
ret = eeh_ops->reset(pe, option);
break;
default:
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 3fd514f8e4b2..6535936bdf27 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -528,13 +528,13 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
eeh_pe_dev_traverse(pe, eeh_report_error, &result);
/* Issue reset */
- eeh_pe_state_mark(pe, EEH_PE_RESET);
+ eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
ret = eeh_reset_pe(pe);
if (ret) {
- eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_CFG_BLOCKED);
return ret;
}
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
/* Unfreeze the PE */
ret = eeh_clear_pe_frozen_state(pe, true);
@@ -601,10 +601,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
* config accesses. So we prefer to block them. However, controlled
* PCI config accesses initiated from EEH itself are allowed.
*/
- eeh_pe_state_mark(pe, EEH_PE_RESET);
+ eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
rc = eeh_reset_pe(pe);
if (rc) {
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
return rc;
}
@@ -613,7 +613,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
/* Restore PE */
eeh_ops->configure_bridge(pe);
eeh_pe_restore_bars(pe);
- eeh_pe_state_clear(pe, EEH_PE_RESET);
+ eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
/* Clear frozen state */
rc = eeh_clear_pe_frozen_state(pe, false);
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index 53dd0915e690..5a63e2b0f65b 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -525,7 +525,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
pe->state |= state;
/* Offline PCI devices if applicable */
- if (state != EEH_PE_ISOLATED)
+ if (!(state & EEH_PE_ISOLATED))
return NULL;
eeh_pe_for_each_dev(pe, edev, tmp) {
@@ -534,6 +534,10 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
pdev->error_state = pci_channel_io_frozen;
}
+ /* Block PCI config access if required */
+ if (pe->state & EEH_PE_CFG_RESTRICTED)
+ pe->state |= EEH_PE_CFG_BLOCKED;
+
return NULL;
}
@@ -611,6 +615,10 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
pdev->error_state = pci_channel_io_normal;
}
+ /* Unblock PCI config access if required */
+ if (pe->state & EEH_PE_CFG_RESTRICTED)
+ pe->state &= ~EEH_PE_CFG_BLOCKED;
+
return NULL;
}
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 050f79a4a168..72e783ea0681 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1270,11 +1270,6 @@ hmi_exception_early:
addi r3,r1,STACK_FRAME_OVERHEAD
bl hmi_exception_realmode
/* Windup the stack. */
- /* Clear MSR_RI before setting SRR0 and SRR1. */
- li r0,MSR_RI
- mfmsr r9 /* get MSR value */
- andc r9,r9,r0
- mtmsrd r9,1 /* Clear MSR_RI */
/* Move original HSRR0 and HSRR1 into the respective regs */
ld r9,_MSR(r1)
mtspr SPRN_HSRR1,r9
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 8eb857f216c1..c14383575fe8 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -466,7 +466,7 @@ static inline void check_stack_overflow(void)
#ifdef CONFIG_DEBUG_STACKOVERFLOW
long sp;
- sp = __get_SP() & (THREAD_SIZE-1);
+ sp = current_stack_pointer() & (THREAD_SIZE-1);
/* check for stack overflow: is there less than 2KB free? */
if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index 7ce26d45777e..0d432194c018 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -114,3 +114,7 @@ _GLOBAL(longjmp)
mtlr r0
mr r3,r4
blr
+
+_GLOBAL(current_stack_pointer)
+ PPC_LL r3,0(r1)
+ blr
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index c4dfff6c2719..202963ee013a 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -41,3 +41,5 @@ EXPORT_SYMBOL(giveup_spe);
#ifdef CONFIG_EPAPR_PARAVIRT
EXPORT_SYMBOL(epapr_hypercall_start);
#endif
+
+EXPORT_SYMBOL(current_stack_pointer);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index aa1df89c8b2a..923cd2daba89 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1545,7 +1545,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
tsk = current;
if (sp == 0) {
if (tsk == current)
- asm("mr %0,1" : "=r" (sp));
+ sp = current_stack_pointer();
else
sp = tsk->thread.ksp;
}
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index c168337aef9d..7c55b86206b3 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -66,6 +66,11 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
return PCIBIOS_DEVICE_NOT_FOUND;
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+ if (pdn->edev && pdn->edev->pe &&
+ (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+ return PCIBIOS_SET_FAILED;
+#endif
addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
buid = pdn->phb->buid;
@@ -90,9 +95,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
struct device_node *busdn, *dn;
struct pci_dn *pdn;
bool found = false;
-#ifdef CONFIG_EEH
- struct eeh_dev *edev;
-#endif
int ret;
/* Search only direct children of the bus */
@@ -109,11 +111,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
if (!found)
return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
- edev = of_node_to_eeh_dev(dn);
- if (edev && edev->pe && edev->pe->state & EEH_PE_RESET)
- return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
ret = rtas_read_config(pdn, where, size, val);
if (*val == EEH_IO_ERROR_VALUE(size) &&
@@ -132,6 +129,11 @@ int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
return PCIBIOS_DEVICE_NOT_FOUND;
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+ if (pdn->edev && pdn->edev->pe &&
+ (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+ return PCIBIOS_SET_FAILED;
+#endif
addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
buid = pdn->phb->buid;
@@ -155,10 +157,6 @@ static int rtas_pci_write_config(struct pci_bus *bus,
struct device_node *busdn, *dn;
struct pci_dn *pdn;
bool found = false;
-#ifdef CONFIG_EEH
- struct eeh_dev *edev;
-#endif
- int ret;
/* Search only direct children of the bus */
busdn = pci_bus_to_OF_node(bus);
@@ -173,14 +171,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
if (!found)
return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
- edev = of_node_to_eeh_dev(dn);
- if (edev && edev->pe && (edev->pe->state & EEH_PE_RESET))
- return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
- ret = rtas_write_config(pdn, where, size, val);
- return ret;
+ return rtas_write_config(pdn, where, size, val);
}
static struct pci_ops rtas_pci_ops = {
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index cd07d79ad21c..4f3cfe1b6a33 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -522,36 +522,36 @@ void __init setup_system(void)
smp_release_cpus();
#endif
- printk("Starting Linux PPC64 %s\n", init_utsname()->version);
+ pr_info("Starting Linux PPC64 %s\n", init_utsname()->version);
- printk("-----------------------------------------------------\n");
- printk("ppc64_pft_size = 0x%llx\n", ppc64_pft_size);
- printk("phys_mem_size = 0x%llx\n", memblock_phys_mem_size());
+ pr_info("-----------------------------------------------------\n");
+ pr_info("ppc64_pft_size = 0x%llx\n", ppc64_pft_size);
+ pr_info("phys_mem_size = 0x%llx\n", memblock_phys_mem_size());
if (ppc64_caches.dline_size != 0x80)
- printk("dcache_line_size = 0x%x\n", ppc64_caches.dline_size);
+ pr_info("dcache_line_size = 0x%x\n", ppc64_caches.dline_size);
if (ppc64_caches.iline_size != 0x80)
- printk("icache_line_size = 0x%x\n", ppc64_caches.iline_size);
+ pr_info("icache_line_size = 0x%x\n", ppc64_caches.iline_size);
- printk("cpu_features = 0x%016lx\n", cur_cpu_spec->cpu_features);
- printk(" possible = 0x%016lx\n", CPU_FTRS_POSSIBLE);
- printk(" always = 0x%016lx\n", CPU_FTRS_ALWAYS);
- printk("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
+ pr_info("cpu_features = 0x%016lx\n", cur_cpu_spec->cpu_features);
+ pr_info(" possible = 0x%016lx\n", CPU_FTRS_POSSIBLE);
+ pr_info(" always = 0x%016lx\n", CPU_FTRS_ALWAYS);
+ pr_info("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
cur_cpu_spec->cpu_user_features2);
- printk("mmu_features = 0x%08x\n", cur_cpu_spec->mmu_features);
- printk("firmware_features = 0x%016lx\n", powerpc_firmware_features);
+ pr_info("mmu_features = 0x%08x\n", cur_cpu_spec->mmu_features);
+ pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features);
#ifdef CONFIG_PPC_STD_MMU_64
if (htab_address)
- printk("htab_address = 0x%p\n", htab_address);
+ pr_info("htab_address = 0x%p\n", htab_address);
- printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
+ pr_info("htab_hash_mask = 0x%lx\n", htab_hash_mask);
#endif
if (PHYSICAL_START > 0)
- printk("physical_start = 0x%llx\n",
+ pr_info("physical_start = 0x%llx\n",
(unsigned long long)PHYSICAL_START);
- printk("-----------------------------------------------------\n");
+ pr_info("-----------------------------------------------------\n");
DBG(" <- setup_system()\n");
}
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 3d30ef1038e5..ea43a347a104 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -50,7 +50,7 @@ void save_stack_trace(struct stack_trace *trace)
{
unsigned long sp;
- asm("mr %0,1" : "=r" (sp));
+ sp = current_stack_pointer();
save_context_stack(trace, sp, current, 1);
}
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 649666d5d1c2..e5236c24dc07 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -8,6 +8,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#define pr_fmt(fmt) "numa: " fmt
+
#include <linux/threads.h>
#include <linux/bootmem.h>
#include <linux/init.h>
@@ -1153,6 +1155,22 @@ static int __init early_numa(char *p)
}
early_param("numa", early_numa);
+static bool topology_updates_enabled = true;
+
+static int __init early_topology_updates(char *p)
+{
+ if (!p)
+ return 0;
+
+ if (!strcmp(p, "off")) {
+ pr_info("Disabling topology updates\n");
+ topology_updates_enabled = false;
+ }
+
+ return 0;
+}
+early_param("topology_updates", early_topology_updates);
+
#ifdef CONFIG_MEMORY_HOTPLUG
/*
* Find the node associated with a hot added memory section for
@@ -1442,8 +1460,11 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity)
long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
u64 flags = 1;
int hwcpu = get_hard_smp_processor_id(cpu);
+ int i;
rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
+ for (i = 0; i < 6; i++)
+ retbuf[i] = cpu_to_be64(retbuf[i]);
vphn_unpack_associativity(retbuf, associativity);
return rc;
@@ -1539,6 +1560,9 @@ int arch_update_cpu_topology(void)
struct device *dev;
int weight, new_nid, i = 0;
+ if (!prrn_enabled && !vphn_enabled)
+ return 0;
+
weight = cpumask_weight(&cpu_associativity_changes_mask);
if (!weight)
return 0;
@@ -1592,6 +1616,15 @@ int arch_update_cpu_topology(void)
cpu = cpu_last_thread_sibling(cpu);
}
+ pr_debug("Topology update for the following CPUs:\n");
+ if (cpumask_weight(&updated_cpus)) {
+ for (ud = &updates[0]; ud; ud = ud->next) {
+ pr_debug("cpu %d moving from node %d "
+ "to %d\n", ud->cpu,
+ ud->old_nid, ud->new_nid);
+ }
+ }
+
/*
* In cases where we have nothing to update (because the updates list
* is too short or because the new topology is same as the old one),
@@ -1800,8 +1833,12 @@ static const struct file_operations topology_ops = {
static int topology_update_init(void)
{
- start_topology_update();
- proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops);
+ /* Do not poll for changes if disabled at boot */
+ if (topology_updates_enabled)
+ start_topology_update();
+
+ if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
+ return -ENOMEM;
return 0;
}
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 426814a2ede3..eba9cb10619c 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -373,7 +373,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
* moving forward, we have to return operational
* state during PE reset.
*/
- if (pe->state & EEH_PE_RESET) {
+ if (pe->state & EEH_PE_CFG_BLOCKED) {
result = (EEH_STATE_MMIO_ACTIVE |
EEH_STATE_DMA_ACTIVE |
EEH_STATE_MMIO_ENABLED |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 3e89cbf55885..1d19e7917d7f 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -169,6 +169,26 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
}
/*
+ * If the PE contains any one of following adapters, the
+ * PCI config space can't be accessed when dumping EEH log.
+ * Otherwise, we will run into fenced PHB caused by shortage
+ * of outbound credits in the adapter. The PCI config access
+ * should be blocked until PE reset. MMIO access is dropped
+ * by hardware certainly. In order to drop PCI config requests,
+ * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which
+ * will be checked in the backend for PE state retrival. If
+ * the PE becomes frozen for the first time and the flag has
+ * been set for the PE, we will set EEH_PE_CFG_BLOCKED for
+ * that PE to block its config space.
+ *
+ * Broadcom Austin 4-ports NICs (14e4:1657)
+ * Broadcom Shiner 2-ports 10G NICs (14e4:168e)
+ */
+ if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) ||
+ (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e))
+ edev->pe->state |= EEH_PE_CFG_RESTRICTED;
+
+ /*
* Cache the PE primary bus, which can't be fetched when
* full hotplug is in progress. In that case, all child
* PCI devices of the PE are expected to be removed prior
@@ -383,6 +403,39 @@ static int powernv_eeh_err_inject(struct eeh_pe *pe, int type, int func,
return ret;
}
+static inline bool powernv_eeh_cfg_blocked(struct device_node *dn)
+{
+ struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+
+ if (!edev || !edev->pe)
+ return false;
+
+ if (edev->pe->state & EEH_PE_CFG_BLOCKED)
+ return true;
+
+ return false;
+}
+
+static int powernv_eeh_read_config(struct device_node *dn,
+ int where, int size, u32 *val)
+{
+ if (powernv_eeh_cfg_blocked(dn)) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_SET_FAILED;
+ }
+
+ return pnv_pci_cfg_read(dn, where, size, val);
+}
+
+static int powernv_eeh_write_config(struct device_node *dn,
+ int where, int size, u32 val)
+{
+ if (powernv_eeh_cfg_blocked(dn))
+ return PCIBIOS_SET_FAILED;
+
+ return pnv_pci_cfg_write(dn, where, size, val);
+}
+
/**
* powernv_eeh_next_error - Retrieve next EEH error to handle
* @pe: Affected PE
@@ -440,8 +493,8 @@ static struct eeh_ops powernv_eeh_ops = {
.get_log = powernv_eeh_get_log,
.configure_bridge = powernv_eeh_configure_bridge,
.err_inject = powernv_eeh_err_inject,
- .read_config = pnv_pci_cfg_read,
- .write_config = pnv_pci_cfg_write,
+ .read_config = powernv_eeh_read_config,
+ .write_config = powernv_eeh_write_config,
.next_error = powernv_eeh_next_error,
.restore_config = powernv_eeh_restore_config
};
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index b642b0562f5a..d019b081df9d 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -194,6 +194,27 @@ static int __init opal_register_exception_handlers(void)
* fwnmi area at 0x7000 to provide the glue space to OPAL
*/
glue = 0x7000;
+
+ /*
+ * Check if we are running on newer firmware that exports
+ * OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to patch
+ * the HMI interrupt and we catch it directly in Linux.
+ *
+ * For older firmware (i.e currently released POWER8 System Firmware
+ * as of today <= SV810_087), we fallback to old behavior and let OPAL
+ * patch the HMI vector and handle it inside OPAL firmware.
+ *
+ * For newer firmware (in development/yet to be released) we will
+ * start catching/handling HMI directly in Linux.
+ */
+ if (!opal_check_token(OPAL_HANDLE_HMI)) {
+ pr_info("opal: Old firmware detected, OPAL handles HMIs.\n");
+ opal_register_exception_handler(
+ OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+ 0, glue);
+ glue += 128;
+ }
+
opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
#endif
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index b3ca77ddf36d..b2187d0068b8 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -505,7 +505,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose,
edev = of_node_to_eeh_dev(dn);
if (edev) {
if (edev->pe &&
- (edev->pe->state & EEH_PE_RESET))
+ (edev->pe->state & EEH_PE_CFG_BLOCKED))
return false;
if (edev->mode & EEH_DEV_REMOVED)
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index fdf01b660d59..6ad83bd11fe2 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -25,11 +25,11 @@
#include <asm/rtas.h>
struct cc_workarea {
- u32 drc_index;
- u32 zero;
- u32 name_offset;
- u32 prop_length;
- u32 prop_offset;
+ __be32 drc_index;
+ __be32 zero;
+ __be32 name_offset;
+ __be32 prop_length;
+ __be32 prop_offset;
};
void dlpar_free_cc_property(struct property *prop)
@@ -49,11 +49,11 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
if (!prop)
return NULL;
- name = (char *)ccwa + ccwa->name_offset;
+ name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
prop->name = kstrdup(name, GFP_KERNEL);
- prop->length = ccwa->prop_length;
- value = (char *)ccwa + ccwa->prop_offset;
+ prop->length = be32_to_cpu(ccwa->prop_length);
+ value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset);
prop->value = kmemdup(value, prop->length, GFP_KERNEL);
if (!prop->value) {
dlpar_free_cc_property(prop);
@@ -79,7 +79,7 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
if (!dn)
return NULL;
- name = (char *)ccwa + ccwa->name_offset;
+ name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
if (!dn->full_name) {
kfree(dn);
@@ -126,7 +126,7 @@ void dlpar_free_cc_nodes(struct device_node *dn)
#define CALL_AGAIN -2
#define ERR_CFG_USE -9003
-struct device_node *dlpar_configure_connector(u32 drc_index,
+struct device_node *dlpar_configure_connector(__be32 drc_index,
struct device_node *parent)
{
struct device_node *dn;
@@ -414,7 +414,7 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
if (!parent)
return -ENODEV;
- dn = dlpar_configure_connector(drc_index, parent);
+ dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
if (!dn)
return -EINVAL;
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index b174fa751d26..5c375f93c669 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -247,7 +247,7 @@ static int pseries_add_processor(struct device_node *np)
unsigned int cpu;
cpumask_var_t candidate_mask, tmp;
int err = -ENOSPC, len, nthreads, i;
- const u32 *intserv;
+ const __be32 *intserv;
intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
if (!intserv)
@@ -293,7 +293,7 @@ static int pseries_add_processor(struct device_node *np)
for_each_cpu(cpu, tmp) {
BUG_ON(cpu_present(cpu));
set_cpu_present(cpu, true);
- set_hard_smp_processor_id(cpu, *intserv++);
+ set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++));
}
err = 0;
out_unlock:
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index de1ec54a2a57..e32e00976a94 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -30,7 +30,6 @@
#include <linux/mm.h>
#include <linux/memblock.h>
#include <linux/spinlock.h>
-#include <linux/sched.h> /* for show_stack */
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
@@ -168,7 +167,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%llx\n", (u64)tcenum);
printk("\ttce val = 0x%llx\n", tce );
- show_stack(current, (unsigned long *)__get_SP());
+ dump_stack();
}
tcenum++;
@@ -257,7 +256,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\tnpages = 0x%llx\n", (u64)npages);
printk("\ttce[0] val = 0x%llx\n", tcep[0]);
- show_stack(current, (unsigned long *)__get_SP());
+ dump_stack();
}
return ret;
}
@@ -273,7 +272,7 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%llx\n", (u64)tcenum);
- show_stack(current, (unsigned long *)__get_SP());
+ dump_stack();
}
tcenum++;
@@ -292,7 +291,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
printk("\trc = %lld\n", rc);
printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\tnpages = 0x%llx\n", (u64)npages);
- show_stack(current, (unsigned long *)__get_SP());
+ dump_stack();
}
}
@@ -307,7 +306,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);
printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%llx\n", (u64)tcenum);
- show_stack(current, (unsigned long *)__get_SP());
+ dump_stack();
}
return tce_ret;
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 361add62abf1..1796c5438cc6 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -56,7 +56,8 @@ extern void hvc_vio_init_early(void);
/* Dynamic logical Partitioning/Mobility */
extern void dlpar_free_cc_nodes(struct device_node *);
extern void dlpar_free_cc_property(struct property *);
-extern struct device_node *dlpar_configure_connector(u32, struct device_node *);
+extern struct device_node *dlpar_configure_connector(__be32,
+ struct device_node *);
extern int dlpar_attach_node(struct device_node *);
extern int dlpar_detach_node(struct device_node *);
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 0c75214b6f92..73b64c73505b 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -145,59 +145,64 @@ void msi_bitmap_free(struct msi_bitmap *bmp)
#ifdef CONFIG_MSI_BITMAP_SELFTEST
-#define check(x) \
- if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
-
static void __init test_basics(void)
{
struct msi_bitmap bmp;
- int i, size = 512;
+ int rc, i, size = 512;
/* Can't allocate a bitmap of 0 irqs */
- check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
+ WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0);
/* of_node may be NULL */
- check(0 == msi_bitmap_alloc(&bmp, size, NULL));
+ WARN_ON(msi_bitmap_alloc(&bmp, size, NULL));
/* Should all be free by default */
- check(0 == bitmap_find_free_region(bmp.bitmap, size,
- get_count_order(size)));
+ WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
/* With no node, there's no msi-available-ranges, so expect > 0 */
- check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+ WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
/* Should all still be free */
- check(0 == bitmap_find_free_region(bmp.bitmap, size,
- get_count_order(size)));
+ WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
/* Check we can fill it up and then no more */
for (i = 0; i < size; i++)
- check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
+ WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
+ WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
/* Should all be allocated */
- check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0);
+ WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0);
/* And if we free one we can then allocate another */
msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
- check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
+ WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2);
+
+ /* Free most of them for the alignment tests */
+ msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
/* Check we get a naturally aligned offset */
- check(msi_bitmap_alloc_hwirqs(&bmp, 2) % 2 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 4) % 4 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 8) % 8 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 9) % 16 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 3) % 4 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 7) % 8 == 0);
- check(msi_bitmap_alloc_hwirqs(&bmp, 121) % 128 == 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
+ WARN_ON(rc < 0 && rc % 2 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
+ WARN_ON(rc < 0 && rc % 4 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
+ WARN_ON(rc < 0 && rc % 8 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
+ WARN_ON(rc < 0 && rc % 16 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
+ WARN_ON(rc < 0 && rc % 4 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
+ WARN_ON(rc < 0 && rc % 8 != 0);
+ rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
+ WARN_ON(rc < 0 && rc % 128 != 0);
msi_bitmap_free(&bmp);
- /* Clients may check bitmap == NULL for "not-allocated" */
- check(bmp.bitmap == NULL);
+ /* Clients may WARN_ON bitmap == NULL for "not-allocated" */
+ WARN_ON(bmp.bitmap != NULL);
kfree(bmp.bitmap);
}
@@ -219,14 +224,13 @@ static void __init test_of_node(void)
of_node_init(&of_node);
of_node.full_name = node_name;
- check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
+ WARN_ON(msi_bitmap_alloc(&bmp, size, &of_node));
/* No msi-available-ranges, so expect > 0 */
- check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+ WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
/* Should all still be free */
- check(0 == bitmap_find_free_region(bmp.bitmap, size,
- get_count_order(size)));
+ WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
/* Now create a fake msi-available-ranges property */
@@ -240,11 +244,11 @@ static void __init test_of_node(void)
of_node.properties = &prop;
/* msi-available-ranges, so expect == 0 */
- check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
+ WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
/* Check we got the expected result */
- check(0 == bitmap_parselist(expected_str, expected, size));
- check(bitmap_equal(expected, bmp.bitmap, size));
+ WARN_ON(bitmap_parselist(expected_str, expected, size));
+ WARN_ON(!bitmap_equal(expected, bmp.bitmap, size));
msi_bitmap_free(&bmp);
kfree(bmp.bitmap);
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h
index 940ac49198db..4197c89c52d4 100644
--- a/arch/s390/include/uapi/asm/unistd.h
+++ b/arch/s390/include/uapi/asm/unistd.h
@@ -286,7 +286,8 @@
#define __NR_seccomp 348
#define __NR_getrandom 349
#define __NR_memfd_create 350
-#define NR_syscalls 351
+#define __NR_bpf 351
+#define NR_syscalls 352
/*
* There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
index faf6caa510dc..c4f7a3d655b8 100644
--- a/arch/s390/kernel/compat_wrapper.c
+++ b/arch/s390/kernel/compat_wrapper.c
@@ -217,3 +217,4 @@ COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int,
COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
+COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 6fe886ac2db5..9f7087fd58de 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -359,3 +359,4 @@ SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
+SYSCALL(sys_bpf,sys_bpf,compat_sys_bpf)
diff --git a/arch/s390/kernel/uprobes.c b/arch/s390/kernel/uprobes.c
index 956f4f7a591c..f6b3cd056ec2 100644
--- a/arch/s390/kernel/uprobes.c
+++ b/arch/s390/kernel/uprobes.c
@@ -5,13 +5,13 @@
* Author(s): Jan Willeke,
*/
-#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/uprobes.h>
#include <linux/compat.h>
#include <linux/kdebug.h>
#include <asm/switch_to.h>
#include <asm/facility.h>
+#include <asm/kprobes.h>
#include <asm/dis.h>
#include "entry.h"
diff --git a/arch/s390/lib/probes.c b/arch/s390/lib/probes.c
index c5d64a099719..ae90e1ae3607 100644
--- a/arch/s390/lib/probes.c
+++ b/arch/s390/lib/probes.c
@@ -4,7 +4,7 @@
* Copyright IBM Corp. 2014
*/
-#include <linux/kprobes.h>
+#include <asm/kprobes.h>
#include <asm/dis.h>
int probe_is_prohibited_opcode(u16 *insn)
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 296b61a4af59..1b79ca67392f 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -656,7 +656,7 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr)
}
pgste_set_unlock(ptep, pgste);
out_pte:
- pte_unmap_unlock(*ptep, ptl);
+ pte_unmap_unlock(ptep, ptl);
}
EXPORT_SYMBOL_GPL(__gmap_zap);
@@ -943,7 +943,7 @@ retry:
}
if (!(pte_val(*ptep) & _PAGE_INVALID) &&
(pte_val(*ptep) & _PAGE_PROTECT)) {
- pte_unmap_unlock(*ptep, ptl);
+ pte_unmap_unlock(ptep, ptl);
if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
up_read(&mm->mmap_sem);
return -EFAULT;
@@ -974,7 +974,7 @@ retry:
pgste_val(new) |= PGSTE_UC_BIT;
pgste_set_unlock(ptep, new);
- pte_unmap_unlock(*ptep, ptl);
+ pte_unmap_unlock(ptep, ptl);
up_read(&mm->mmap_sem);
return 0;
}
diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h
index f34682430fcf..2e3a4add8591 100644
--- a/arch/sparc/include/asm/oplib_64.h
+++ b/arch/sparc/include/asm/oplib_64.h
@@ -62,7 +62,8 @@ struct linux_mem_p1275 {
/* You must call prom_init() before using any of the library services,
* preferably as early as possible. Pass it the romvec pointer.
*/
-void prom_init(void *cif_handler, void *cif_stack);
+void prom_init(void *cif_handler);
+void prom_init_report(void);
/* Boot argument acquisition, returns the boot command line string. */
char *prom_getbootargs(void);
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
index f5fffd84d0dd..29d64b1758ed 100644
--- a/arch/sparc/include/asm/setup.h
+++ b/arch/sparc/include/asm/setup.h
@@ -48,6 +48,8 @@ unsigned long safe_compute_effective_address(struct pt_regs *, unsigned int);
#endif
#ifdef CONFIG_SPARC64
+void __init start_early_boot(void);
+
/* unaligned_64.c */
int handle_ldf_stq(u32 insn, struct pt_regs *regs);
void handle_ld_nf(u32 insn, struct pt_regs *regs);
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index ebaba6167dd4..88d322b67fac 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -65,13 +65,10 @@ struct pause_patch_entry {
extern struct pause_patch_entry __pause_3insn_patch,
__pause_3insn_patch_end;
-void __init per_cpu_patch(void);
void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
struct sun4v_1insn_patch_entry *);
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
struct sun4v_2insn_patch_entry *);
-void __init sun4v_patch(void);
-void __init boot_cpu_id_too_large(int cpu);
extern unsigned int dcache_parity_tl1_occurred;
extern unsigned int icache_parity_tl1_occurred;
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 4fdeb8040d4d..3d61fcae7ee3 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -672,14 +672,12 @@ tlb_fixup_done:
sethi %hi(init_thread_union), %g6
or %g6, %lo(init_thread_union), %g6
ldx [%g6 + TI_TASK], %g4
- mov %sp, %l6
wr %g0, ASI_P, %asi
mov 1, %g1
sllx %g1, THREAD_SHIFT, %g1
sub %g1, (STACKFRAME_SZ + STACK_BIAS), %g1
add %g6, %g1, %sp
- mov 0, %fp
/* Set per-cpu pointer initially to zero, this makes
* the boot-cpu use the in-kernel-image per-cpu areas
@@ -706,44 +704,14 @@ tlb_fixup_done:
nop
#endif
- mov %l6, %o1 ! OpenPROM stack
call prom_init
mov %l7, %o0 ! OpenPROM cif handler
- /* Initialize current_thread_info()->cpu as early as possible.
- * In order to do that accurately we have to patch up the get_cpuid()
- * assembler sequences. And that, in turn, requires that we know
- * if we are on a Starfire box or not. While we're here, patch up
- * the sun4v sequences as well.
+ /* To create a one-register-window buffer between the kernel's
+ * initial stack and the last stack frame we use from the firmware,
+ * do the rest of the boot from a C helper function.
*/
- call check_if_starfire
- nop
- call per_cpu_patch
- nop
- call sun4v_patch
- nop
-
-#ifdef CONFIG_SMP
- call hard_smp_processor_id
- nop
- cmp %o0, NR_CPUS
- blu,pt %xcc, 1f
- nop
- call boot_cpu_id_too_large
- nop
- /* Not reached... */
-
-1:
-#else
- mov 0, %o0
-#endif
- sth %o0, [%g6 + TI_CPU]
-
- call prom_init_report
- nop
-
- /* Off we go.... */
- call start_kernel
+ call start_early_boot
nop
/* Not reached... */
diff --git a/arch/sparc/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S
index b7ddcdd1dea9..cdbfec299f2f 100644
--- a/arch/sparc/kernel/hvtramp.S
+++ b/arch/sparc/kernel/hvtramp.S
@@ -109,7 +109,6 @@ hv_cpu_startup:
sllx %g5, THREAD_SHIFT, %g5
sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
add %g6, %g5, %sp
- mov 0, %fp
call init_irqwork_curcpu
nop
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index e629b8377587..c38d19fc27ba 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -30,6 +30,7 @@
#include <linux/cpu.h>
#include <linux/initrd.h>
#include <linux/module.h>
+#include <linux/start_kernel.h>
#include <asm/io.h>
#include <asm/processor.h>
@@ -162,7 +163,7 @@ char reboot_command[COMMAND_LINE_SIZE];
static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
-void __init per_cpu_patch(void)
+static void __init per_cpu_patch(void)
{
struct cpuid_patch_entry *p;
unsigned long ver;
@@ -254,7 +255,7 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
}
}
-void __init sun4v_patch(void)
+static void __init sun4v_patch(void)
{
extern void sun4v_hvapi_init(void);
@@ -323,14 +324,25 @@ static void __init pause_patch(void)
}
}
-#ifdef CONFIG_SMP
-void __init boot_cpu_id_too_large(int cpu)
+void __init start_early_boot(void)
{
- prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
- cpu, NR_CPUS);
- prom_halt();
+ int cpu;
+
+ check_if_starfire();
+ per_cpu_patch();
+ sun4v_patch();
+
+ cpu = hard_smp_processor_id();
+ if (cpu >= NR_CPUS) {
+ prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
+ cpu, NR_CPUS);
+ prom_halt();
+ }
+ current_thread_info()->cpu = cpu;
+
+ prom_init_report();
+ start_kernel();
}
-#endif
/* On Ultra, we support all of the v8 capabilities. */
unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S
index 737f8cbc7d56..88ede1d53b4c 100644
--- a/arch/sparc/kernel/trampoline_64.S
+++ b/arch/sparc/kernel/trampoline_64.S
@@ -109,10 +109,13 @@ startup_continue:
brnz,pn %g1, 1b
nop
- sethi %hi(p1275buf), %g2
- or %g2, %lo(p1275buf), %g2
- ldx [%g2 + 0x10], %l2
- add %l2, -(192 + 128), %sp
+ /* Get onto temporary stack which will be in the locked
+ * kernel image.
+ */
+ sethi %hi(tramp_stack), %g1
+ or %g1, %lo(tramp_stack), %g1
+ add %g1, TRAMP_STACK_SIZE, %g1
+ sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp
flushw
/* Setup the loop variables:
@@ -394,7 +397,6 @@ after_lock_tlb:
sllx %g5, THREAD_SHIFT, %g5
sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
add %g6, %g5, %sp
- mov 0, %fp
rdpr %pstate, %o1
or %o1, PSTATE_IE, %o1
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index 1aed0432c64b..ae6ce383d4df 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -160,6 +160,36 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
return 1;
}
+int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
+ struct page **pages)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr, len, end;
+ unsigned long next, flags;
+ pgd_t *pgdp;
+ int nr = 0;
+
+ start &= PAGE_MASK;
+ addr = start;
+ len = (unsigned long) nr_pages << PAGE_SHIFT;
+ end = start + len;
+
+ local_irq_save(flags);
+ pgdp = pgd_offset(mm, addr);
+ do {
+ pgd_t pgd = *pgdp;
+
+ next = pgd_addr_end(addr, end);
+ if (pgd_none(pgd))
+ break;
+ if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+ break;
+ } while (pgdp++, addr = next, addr != end);
+ local_irq_restore(flags);
+
+ return nr;
+}
+
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
struct page **pages)
{
diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S
index 9c86b4b7d429..8050f381f518 100644
--- a/arch/sparc/prom/cif.S
+++ b/arch/sparc/prom/cif.S
@@ -11,11 +11,10 @@
.text
.globl prom_cif_direct
prom_cif_direct:
+ save %sp, -192, %sp
sethi %hi(p1275buf), %o1
or %o1, %lo(p1275buf), %o1
- ldx [%o1 + 0x0010], %o2 ! prom_cif_stack
- save %o2, -192, %sp
- ldx [%i1 + 0x0008], %l2 ! prom_cif_handler
+ ldx [%o1 + 0x0008], %l2 ! prom_cif_handler
mov %g4, %l0
mov %g5, %l1
mov %g6, %l3
diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c
index d95db755828f..110b0d78b864 100644
--- a/arch/sparc/prom/init_64.c
+++ b/arch/sparc/prom/init_64.c
@@ -26,13 +26,13 @@ phandle prom_chosen_node;
* It gets passed the pointer to the PROM vector.
*/
-extern void prom_cif_init(void *, void *);
+extern void prom_cif_init(void *);
-void __init prom_init(void *cif_handler, void *cif_stack)
+void __init prom_init(void *cif_handler)
{
phandle node;
- prom_cif_init(cif_handler, cif_stack);
+ prom_cif_init(cif_handler);
prom_chosen_node = prom_finddevice(prom_chosen_path);
if (!prom_chosen_node || (s32)prom_chosen_node == -1)
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c
index b2340f008ae0..545d8bb79b65 100644
--- a/arch/sparc/prom/p1275.c
+++ b/arch/sparc/prom/p1275.c
@@ -20,7 +20,6 @@
struct {
long prom_callback; /* 0x00 */
void (*prom_cif_handler)(long *); /* 0x08 */
- unsigned long prom_cif_stack; /* 0x10 */
} p1275buf;
extern void prom_world(int);
@@ -52,5 +51,4 @@ void p1275_cmd_direct(unsigned long *args)
void prom_cif_init(void *cif_handler, void *cif_stack)
{
p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
- p1275buf.prom_cif_stack = (unsigned long)cif_stack;
}
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index de8eebd6f67c..1acf605a646d 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -330,8 +330,10 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
size = pci->romsize + sizeof(*rom);
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to alloc mem for rom\n");
return status;
+ }
memset(rom, 0, sizeof(*rom));
@@ -344,14 +346,18 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
PCI_VENDOR_ID, 1, &(rom->vendor));
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to read rom->vendor\n");
goto free_struct;
+ }
status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
PCI_DEVICE_ID, 1, &(rom->devid));
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to read rom->devid\n");
goto free_struct;
+ }
status = efi_early->call(pci->get_location, pci, &(rom->segment),
&(rom->bus), &(rom->device), &(rom->function));
@@ -432,8 +438,10 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
size = pci->romsize + sizeof(*rom);
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to alloc mem for rom\n");
return status;
+ }
rom->data.type = SETUP_PCI;
rom->data.len = size - sizeof(struct setup_data);
@@ -444,14 +452,18 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
PCI_VENDOR_ID, 1, &(rom->vendor));
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to read rom->vendor\n");
goto free_struct;
+ }
status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
PCI_DEVICE_ID, 1, &(rom->devid));
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to read rom->devid\n");
goto free_struct;
+ }
status = efi_early->call(pci->get_location, pci, &(rom->segment),
&(rom->bus), &(rom->device), &(rom->function));
@@ -538,8 +550,10 @@ static void setup_efi_pci(struct boot_params *params)
EFI_LOADER_DATA,
size, (void **)&pci_handle);
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to alloc mem for pci_handle\n");
return;
+ }
status = efi_call_early(locate_handle,
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -1105,6 +1119,10 @@ struct boot_params *make_boot_params(struct efi_config *c)
memset(sdt, 0, sizeof(*sdt));
+ status = efi_parse_options(cmdline_ptr);
+ if (status != EFI_SUCCESS)
+ goto fail2;
+
status = handle_cmdline_files(sys_table, image,
(char *)(unsigned long)hdr->cmd_line_ptr,
"initrd=", hdr->initrd_addr_max,
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 0ec241ede5a2..9b11757975d0 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -81,24 +81,23 @@ extern u64 asmlinkage efi_call(void *fp, ...);
*/
#define __efi_call_virt(f, args...) efi_call_virt(f, args)
-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
- u32 type, u64 attribute);
+extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
+ u32 type, u64 attribute);
#endif /* CONFIG_X86_32 */
-extern int add_efi_memmap;
extern struct efi_scratch efi_scratch;
-extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
-extern int efi_memblock_x86_reserve_range(void);
-extern void efi_call_phys_prelog(void);
-extern void efi_call_phys_epilog(void);
-extern void efi_unmap_memmap(void);
-extern void efi_memory_uc(u64 addr, unsigned long size);
+extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
+extern int __init efi_memblock_x86_reserve_range(void);
+extern void __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(void);
+extern void __init efi_unmap_memmap(void);
+extern void __init efi_memory_uc(u64 addr, unsigned long size);
extern void __init efi_map_region(efi_memory_desc_t *md);
extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
extern void efi_sync_low_kernel_mappings(void);
-extern int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
-extern void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
extern void __init old_map_region(efi_memory_desc_t *md);
extern void __init runtime_code_page_mkexec(void);
extern void __init efi_runtime_mkexec(void);
@@ -162,16 +161,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
extern bool efi_reboot_required(void);
#else
-/*
- * IF EFI is not configured, have the EFI calls return -ENOSYS.
- */
-#define efi_call0(_f) (-ENOSYS)
-#define efi_call1(_f, _a1) (-ENOSYS)
-#define efi_call2(_f, _a1, _a2) (-ENOSYS)
-#define efi_call3(_f, _a1, _a2, _a3) (-ENOSYS)
-#define efi_call4(_f, _a1, _a2, _a3, _a4) (-ENOSYS)
-#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS)
-#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS)
static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
static inline bool efi_reboot_required(void)
{
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 7d603a71ab3a..6ed0c30d6a0c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -989,6 +989,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
}
+static inline u64 get_canonical(u64 la)
+{
+ return ((int64_t)la << 16) >> 16;
+}
+
+static inline bool is_noncanonical_address(u64 la)
+{
+#ifdef CONFIG_X86_64
+ return get_canonical(la) != la;
+#else
+ return false;
+#endif
+}
+
#define TSS_IOPB_BASE_OFFSET 0x66
#define TSS_BASE_SIZE 0x68
#define TSS_IOPB_SIZE (65536 / 8)
@@ -1050,7 +1064,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
unsigned long address);
void kvm_define_shared_msr(unsigned index, u32 msr);
-void kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
+int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index 0e79420376eb..990a2fe1588d 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -67,6 +67,7 @@
#define EXIT_REASON_EPT_MISCONFIG 49
#define EXIT_REASON_INVEPT 50
#define EXIT_REASON_PREEMPTION_TIMER 52
+#define EXIT_REASON_INVVPID 53
#define EXIT_REASON_WBINVD 54
#define EXIT_REASON_XSETBV 55
#define EXIT_REASON_APIC_WRITE 56
@@ -114,6 +115,7 @@
{ EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
{ EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
{ EXIT_REASON_INVD, "INVD" }, \
+ { EXIT_REASON_INVVPID, "INVVPID" }, \
{ EXIT_REASON_INVPCID, "INVPCID" }
#endif /* _UAPIVMX_H */
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a46207a05835..749f9fa38254 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -504,11 +504,6 @@ static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc);
}
-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
-{
- register_address_increment(ctxt, &ctxt->_eip, rel);
-}
-
static u32 desc_limit_scaled(struct desc_struct *desc)
{
u32 limit = get_desc_limit(desc);
@@ -569,6 +564,38 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
return emulate_exception(ctxt, NM_VECTOR, 0, false);
}
+static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
+ int cs_l)
+{
+ switch (ctxt->op_bytes) {
+ case 2:
+ ctxt->_eip = (u16)dst;
+ break;
+ case 4:
+ ctxt->_eip = (u32)dst;
+ break;
+ case 8:
+ if ((cs_l && is_noncanonical_address(dst)) ||
+ (!cs_l && (dst & ~(u32)-1)))
+ return emulate_gp(ctxt, 0);
+ ctxt->_eip = dst;
+ break;
+ default:
+ WARN(1, "unsupported eip assignment size\n");
+ }
+ return X86EMUL_CONTINUE;
+}
+
+static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
+{
+ return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64);
+}
+
+static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
+{
+ return assign_eip_near(ctxt, ctxt->_eip + rel);
+}
+
static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
{
u16 selector;
@@ -751,8 +778,10 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
unsigned size)
{
- if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
- return __do_insn_fetch_bytes(ctxt, size);
+ unsigned done_size = ctxt->fetch.end - ctxt->fetch.ptr;
+
+ if (unlikely(done_size < size))
+ return __do_insn_fetch_bytes(ctxt, size - done_size);
else
return X86EMUL_CONTINUE;
}
@@ -1416,7 +1445,9 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
/* Does not support long mode */
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
- u16 selector, int seg, u8 cpl, bool in_task_switch)
+ u16 selector, int seg, u8 cpl,
+ bool in_task_switch,
+ struct desc_struct *desc)
{
struct desc_struct seg_desc, old_desc;
u8 dpl, rpl;
@@ -1557,6 +1588,8 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
}
load:
ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
+ if (desc)
+ *desc = seg_desc;
return X86EMUL_CONTINUE;
exception:
return emulate_exception(ctxt, err_vec, err_code, true);
@@ -1566,7 +1599,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
u16 selector, int seg)
{
u8 cpl = ctxt->ops->cpl(ctxt);
- return __load_segment_descriptor(ctxt, selector, seg, cpl, false);
+ return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL);
}
static void write_register_operand(struct operand *op)
@@ -1960,17 +1993,31 @@ static int em_iret(struct x86_emulate_ctxt *ctxt)
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
{
int rc;
- unsigned short sel;
+ unsigned short sel, old_sel;
+ struct desc_struct old_desc, new_desc;
+ const struct x86_emulate_ops *ops = ctxt->ops;
+ u8 cpl = ctxt->ops->cpl(ctxt);
+
+ /* Assignment of RIP may only fail in 64-bit mode */
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
+ ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
+ VCPU_SREG_CS);
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
- rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
+ rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+ &new_desc);
if (rc != X86EMUL_CONTINUE)
return rc;
- ctxt->_eip = 0;
- memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
- return X86EMUL_CONTINUE;
+ rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+ if (rc != X86EMUL_CONTINUE) {
+ WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+ /* assigning eip failed; restore the old cs */
+ ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
+ return rc;
+ }
+ return rc;
}
static int em_grp45(struct x86_emulate_ctxt *ctxt)
@@ -1981,13 +2028,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
case 2: /* call near abs */ {
long int old_eip;
old_eip = ctxt->_eip;
- ctxt->_eip = ctxt->src.val;
+ rc = assign_eip_near(ctxt, ctxt->src.val);
+ if (rc != X86EMUL_CONTINUE)
+ break;
ctxt->src.val = old_eip;
rc = em_push(ctxt);
break;
}
case 4: /* jmp abs */
- ctxt->_eip = ctxt->src.val;
+ rc = assign_eip_near(ctxt, ctxt->src.val);
break;
case 5: /* jmp far */
rc = em_jmp_far(ctxt);
@@ -2022,30 +2071,47 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
static int em_ret(struct x86_emulate_ctxt *ctxt)
{
- ctxt->dst.type = OP_REG;
- ctxt->dst.addr.reg = &ctxt->_eip;
- ctxt->dst.bytes = ctxt->op_bytes;
- return em_pop(ctxt);
+ int rc;
+ unsigned long eip;
+
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+ return assign_eip_near(ctxt, eip);
}
static int em_ret_far(struct x86_emulate_ctxt *ctxt)
{
int rc;
- unsigned long cs;
+ unsigned long eip, cs;
+ u16 old_cs;
int cpl = ctxt->ops->cpl(ctxt);
+ struct desc_struct old_desc, new_desc;
+ const struct x86_emulate_ops *ops = ctxt->ops;
- rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
+ ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
+ VCPU_SREG_CS);
+
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
- if (ctxt->op_bytes == 4)
- ctxt->_eip = (u32)ctxt->_eip;
rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
/* Outer-privilege level return is not implemented */
if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
return X86EMUL_UNHANDLEABLE;
- rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
+ rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, 0, false,
+ &new_desc);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+ rc = assign_eip_far(ctxt, eip, new_desc.l);
+ if (rc != X86EMUL_CONTINUE) {
+ WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+ ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+ }
return rc;
}
@@ -2306,7 +2372,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
{
const struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
- u64 msr_data;
+ u64 msr_data, rcx, rdx;
int usermode;
u16 cs_sel = 0, ss_sel = 0;
@@ -2322,6 +2388,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
else
usermode = X86EMUL_MODE_PROT32;
+ rcx = reg_read(ctxt, VCPU_REGS_RCX);
+ rdx = reg_read(ctxt, VCPU_REGS_RDX);
+
cs.dpl = 3;
ss.dpl = 3;
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
@@ -2339,6 +2408,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
ss_sel = cs_sel + 8;
cs.d = 0;
cs.l = 1;
+ if (is_noncanonical_address(rcx) ||
+ is_noncanonical_address(rdx))
+ return emulate_gp(ctxt, 0);
break;
}
cs_sel |= SELECTOR_RPL_MASK;
@@ -2347,8 +2419,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
- ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX);
- *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX);
+ ctxt->_eip = rdx;
+ *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
return X86EMUL_CONTINUE;
}
@@ -2466,19 +2538,24 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
* Now load segment descriptors. If fault happens at this stage
* it is handled in a context of new task
*/
- ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2603,25 +2680,32 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
* Now load segment descriptors. If fault happenes at this stage
* it is handled in a context of new task
*/
- ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR,
+ cpl, true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, true);
+ ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl,
+ true, NULL);
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2888,10 +2972,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt)
static int em_call(struct x86_emulate_ctxt *ctxt)
{
+ int rc;
long rel = ctxt->src.val;
ctxt->src.val = (unsigned long)ctxt->_eip;
- jmp_rel(ctxt, rel);
+ rc = jmp_rel(ctxt, rel);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
return em_push(ctxt);
}
@@ -2900,34 +2987,50 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
u16 sel, old_cs;
ulong old_eip;
int rc;
+ struct desc_struct old_desc, new_desc;
+ const struct x86_emulate_ops *ops = ctxt->ops;
+ int cpl = ctxt->ops->cpl(ctxt);
- old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
old_eip = ctxt->_eip;
+ ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS);
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
- if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
+ rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+ &new_desc);
+ if (rc != X86EMUL_CONTINUE)
return X86EMUL_CONTINUE;
- ctxt->_eip = 0;
- memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
+ rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+ if (rc != X86EMUL_CONTINUE)
+ goto fail;
ctxt->src.val = old_cs;
rc = em_push(ctxt);
if (rc != X86EMUL_CONTINUE)
- return rc;
+ goto fail;
ctxt->src.val = old_eip;
- return em_push(ctxt);
+ rc = em_push(ctxt);
+ /* If we failed, we tainted the memory, but the very least we should
+ restore cs */
+ if (rc != X86EMUL_CONTINUE)
+ goto fail;
+ return rc;
+fail:
+ ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+ return rc;
+
}
static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
{
int rc;
+ unsigned long eip;
- ctxt->dst.type = OP_REG;
- ctxt->dst.addr.reg = &ctxt->_eip;
- ctxt->dst.bytes = ctxt->op_bytes;
- rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+ rc = assign_eip_near(ctxt, eip);
if (rc != X86EMUL_CONTINUE)
return rc;
rsp_increment(ctxt, ctxt->src.val);
@@ -3254,20 +3357,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
static int em_loop(struct x86_emulate_ctxt *ctxt)
{
+ int rc = X86EMUL_CONTINUE;
+
register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
(ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
- jmp_rel(ctxt, ctxt->src.val);
+ rc = jmp_rel(ctxt, ctxt->src.val);
- return X86EMUL_CONTINUE;
+ return rc;
}
static int em_jcxz(struct x86_emulate_ctxt *ctxt)
{
+ int rc = X86EMUL_CONTINUE;
+
if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
- jmp_rel(ctxt, ctxt->src.val);
+ rc = jmp_rel(ctxt, ctxt->src.val);
- return X86EMUL_CONTINUE;
+ return rc;
}
static int em_in(struct x86_emulate_ctxt *ctxt)
@@ -3355,6 +3462,12 @@ static int em_bswap(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
}
+static int em_clflush(struct x86_emulate_ctxt *ctxt)
+{
+ /* emulating clflush regardless of cpuid */
+ return X86EMUL_CONTINUE;
+}
+
static bool valid_cr(int nr)
{
switch (nr) {
@@ -3693,6 +3806,16 @@ static const struct opcode group11[] = {
X7(D(Undefined)),
};
+static const struct gprefix pfx_0f_ae_7 = {
+ I(SrcMem | ByteOp, em_clflush), N, N, N,
+};
+
+static const struct group_dual group15 = { {
+ N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
+}, {
+ N, N, N, N, N, N, N, N,
+} };
+
static const struct gprefix pfx_0f_6f_0f_7f = {
I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
};
@@ -3901,10 +4024,11 @@ static const struct opcode twobyte_table[256] = {
N, I(ImplicitOps | EmulateOnUD, em_syscall),
II(ImplicitOps | Priv, em_clts, clts), N,
DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
- N, D(ImplicitOps | ModRM), N, N,
+ N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
/* 0x10 - 0x1F */
N, N, N, N, N, N, N, N,
- D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
+ D(ImplicitOps | ModRM | SrcMem | NoAccess),
+ N, N, N, N, N, N, D(ImplicitOps | ModRM | SrcMem | NoAccess),
/* 0x20 - 0x2F */
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read),
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
@@ -3956,7 +4080,7 @@ static const struct opcode twobyte_table[256] = {
F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
- D(ModRM), F(DstReg | SrcMem | ModRM, em_imul),
+ GD(0, &group15), F(DstReg | SrcMem | ModRM, em_imul),
/* 0xB0 - 0xB7 */
I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
@@ -4473,10 +4597,10 @@ done_prefixes:
/* Decode and fetch the destination operand: register or memory. */
rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
-done:
if (ctxt->rip_relative)
ctxt->memopp->addr.mem.ea += ctxt->_eip;
+done:
return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
}
@@ -4726,7 +4850,7 @@ special_insn:
break;
case 0x70 ... 0x7f: /* jcc (short) */
if (test_cc(ctxt->b, ctxt->eflags))
- jmp_rel(ctxt, ctxt->src.val);
+ rc = jmp_rel(ctxt, ctxt->src.val);
break;
case 0x8d: /* lea r16/r32, m */
ctxt->dst.val = ctxt->src.addr.mem.ea;
@@ -4756,7 +4880,7 @@ special_insn:
break;
case 0xe9: /* jmp rel */
case 0xeb: /* jmp rel short */
- jmp_rel(ctxt, ctxt->src.val);
+ rc = jmp_rel(ctxt, ctxt->src.val);
ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
case 0xf4: /* hlt */
@@ -4881,13 +5005,11 @@ twobyte_insn:
break;
case 0x80 ... 0x8f: /* jnz rel, etc*/
if (test_cc(ctxt->b, ctxt->eflags))
- jmp_rel(ctxt, ctxt->src.val);
+ rc = jmp_rel(ctxt, ctxt->src.val);
break;
case 0x90 ... 0x9f: /* setcc r/m8 */
ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
break;
- case 0xae: /* clflush */
- break;
case 0xb6 ... 0xb7: /* movzx */
ctxt->dst.bytes = ctxt->op_bytes;
ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 518d86471b76..298781d4cfb4 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
return;
timer = &pit->pit_state.timer;
+ mutex_lock(&pit->pit_state.lock);
if (hrtimer_cancel(timer))
hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
+ mutex_unlock(&pit->pit_state.lock);
}
static void destroy_pit_timer(struct kvm_pit *pit)
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 806d58e3c320..fd49c867b25a 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -298,7 +298,7 @@ retry_walk:
}
#endif
walker->max_level = walker->level;
- ASSERT(!is_long_mode(vcpu) && is_pae(vcpu));
+ ASSERT(!(is_long_mode(vcpu) && !is_pae(vcpu)));
accessed_dirty = PT_GUEST_ACCESSED_MASK;
pt_access = pte_access = ACC_ALL;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 65510f624dfe..7527cefc5a43 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3251,7 +3251,7 @@ static int wrmsr_interception(struct vcpu_svm *svm)
msr.host_initiated = false;
svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
- if (svm_set_msr(&svm->vcpu, &msr)) {
+ if (kvm_set_msr(&svm->vcpu, &msr)) {
trace_kvm_msr_write_ex(ecx, data);
kvm_inject_gp(&svm->vcpu, 0);
} else {
@@ -3551,9 +3551,9 @@ static int handle_exit(struct kvm_vcpu *vcpu)
if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
|| !svm_exit_handlers[exit_code]) {
- kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
- kvm_run->hw.hardware_exit_reason = exit_code;
- return 0;
+ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code);
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
}
return svm_exit_handlers[exit_code](svm);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 0acac81f198b..a8b76c4c95e2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2659,12 +2659,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
default:
msr = find_msr_entry(vmx, msr_index);
if (msr) {
+ u64 old_msr_data = msr->data;
msr->data = data;
if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
preempt_disable();
- kvm_set_shared_msr(msr->index, msr->data,
- msr->mask);
+ ret = kvm_set_shared_msr(msr->index, msr->data,
+ msr->mask);
preempt_enable();
+ if (ret)
+ msr->data = old_msr_data;
}
break;
}
@@ -5291,7 +5294,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
msr.data = data;
msr.index = ecx;
msr.host_initiated = false;
- if (vmx_set_msr(vcpu, &msr) != 0) {
+ if (kvm_set_msr(vcpu, &msr) != 0) {
trace_kvm_msr_write_ex(ecx, data);
kvm_inject_gp(vcpu, 0);
return 1;
@@ -6743,6 +6746,12 @@ static int handle_invept(struct kvm_vcpu *vcpu)
return 1;
}
+static int handle_invvpid(struct kvm_vcpu *vcpu)
+{
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+}
+
/*
* The exit handlers return 1 if the exit was handled fully and guest execution
* may resume. Otherwise they set the kvm_run parameter to indicate what needs
@@ -6788,6 +6797,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
[EXIT_REASON_INVEPT] = handle_invept,
+ [EXIT_REASON_INVVPID] = handle_invvpid,
};
static const int kvm_vmx_max_exit_handlers =
@@ -7023,7 +7033,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
- case EXIT_REASON_INVEPT:
+ case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
/*
* VMX instructions trap unconditionally. This allows L1 to
* emulate them for its L2 guest, i.e., allows 3-level nesting!
@@ -7164,10 +7174,10 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
&& kvm_vmx_exit_handlers[exit_reason])
return kvm_vmx_exit_handlers[exit_reason](vcpu);
else {
- vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
- vcpu->run->hw.hardware_exit_reason = exit_reason;
+ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason);
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
}
- return 0;
}
static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 34c8f94331f8..0033df32a745 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -229,20 +229,25 @@ static void kvm_shared_msr_cpu_online(void)
shared_msr_update(i, shared_msrs_global.msrs[i]);
}
-void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
+int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
{
unsigned int cpu = smp_processor_id();
struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
+ int err;
if (((value ^ smsr->values[slot].curr) & mask) == 0)
- return;
+ return 0;
smsr->values[slot].curr = value;
- wrmsrl(shared_msrs_global.msrs[slot], value);
+ err = wrmsrl_safe(shared_msrs_global.msrs[slot], value);
+ if (err)
+ return 1;
+
if (!smsr->registered) {
smsr->urn.on_user_return = kvm_on_user_return;
user_return_notifier_register(&smsr->urn);
smsr->registered = true;
}
+ return 0;
}
EXPORT_SYMBOL_GPL(kvm_set_shared_msr);
@@ -987,7 +992,6 @@ void kvm_enable_efer_bits(u64 mask)
}
EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
-
/*
* Writes msr value into into the appropriate "register".
* Returns 0 on success, non-0 otherwise.
@@ -995,8 +999,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
*/
int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
{
+ switch (msr->index) {
+ case MSR_FS_BASE:
+ case MSR_GS_BASE:
+ case MSR_KERNEL_GS_BASE:
+ case MSR_CSTAR:
+ case MSR_LSTAR:
+ if (is_noncanonical_address(msr->data))
+ return 1;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ case MSR_IA32_SYSENTER_ESP:
+ /*
+ * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
+ * non-canonical address is written on Intel but not on
+ * AMD (which ignores the top 32-bits, because it does
+ * not implement 64-bit SYSENTER).
+ *
+ * 64-bit code should hence be able to write a non-canonical
+ * value on AMD. Making the address canonical ensures that
+ * vmentry does not fail on Intel after writing a non-canonical
+ * value, and that something deterministic happens if the guest
+ * invokes 64-bit SYSENTER.
+ */
+ msr->data = get_canonical(msr->data);
+ }
return kvm_x86_ops->set_msr(vcpu, msr);
}
+EXPORT_SYMBOL_GPL(kvm_set_msr);
/*
* Adapt set_msr() to msr_io()'s calling convention
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c
index f15103dff4b4..d143d216d52b 100644
--- a/arch/x86/platform/efi/efi-bgrt.c
+++ b/arch/x86/platform/efi/efi-bgrt.c
@@ -40,20 +40,40 @@ void __init efi_bgrt_init(void)
if (ACPI_FAILURE(status))
return;
- if (bgrt_tab->header.length < sizeof(*bgrt_tab))
+ if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
+ pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n",
+ bgrt_tab->header.length, sizeof(*bgrt_tab));
return;
- if (bgrt_tab->version != 1 || bgrt_tab->status != 1)
+ }
+ if (bgrt_tab->version != 1) {
+ pr_err("Ignoring BGRT: invalid version %u (expected 1)\n",
+ bgrt_tab->version);
+ return;
+ }
+ if (bgrt_tab->status != 1) {
+ pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
+ bgrt_tab->status);
+ return;
+ }
+ if (bgrt_tab->image_type != 0) {
+ pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
+ bgrt_tab->image_type);
return;
- if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
+ }
+ if (!bgrt_tab->image_address) {
+ pr_err("Ignoring BGRT: null image address\n");
return;
+ }
image = efi_lookup_mapped_addr(bgrt_tab->image_address);
if (!image) {
image = early_memremap(bgrt_tab->image_address,
sizeof(bmp_header));
ioremapped = true;
- if (!image)
+ if (!image) {
+ pr_err("Ignoring BGRT: failed to map image header memory\n");
return;
+ }
}
memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
@@ -61,14 +81,18 @@ void __init efi_bgrt_init(void)
early_iounmap(image, sizeof(bmp_header));
bgrt_image_size = bmp_header.size;
- bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL);
- if (!bgrt_image)
+ bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
+ if (!bgrt_image) {
+ pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n",
+ bgrt_image_size);
return;
+ }
if (ioremapped) {
image = early_memremap(bgrt_tab->image_address,
bmp_header.size);
if (!image) {
+ pr_err("Ignoring BGRT: failed to map image memory\n");
kfree(bgrt_image);
bgrt_image = NULL;
return;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 850da94fef30..dbc8627a5cdf 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -70,17 +70,7 @@ static efi_config_table_type_t arch_tables[] __initdata = {
u64 efi_setup; /* efi setup_data physical address */
-static bool disable_runtime __initdata = false;
-static int __init setup_noefi(char *arg)
-{
- disable_runtime = true;
- return 0;
-}
-early_param("noefi", setup_noefi);
-
-int add_efi_memmap;
-EXPORT_SYMBOL(add_efi_memmap);
-
+static int add_efi_memmap __initdata;
static int __init setup_add_efi_memmap(char *arg)
{
add_efi_memmap = 1;
@@ -96,7 +86,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
{
efi_status_t status;
- efi_call_phys_prelog();
+ efi_call_phys_prolog();
status = efi_call_phys(efi_phys.set_virtual_address_map,
memory_map_size, descriptor_size,
descriptor_version, virtual_map);
@@ -210,9 +200,12 @@ static void __init print_efi_memmap(void)
for (p = memmap.map, i = 0;
p < memmap.map_end;
p += memmap.desc_size, i++) {
+ char buf[64];
+
md = p;
- pr_info("mem%02u: type=%u, attr=0x%llx, range=[0x%016llx-0x%016llx) (%lluMB)\n",
- i, md->type, md->attribute, md->phys_addr,
+ pr_info("mem%02u: %s range=[0x%016llx-0x%016llx) (%lluMB)\n",
+ i, efi_md_typeattr_format(buf, sizeof(buf), md),
+ md->phys_addr,
md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
(md->num_pages >> (20 - EFI_PAGE_SHIFT)));
}
@@ -344,9 +337,9 @@ static int __init efi_runtime_init32(void)
}
/*
- * We will only need *early* access to the following two
- * EFI runtime services before set_virtual_address_map
- * is invoked.
+ * We will only need *early* access to the SetVirtualAddressMap
+ * EFI runtime service. All other runtime services will be called
+ * via the virtual mapping.
*/
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
@@ -368,9 +361,9 @@ static int __init efi_runtime_init64(void)
}
/*
- * We will only need *early* access to the following two
- * EFI runtime services before set_virtual_address_map
- * is invoked.
+ * We will only need *early* access to the SetVirtualAddressMap
+ * EFI runtime service. All other runtime services will be called
+ * via the virtual mapping.
*/
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
@@ -492,7 +485,7 @@ void __init efi_init(void)
if (!efi_runtime_supported())
pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
else {
- if (disable_runtime || efi_runtime_init())
+ if (efi_runtime_disabled() || efi_runtime_init())
return;
}
if (efi_memmap_init())
@@ -537,7 +530,7 @@ void __init runtime_code_page_mkexec(void)
}
}
-void efi_memory_uc(u64 addr, unsigned long size)
+void __init efi_memory_uc(u64 addr, unsigned long size)
{
unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
u64 npages;
@@ -732,6 +725,7 @@ static void __init kexec_enter_virtual_mode(void)
*/
if (!efi_is_native()) {
efi_unmap_memmap();
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return;
}
@@ -805,6 +799,7 @@ static void __init __efi_enter_virtual_mode(void)
new_memmap = efi_map_regions(&count, &pg_shift);
if (!new_memmap) {
pr_err("Error reallocating memory, EFI runtime non-functional!\n");
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return;
}
@@ -812,8 +807,10 @@ static void __init __efi_enter_virtual_mode(void)
BUG_ON(!efi.systab);
- if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
+ if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift)) {
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return;
+ }
efi_sync_low_kernel_mappings();
efi_dump_pagetable();
@@ -938,14 +935,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
return 0;
}
-static int __init parse_efi_cmdline(char *str)
+static int __init arch_parse_efi_cmdline(char *str)
{
- if (*str == '=')
- str++;
-
- if (!strncmp(str, "old_map", 7))
+ if (parse_option_str(str, "old_map"))
set_bit(EFI_OLD_MEMMAP, &efi.flags);
return 0;
}
-early_param("efi", parse_efi_cmdline);
+early_param("efi", arch_parse_efi_cmdline);
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index 9ee3491e31fb..40e7cda52936 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -33,7 +33,7 @@
/*
* To make EFI call EFI runtime service in physical addressing mode we need
- * prelog/epilog before/after the invocation to disable interrupt, to
+ * prolog/epilog before/after the invocation to disable interrupt, to
* claim EFI runtime service handler exclusively and to duplicate a memory in
* low memory space say 0 - 3G.
*/
@@ -41,11 +41,13 @@ static unsigned long efi_rt_eflags;
void efi_sync_low_kernel_mappings(void) {}
void __init efi_dump_pagetable(void) {}
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
{
return 0;
}
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages) {}
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+}
void __init efi_map_region(efi_memory_desc_t *md)
{
@@ -55,7 +57,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
-void efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
{
struct desc_ptr gdt_descr;
@@ -69,7 +71,7 @@ void efi_call_phys_prelog(void)
load_gdt(&gdt_descr);
}
-void efi_call_phys_epilog(void)
+void __init efi_call_phys_epilog(void)
{
struct desc_ptr gdt_descr;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 290d397e1dd9..35aecb6042fb 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -79,7 +79,7 @@ static void __init early_code_mapping_set_exec(int executable)
}
}
-void __init efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
{
unsigned long vaddress;
int pgd;
@@ -139,7 +139,7 @@ void efi_sync_low_kernel_mappings(void)
sizeof(pgd_t) * num_pgds);
}
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
{
unsigned long text;
struct page *page;
@@ -192,7 +192,7 @@ int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
return 0;
}
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
{
pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
diff --git a/arch/x86/platform/efi/efi_stub_32.S b/arch/x86/platform/efi/efi_stub_32.S
index fbe66e626c09..040192b50d02 100644
--- a/arch/x86/platform/efi/efi_stub_32.S
+++ b/arch/x86/platform/efi/efi_stub_32.S
@@ -27,13 +27,13 @@ ENTRY(efi_call_phys)
* set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
* the values of these registers are the same. And, the corresponding
* GDT entries are identical. So I will do nothing about segment reg
- * and GDT, but change GDT base register in prelog and epilog.
+ * and GDT, but change GDT base register in prolog and epilog.
*/
/*
* 1. Now I am running with EIP = <physical address> + PAGE_OFFSET.
* But to make it smoothly switch from virtual mode to flat mode.
- * The mapping of lower virtual memory has been created in prelog and
+ * The mapping of lower virtual memory has been created in prolog and
* epilog.
*/
movl $1f, %edx
diff --git a/arch/x86/platform/intel-mid/intel_mid_weak_decls.h b/arch/x86/platform/intel-mid/intel_mid_weak_decls.h
index 46aa25c8ce06..3c1c3866d82b 100644
--- a/arch/x86/platform/intel-mid/intel_mid_weak_decls.h
+++ b/arch/x86/platform/intel-mid/intel_mid_weak_decls.h
@@ -10,10 +10,9 @@
*/
-/* __attribute__((weak)) makes these declarations overridable */
/* For every CPU addition a new get_<cpuname>_ops interface needs
* to be added.
*/
-extern void *get_penwell_ops(void) __attribute__((weak));
-extern void *get_cloverview_ops(void) __attribute__((weak));
-extern void *get_tangier_ops(void) __attribute__((weak));
+extern void *get_penwell_ops(void);
+extern void *get_cloverview_ops(void);
+extern void *get_tangier_ops(void);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 1a3f0445432a..fac5e4f9607c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1636,9 +1636,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
xen_raw_console_write("mapping kernel into physical memory\n");
xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_start_info->nr_pages);
- /* Allocate and initialize top and mid mfn levels for p2m structure */
- xen_build_mfn_list_list();
-
/* keep using Xen gdt for now; no urgent need to change it */
#ifdef CONFIG_X86_32
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index f62af7647ec9..a8a1a3d08d4d 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1217,10 +1217,13 @@ static void __init xen_pagetable_p2m_copy(void)
static void __init xen_pagetable_init(void)
{
paging_init();
- xen_setup_shared_info();
#ifdef CONFIG_X86_64
xen_pagetable_p2m_copy();
#endif
+ /* Allocate and initialize top and mid mfn levels for p2m structure */
+ xen_build_mfn_list_list();
+
+ xen_setup_shared_info();
xen_post_allocator_init();
}
static void xen_write_cr2(unsigned long cr2)
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 9f5983b01ed9..b456b048eca9 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -163,6 +163,7 @@
#include <linux/hash.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
+#include <linux/bootmem.h>
#include <asm/cache.h>
#include <asm/setup.h>
@@ -181,21 +182,20 @@ static void __init m2p_override_init(void);
unsigned long xen_max_p2m_pfn __read_mostly;
+static unsigned long *p2m_mid_missing_mfn;
+static unsigned long *p2m_top_mfn;
+static unsigned long **p2m_top_mfn_p;
+
/* Placeholders for holes in the address space */
static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
-RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
/* For each I/O range remapped we may lose up to two leaf pages for the boundary
* violations and three mid pages to cover up to 3GB. With
@@ -272,11 +272,11 @@ static void p2m_init(unsigned long *p2m)
* Build the parallel p2m_top_mfn and p2m_mid_mfn structures
*
* This is called both at boot time, and after resuming from suspend:
- * - At boot time we're called very early, and must use extend_brk()
+ * - At boot time we're called rather early, and must use alloc_bootmem*()
* to allocate memory.
*
* - After resume we're called from within stop_machine, but the mfn
- * tree should alreay be completely allocated.
+ * tree should already be completely allocated.
*/
void __ref xen_build_mfn_list_list(void)
{
@@ -287,20 +287,17 @@ void __ref xen_build_mfn_list_list(void)
/* Pre-initialize p2m_top_mfn to be completely missing */
if (p2m_top_mfn == NULL) {
- p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_mid_missing_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
- p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
- p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_top_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
p2m_top_mfn_p_init(p2m_top_mfn_p);
- p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_top_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
p2m_top_mfn_init(p2m_top_mfn);
} else {
/* Reinitialise, mfn's all change after migration */
p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
- p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
}
for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -328,10 +325,9 @@ void __ref xen_build_mfn_list_list(void)
/*
* XXX boot-time only! We should never find
* missing parts of the mfn tree after
- * runtime. extend_brk() will BUG if we call
- * it too late.
+ * runtime.
*/
- mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ mid_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
p2m_top_mfn_p[topidx] = mid_mfn_p;
@@ -415,7 +411,6 @@ void __init xen_build_dynamic_phys_to_machine(void)
m2p_override_init();
}
#ifdef CONFIG_X86_64
-#include <linux/bootmem.h>
unsigned long __init xen_revector_p2m_tree(void)
{
unsigned long va_start;
@@ -477,7 +472,6 @@ unsigned long __init xen_revector_p2m_tree(void)
copy_page(new, mid_p);
p2m_top[topidx][mididx] = &mfn_list[pfn_free];
- p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]);
pfn_free += P2M_PER_PAGE;
@@ -538,12 +532,13 @@ static bool alloc_p2m(unsigned long pfn)
unsigned topidx, mididx;
unsigned long ***top_p, **mid;
unsigned long *top_mfn_p, *mid_mfn;
+ unsigned long *p2m_orig;
topidx = p2m_top_index(pfn);
mididx = p2m_mid_index(pfn);
top_p = &p2m_top[topidx];
- mid = *top_p;
+ mid = ACCESS_ONCE(*top_p);
if (mid == p2m_mid_missing) {
/* Mid level is missing, allocate a new one */
@@ -558,7 +553,7 @@ static bool alloc_p2m(unsigned long pfn)
}
top_mfn_p = &p2m_top_mfn[topidx];
- mid_mfn = p2m_top_mfn_p[topidx];
+ mid_mfn = ACCESS_ONCE(p2m_top_mfn_p[topidx]);
BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
@@ -566,6 +561,7 @@ static bool alloc_p2m(unsigned long pfn)
/* Separately check the mid mfn level */
unsigned long missing_mfn;
unsigned long mid_mfn_mfn;
+ unsigned long old_mfn;
mid_mfn = alloc_p2m_page();
if (!mid_mfn)
@@ -575,17 +571,19 @@ static bool alloc_p2m(unsigned long pfn)
missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
mid_mfn_mfn = virt_to_mfn(mid_mfn);
- if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
+ old_mfn = cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn);
+ if (old_mfn != missing_mfn) {
free_p2m_page(mid_mfn);
- else
+ mid_mfn = mfn_to_virt(old_mfn);
+ } else {
p2m_top_mfn_p[topidx] = mid_mfn;
+ }
}
- if (p2m_top[topidx][mididx] == p2m_identity ||
- p2m_top[topidx][mididx] == p2m_missing) {
+ p2m_orig = ACCESS_ONCE(p2m_top[topidx][mididx]);
+ if (p2m_orig == p2m_identity || p2m_orig == p2m_missing) {
/* p2m leaf page is missing */
unsigned long *p2m;
- unsigned long *p2m_orig = p2m_top[topidx][mididx];
p2m = alloc_p2m_page();
if (!p2m)
@@ -606,7 +604,6 @@ static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
{
unsigned topidx, mididx, idx;
unsigned long *p2m;
- unsigned long *mid_mfn_p;
topidx = p2m_top_index(pfn);
mididx = p2m_mid_index(pfn);
@@ -633,43 +630,21 @@ static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
p2m_top[topidx][mididx] = p2m;
- /* For save/restore we need to MFN of the P2M saved */
-
- mid_mfn_p = p2m_top_mfn_p[topidx];
- WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing),
- "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n",
- topidx, mididx);
- mid_mfn_p[mididx] = virt_to_mfn(p2m);
-
return true;
}
static bool __init early_alloc_p2m_middle(unsigned long pfn)
{
unsigned topidx = p2m_top_index(pfn);
- unsigned long *mid_mfn_p;
unsigned long **mid;
mid = p2m_top[topidx];
- mid_mfn_p = p2m_top_mfn_p[topidx];
if (mid == p2m_mid_missing) {
mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
p2m_mid_init(mid, p2m_missing);
p2m_top[topidx] = mid;
-
- BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
- }
- /* And the save/restore P2M tables.. */
- if (mid_mfn_p == p2m_mid_missing_mfn) {
- mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
-
- p2m_top_mfn_p[topidx] = mid_mfn_p;
- p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
- /* Note: we don't set mid_mfn_p[midix] here,
- * look in early_alloc_p2m() */
}
return true;
}
@@ -680,14 +655,13 @@ static bool __init early_alloc_p2m_middle(unsigned long pfn)
* replace the P2M leaf with a p2m_missing or p2m_identity.
* Stick the old page in the new P2M tree location.
*/
-bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn)
+static bool __init early_can_reuse_p2m_middle(unsigned long set_pfn)
{
unsigned topidx;
unsigned mididx;
unsigned ident_pfns;
unsigned inv_pfns;
unsigned long *p2m;
- unsigned long *mid_mfn_p;
unsigned idx;
unsigned long pfn;
@@ -733,11 +707,6 @@ bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_
found:
/* Found one, replace old with p2m_identity or p2m_missing */
p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing);
- /* And the other for save/restore.. */
- mid_mfn_p = p2m_top_mfn_p[topidx];
- /* NOTE: Even if it is a p2m_identity it should still be point to
- * a page filled with INVALID_P2M_ENTRY entries. */
- mid_mfn_p[mididx] = virt_to_mfn(p2m_missing);
/* Reset where we want to stick the old page in. */
topidx = p2m_top_index(set_pfn);
@@ -752,8 +721,6 @@ found:
p2m_init(p2m);
p2m_top[topidx][mididx] = p2m;
- mid_mfn_p = p2m_top_mfn_p[topidx];
- mid_mfn_p[mididx] = virt_to_mfn(p2m);
return true;
}
@@ -763,7 +730,7 @@ bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
if (!early_alloc_p2m_middle(pfn))
return false;
- if (early_can_reuse_p2m_middle(pfn, mfn))
+ if (early_can_reuse_p2m_middle(pfn))
return __set_phys_to_machine(pfn, mfn);
if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index af7216128d93..29834b3fd87f 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -595,6 +595,7 @@ char * __init xen_memory_setup(void)
rc = 0;
}
BUG_ON(rc);
+ BUG_ON(memmap.nr_entries == 0);
/*
* Xen won't allow a 1:1 mapping to be created to UNUSABLE
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index a1d430b112b3..f473d268d387 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -158,7 +158,7 @@ cycle_t xen_clocksource_read(void)
cycle_t ret;
preempt_disable_notrace();
- src = this_cpu_ptr(&xen_vcpu->time);
+ src = &__this_cpu_read(xen_vcpu)->time;
ret = pvclock_clocksource_read(src);
preempt_enable_notrace();
return ret;