diff options
author | Kevin Hilman <khilman@linaro.org> | 2014-09-05 08:01:52 -0700 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2014-09-05 08:05:56 -0700 |
commit | 95f6e8142d82789eca977ccdd6153a48b343fde9 (patch) | |
tree | ef39263a5bbc5c497d8603b77d2db1316a2845fc /arch | |
parent | 28c2260f13c8ea3be6fcba1609502874f868284b (diff) | |
parent | c7cc9ba11f8c09a4d12af0fc4aa9f9b026cdd354 (diff) |
Merge tag 'omap-fixes-against-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
Merge "omap fixes against v3.17-rc3" from Tony Lindgren:
Few fixes for omaps mostly for various devices to get them working
properly on the new am437x and dra7 hardware for several devices
such as I2C, NAND, DDR3 and USB. There's also a clock fix for omap3.
And also included are two minor cosmetic fixes that are not
stictly fixes for the new hardware support added recently to
downgrade a GPMC warning into a debug statement, and fix the
confusing comments for dra7-evm spi1 mux.
Note that these are all .dts changes except for a GPMC change.
* tag 'omap-fixes-against-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (255 commits)
ARM: dts: dra7-evm: Add vtt regulator support
ARM: dts: dra7-evm: Fix spi1 mux documentation
ARM: dts: am43x-epos-evm: Disable QSPI to prevent conflict with GPMC-NAND
ARM: OMAP2+: gpmc: Don't complain if wait pin is used without r/w monitoring
ARM: dts: am43xx-epos-evm: Don't use read/write wait monitoring
ARM: dts: am437x-gp-evm: Don't use read/write wait monitoring
ARM: dts: am437x-gp-evm: Use BCH16 ECC scheme instead of BCH8
ARM: dts: am43x-epos-evm: Use BCH16 ECC scheme instead of BCH8
ARM: dts: am4372: fix USB regs size
ARM: dts: am437x-gp: switch i2c0 to 100KHz
ARM: dts: dra7-evm: Fix 8th NAND partition's name
ARM: dts: dra7-evm: Fix i2c3 pinmux and frequency
Linux 3.17-rc3
...
Signed-off-by: Kevin Hilman <khilman@linaro.org>
Diffstat (limited to 'arch')
77 files changed, 714 insertions, 325 deletions
diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h index 5ebab5895ed..f05bdb4b1cb 100644 --- a/arch/alpha/include/asm/io.h +++ b/arch/alpha/include/asm/io.h @@ -500,10 +500,14 @@ extern inline void writeq(u64 b, volatile void __iomem *addr) #define outb_p outb #define outw_p outw #define outl_p outl -#define readb_relaxed(addr) __raw_readb(addr) -#define readw_relaxed(addr) __raw_readw(addr) -#define readl_relaxed(addr) __raw_readl(addr) -#define readq_relaxed(addr) __raw_readq(addr) +#define readb_relaxed(addr) __raw_readb(addr) +#define readw_relaxed(addr) __raw_readw(addr) +#define readl_relaxed(addr) __raw_readl(addr) +#define readq_relaxed(addr) __raw_readq(addr) +#define writeb_relaxed(b, addr) __raw_writeb(b, addr) +#define writew_relaxed(b, addr) __raw_writew(b, addr) +#define writel_relaxed(b, addr) __raw_writel(b, addr) +#define writeq_relaxed(b, addr) __raw_writeq(b, addr) #define mmiowb() diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index f2c94402e2c..c509d306db4 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -3,7 +3,7 @@ #include <uapi/asm/unistd.h> -#define NR_SYSCALLS 508 +#define NR_SYSCALLS 511 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/arch/alpha/include/uapi/asm/unistd.h b/arch/alpha/include/uapi/asm/unistd.h index 53ae7bb1bfd..d214a035810 100644 --- a/arch/alpha/include/uapi/asm/unistd.h +++ b/arch/alpha/include/uapi/asm/unistd.h @@ -469,5 +469,8 @@ #define __NR_process_vm_writev 505 #define __NR_kcmp 506 #define __NR_finit_module 507 +#define __NR_sched_setattr 508 +#define __NR_sched_getattr 509 +#define __NR_renameat2 510 #endif /* _UAPI_ALPHA_UNISTD_H */ diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index dca9b3fb007..24789713f1e 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -526,6 +526,9 @@ sys_call_table: .quad sys_process_vm_writev /* 505 */ .quad sys_kcmp .quad sys_finit_module + .quad sys_sched_setattr + .quad sys_sched_getattr + .quad sys_renameat2 /* 510 */ .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 4670afc3b97..e88ddbf990e 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -581,6 +581,7 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) tot_sz -= sz; } } +EXPORT_SYMBOL(flush_icache_range); /* * General purpose helper to make I and D cache lines consistent. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c49a775937d..32cbbd56590 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1983,8 +1983,6 @@ config XIP_PHYS_ADDR config KEXEC bool "Kexec system call (EXPERIMENTAL)" depends on (!SMP || PM_SLEEP_SMP) - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 9b3d2ba82f1..8689949bdba 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -804,7 +804,7 @@ usb1: usb@48390000 { compatible = "synopsys,dwc3"; - reg = <0x48390000 0x17000>; + reg = <0x48390000 0x10000>; interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; phys = <&usb2_phy1>; phy-names = "usb2-phy"; @@ -826,7 +826,7 @@ usb2: usb@483d0000 { compatible = "synopsys,dwc3"; - reg = <0x483d0000 0x17000>; + reg = <0x483d0000 0x10000>; interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; phys = <&usb2_phy2>; phy-names = "usb2-phy"; diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 646a6eade78..e7ac47fa661 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -260,7 +260,7 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins>; - clock-frequency = <400000>; + clock-frequency = <100000>; tps65218: tps65218@24 { reg = <0x24>; @@ -424,7 +424,7 @@ ranges = <0 0 0 0x01000000>; /* minimum GPMC partition = 16MB */ nand@0,0 { reg = <0 0 4>; /* device IO registers */ - ti,nand-ecc-opt = "bch8"; + ti,nand-ecc-opt = "bch16"; ti,elm-id = <&elm>; nand-bus-width = <8>; gpmc,device-width = <1>; @@ -443,8 +443,6 @@ gpmc,rd-cycle-ns = <40>; gpmc,wr-cycle-ns = <40>; gpmc,wait-pin = <0>; - gpmc,wait-on-read; - gpmc,wait-on-write; gpmc,bus-turnaround-ns = <0>; gpmc,cycle2cycle-delay-ns = <0>; gpmc,clk-activation-ns = <0>; diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index ed7dd239591..ac3e4859935 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -435,13 +435,13 @@ }; &gpmc { - status = "okay"; + status = "okay"; /* Disable QSPI when enabling GPMC (NAND) */ pinctrl-names = "default"; pinctrl-0 = <&nand_flash_x8>; ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ nand@0,0 { reg = <0 0 0>; /* CS0, offset 0 */ - ti,nand-ecc-opt = "bch8"; + ti,nand-ecc-opt = "bch16"; ti,elm-id = <&elm>; nand-bus-width = <8>; gpmc,device-width = <1>; @@ -459,8 +459,7 @@ gpmc,access-ns = <30>; /* tCEA + 4*/ gpmc,rd-cycle-ns = <40>; gpmc,wr-cycle-ns = <40>; - gpmc,wait-on-read = "true"; - gpmc,wait-on-write = "true"; + gpmc,wait-pin = <0>; gpmc,bus-turnaround-ns = <0>; gpmc,cycle2cycle-delay-ns = <0>; gpmc,clk-activation-ns = <0>; @@ -557,7 +556,7 @@ }; &qspi { - status = "okay"; + status = "disabled"; /* Disable GPMC (NAND) when enabling QSPI */ pinctrl-names = "default"; pinctrl-0 = <&qspi1_default>; diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 50f8022905a..e03fbf3c688 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -8,6 +8,7 @@ /dts-v1/; #include "dra74x.dtsi" +#include <dt-bindings/gpio/gpio.h> / { model = "TI DRA742"; @@ -24,9 +25,29 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + vtt_fixed: fixedregulator-vtt { + compatible = "regulator-fixed"; + regulator-name = "vtt_fixed"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>; + }; }; &dra7_pmx_core { + pinctrl-names = "default"; + pinctrl-0 = <&vtt_pin>; + + vtt_pin: pinmux_vtt_pin { + pinctrl-single,pins = < + 0x3b4 (PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */ + >; + }; + i2c1_pins: pinmux_i2c1_pins { pinctrl-single,pins = < 0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */ @@ -43,20 +64,19 @@ i2c3_pins: pinmux_i2c3_pins { pinctrl-single,pins = < - 0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */ - 0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */ + 0x288 (PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */ + 0x28c (PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */ >; }; mcspi1_pins: pinmux_mcspi1_pins { pinctrl-single,pins = < - 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */ - 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */ - 0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */ - 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */ - 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */ - 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */ - 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */ + 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */ + 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */ + 0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */ + 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */ + 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */ + 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */ >; }; @@ -284,7 +304,7 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&i2c3_pins>; - clock-frequency = <3400000>; + clock-frequency = <400000>; }; &mcspi1 { @@ -483,7 +503,7 @@ reg = <0x001c0000 0x00020000>; }; partition@7 { - label = "NAND.u-boot-env"; + label = "NAND.u-boot-env.backup1"; reg = <0x001e0000 0x00020000>; }; partition@8 { @@ -504,3 +524,8 @@ &usb2_phy2 { phy-supply = <&ldousb_reg>; }; + +&gpio7 { + ti,no-reset-on-init; + ti,no-idle-on-init; +}; diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index b15f1a77d68..1fe45d1f75e 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -353,7 +353,7 @@ }; twl_power: power { - compatible = "ti,twl4030-power-n900"; + compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off"; ti,use_poweroff; }; }; diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/omap3xxx-clocks.dtsi index e47ff69dcf7..5c375003bad 100644 --- a/arch/arm/boot/dts/omap3xxx-clocks.dtsi +++ b/arch/arm/boot/dts/omap3xxx-clocks.dtsi @@ -467,6 +467,7 @@ ti,bit-shift = <0x1e>; reg = <0x0d00>; ti,set-bit-to-disable; + ti,set-rate-parent; }; dpll4_m6_ck: dpll4_m6_ck { diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index fd43f7f55b7..79ecb4f34ff 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ "isb \n\t" \ "bl v7_flush_dcache_"__stringify(level)" \n\t" \ - "clrex \n\t" \ "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index 963a2515906..819777d0e91 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -74,6 +74,7 @@ #define ARM_CPU_PART_CORTEX_A12 0x4100c0d0 #define ARM_CPU_PART_CORTEX_A17 0x4100c0e0 #define ARM_CPU_PART_CORTEX_A15 0x4100c0f0 +#define ARM_CPU_PART_MASK 0xff00fff0 #define ARM_CPU_XSCALE_ARCH_MASK 0xe000 #define ARM_CPU_XSCALE_ARCH_V1 0x2000 @@ -179,7 +180,7 @@ static inline unsigned int __attribute_const__ read_cpuid_implementor(void) */ static inline unsigned int __attribute_const__ read_cpuid_part(void) { - return read_cpuid_id() & 0xff00fff0; + return read_cpuid_id() & ARM_CPU_PART_MASK; } static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void) diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index f4b46d39b9c..afb9cafd378 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_ABS32 2 #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 +#define R_ARM_TARGET1 38 #define R_ARM_V4BX 40 #define R_ARM_PREL31 42 #define R_ARM_MOVW_ABS_NC 43 diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index a252c0bfacf..0ad7d490ee6 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -8,6 +8,7 @@ #include <linux/cpumask.h> #include <linux/err.h> +#include <asm/cpu.h> #include <asm/cputype.h> /* @@ -25,6 +26,20 @@ static inline bool is_smp(void) #endif } +/** + * smp_cpuid_part() - return part id for a given cpu + * @cpu: logical cpu id. + * + * Return: part id of logical cpu passed as argument. + */ +static inline unsigned int smp_cpuid_part(int cpu) +{ + struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpu); + + return is_smp() ? cpu_info->cpuid & ARM_CPU_PART_MASK : + read_cpuid_part(); +} + /* all SMP configurations have the extended CPUID registers */ #ifndef CONFIG_MMU #define tlb_ops_need_broadcast() 0 diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 8db307d0954..2fdf8679b46 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -208,26 +208,21 @@ #endif .endif msr spsr_cxsf, \rpsr -#if defined(CONFIG_CPU_V6) - ldr r0, [sp] - strex r1, r2, [sp] @ clear the exclusive monitor - ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr -#elif defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -#else - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) + @ We must avoid clrex due to Cortex-A15 erratum #830321 + sub r0, sp, #4 @ uninhabited address + strex r1, r2, [r0] @ clear the exclusive monitor #endif + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr .endm .macro restore_user_regs, fast = 0, offset = 0 ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr lr, [sp, #\offset + S_PC]! @ get pc msr spsr_cxsf, r1 @ save in spsr_svc -#if defined(CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) + @ We must avoid clrex due to Cortex-A15 erratum #830321 strex r1, r2, [sp] @ clear the exclusive monitor -#elif defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor #endif .if \fast ldmdb sp, {r1 - lr}^ @ get calling r1 - lr @@ -261,7 +256,10 @@ .endif ldr lr, [sp, #S_SP] @ top of the stack ldrd r0, r1, [sp, #S_LR] @ calling lr and pc - clrex @ clear the exclusive monitor + + @ We must avoid clrex due to Cortex-A15 erratum #830321 + strex r2, r1, [sp, #S_LR] @ clear the exclusive monitor + stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context ldmia sp, {r0 - r12} mov sp, lr @@ -282,13 +280,16 @@ .endm #else /* ifdef CONFIG_CPU_V7M */ .macro restore_user_regs, fast = 0, offset = 0 - clrex @ clear the exclusive monitor mov r2, sp load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr lr, [sp, #\offset + S_PC] @ get pc add sp, sp, #\offset + S_SP msr spsr_cxsf, r1 @ save in spsr_svc + + @ We must avoid clrex due to Cortex-A15 erratum #830321 + strex r1, r2, [sp] @ clear the exclusive monitor + .if \fast ldmdb sp, {r1 - r12} @ get calling r1 - r12 .else diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 45e47815727..6a4dffefd35 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -91,6 +91,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, break; case R_ARM_ABS32: + case R_ARM_TARGET1: *(u32 *)loc += sym->st_value; break; diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c index b2f8b60cf0e..dc9a764a7c3 100644 --- a/arch/arm/mach-exynos/mcpm-exynos.c +++ b/arch/arm/mach-exynos/mcpm-exynos.c @@ -43,7 +43,6 @@ "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \ "isb\n\t"\ "bl v7_flush_dcache_"__stringify(level)"\n\t" \ - "clrex\n\t"\ "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \ "bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \ /* Dummy Load of a device register to avoid Erratum 799270 */ \ diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9f42d5437fc..2f97228f188 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1207,8 +1207,7 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p) } } - if ((p->wait_on_read || p->wait_on_write) && - (p->wait_pin > gpmc_nr_waitpins)) { + if (p->wait_pin > gpmc_nr_waitpins) { pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin); return -EINVAL; } @@ -1288,8 +1287,8 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) p->wait_on_write = of_property_read_bool(np, "gpmc,wait-on-write"); if (!p->wait_on_read && !p->wait_on_write) - pr_warn("%s: read/write wait monitoring not enabled!\n", - __func__); + pr_debug("%s: rd/wr wait monitoring not enabled!\n", + __func__); } } diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index 3815a8262af..8c48c5c22a3 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -17,12 +17,6 @@ */ .align 5 ENTRY(v6_early_abort) -#ifdef CONFIG_CPU_V6 - sub r1, sp, #4 @ Get unused stack location - strex r0, r1, [r1] @ Clear the exclusive monitor -#elif defined(CONFIG_CPU_32v6K) - clrex -#endif mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR /* diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S index 703375277ba..4812ad05421 100644 --- a/arch/arm/mm/abort-ev7.S +++ b/arch/arm/mm/abort-ev7.S @@ -13,12 +13,6 @@ */ .align 5 ENTRY(v7_early_abort) - /* - * The effect of data aborts on on the exclusive access monitor are - * UNPREDICTABLE. Do a CLREX to clear the state - */ - clrex - mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR diff --git a/arch/hexagon/mm/cache.c b/arch/hexagon/mm/cache.c index fe14ccf2856..0c76c802e31 100644 --- a/arch/hexagon/mm/cache.c +++ b/arch/hexagon/mm/cache.c @@ -68,6 +68,7 @@ void flush_icache_range(unsigned long start, unsigned long end) ); local_irq_restore(flags); } +EXPORT_SYMBOL(flush_icache_range); void hexagon_clean_dcache_range(unsigned long start, unsigned long end) { diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 64aefb76bd6..c84c88bbbbd 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -549,8 +549,6 @@ source "drivers/sn/Kconfig" config KEXEC bool "kexec system call" depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 3ff8c9a2533..87b7c7581b1 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -91,8 +91,6 @@ config MMU_SUN3 config KEXEC bool "kexec system call" depends on M68KCLASSIC - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index df51e78a72c..900c7e5333b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2396,8 +2396,6 @@ source "kernel/Kconfig.preempt" config KEXEC bool "Kexec system call" - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a577609f8ed..4bc7b62fb4b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -399,8 +399,6 @@ config PPC64_SUPPORTS_MEMORY_FAILURE config KEXEC bool "kexec system call" depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ab39ceb89ec..05c78bb5f57 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -48,8 +48,6 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC config KEXEC def_bool y - select CRYPTO - select CRYPTO_SHA256 config AUDIT_ARCH def_bool y diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 3802d2d3a18..940ac49198d 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h @@ -283,7 +283,10 @@ #define __NR_sched_setattr 345 #define __NR_sched_getattr 346 #define __NR_renameat2 347 -#define NR_syscalls 348 +#define __NR_seccomp 348 +#define __NR_getrandom 349 +#define __NR_memfd_create 350 +#define NR_syscalls 351 /* * 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 45cdb37aa6f..faf6caa510d 100644 --- a/arch/s390/kernel/compat_wrapper.c +++ b/arch/s390/kernel/compat_wrapper.c @@ -214,3 +214,6 @@ COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, fla COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags); COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags); COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags); +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) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 633ca750453..22aac5885ba 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2060,6 +2060,13 @@ void s390_reset_system(void (*func)(void *), void *data) S390_lowcore.program_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; + /* + * Clear subchannel ID and number to signal new kernel that no CCW or + * SCSI IPL has been done (for kexec and kdump) + */ + S390_lowcore.subchannel_id = 0; + S390_lowcore.subchannel_nr = 0; + /* Store status at absolute zero */ store_status(); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ae1d5be7dd8..82bc113e8c1 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -24,6 +24,7 @@ #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> +#include <linux/random.h> #include <linux/user.h> #include <linux/tty.h> #include <linux/ioport.h> @@ -61,6 +62,7 @@ #include <asm/diag.h> #include <asm/os_info.h> #include <asm/sclp.h> +#include <asm/sysinfo.h> #include "entry.h" /* @@ -766,6 +768,7 @@ static void __init setup_hwcaps(void) #endif get_cpu_id(&cpu_id); + add_device_randomness(&cpu_id, sizeof(cpu_id)); switch (cpu_id.machine) { case 0x9672: #if !defined(CONFIG_64BIT) @@ -804,6 +807,19 @@ static void __init setup_hwcaps(void) } /* + * Add system information as device randomness + */ +static void __init setup_randomness(void) +{ + struct sysinfo_3_2_2 *vmms; + + vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL); + if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count) + add_device_randomness(&vmms, vmms->count); + free_page((unsigned long) vmms); +} + +/* * Setup function called from init/main.c just after the banner * was printed. */ @@ -901,6 +917,9 @@ void __init setup_arch(char **cmdline_p) /* Setup zfcpdump support */ setup_zfcpdump(); + + /* Add system specific data to the random pool */ + setup_randomness(); } #ifdef CONFIG_32BIT diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index fe5cdf29a00..6fe886ac2db 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -356,3 +356,6 @@ SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module) SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */ SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr) 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 */ diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index b319846ad97..244fb4c81e2 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -598,8 +598,6 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" depends on SUPERH32 && MMU - select CRYPTO - select CRYPTO_SHA256 help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 097c2cdd117..f770e399262 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -229,6 +229,7 @@ void flush_icache_range(unsigned long start, unsigned long end) cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1); } +EXPORT_SYMBOL(flush_icache_range); void flush_icache_page(struct vm_area_struct *vma, struct page *page) { diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index a3ffe2dd483..7fcd492adbf 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -191,8 +191,6 @@ source "kernel/Kconfig.hz" config KEXEC bool "kexec system call" - select CRYPTO - select CRYPTO_SHA256 ---help--- kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index 01e8ab29f43..19eaa62d456 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c @@ -183,6 +183,7 @@ void flush_icache_range(unsigned long start, unsigned long end) preempt_enable(); } } +EXPORT_SYMBOL(flush_icache_range); /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c index 780d77388de..7c8fb7018dc 100644 --- a/arch/unicore32/kernel/signal.c +++ b/arch/unicore32/kernel/signal.c @@ -254,7 +254,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, err |= setup_sigframe(frame, regs, set); if (err == 0) - err |= setup_return(regs, &ksig->ka, frame->retcode, frame, usig); + err |= setup_return(regs, &ksig->ka, frame->retcode, frame, + ksig->sig); return err; } @@ -276,7 +277,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp); err |= setup_sigframe(&frame->sig, regs, set); if (err == 0) - err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig); + err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, + ksig->sig); if (err == 0) { /* @@ -303,7 +305,6 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall) { struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = current; sigset_t *oldset = sigmask_to_save(); int usig = ksig->sig; int ret; @@ -373,7 +374,7 @@ static void do_signal(struct pt_regs *regs, int syscall) if (!user_mode(regs)) return; - if (get_signsl(&ksig)) { + if (get_signal(&ksig)) { handle_signal(&ksig, regs, syscall); return; } diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild index 61b6d51866f..3942f74c92d 100644 --- a/arch/x86/Kbuild +++ b/arch/x86/Kbuild @@ -17,6 +17,4 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/ obj-y += platform/ obj-y += net/ -ifeq ($(CONFIG_X86_64),y) -obj-$(CONFIG_KEXEC) += purgatory/ -endif +obj-$(CONFIG_KEXEC_FILE) += purgatory/ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5d0bf1aa9dc..778178f4c7d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1585,9 +1585,6 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call" - select BUILD_BIN2C - select CRYPTO - select CRYPTO_SHA256 ---help--- kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -1602,9 +1599,22 @@ config KEXEC interface is strongly in flux, so no good recommendation can be made. +config KEXEC_FILE + bool "kexec file based system call" + select BUILD_BIN2C + depends on KEXEC + depends on X86_64 + depends on CRYPTO=y + depends on CRYPTO_SHA256=y + ---help--- + This is new version of kexec system call. This system call is + file based and takes file descriptors as system call argument + for kernel and initramfs as opposed to list of segments as + accepted by previous system call. + config KEXEC_VERIFY_SIG bool "Verify kernel signature during kexec_file_load() syscall" - depends on KEXEC + depends on KEXEC_FILE ---help--- This option makes kernel signature verification mandatory for kexec_file_load() syscall. If kernel is signature can not be diff --git a/arch/x86/Makefile b/arch/x86/Makefile index c1aa3688784..60087ca3767 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -184,11 +184,8 @@ archheaders: $(Q)$(MAKE) $(build)=arch/x86/syscalls all archprepare: -ifeq ($(CONFIG_KEXEC),y) -# Build only for 64bit. No loaders for 32bit yet. - ifeq ($(CONFIG_X86_64),y) +ifeq ($(CONFIG_KEXEC_FILE),y) $(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c - endif endif ### @@ -254,6 +251,7 @@ archclean: $(Q)rm -rf $(objtree)/arch/x86_64 $(Q)$(MAKE) $(clean)=$(boot) $(Q)$(MAKE) $(clean)=arch/x86/tools + $(Q)$(MAKE) $(clean)=arch/x86/purgatory PHONY += kvmconfig kvmconfig: diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 0aeed5ca356..478c490f365 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned extern void io_apic_eoi(unsigned int apic, unsigned int vector); +extern bool mp_should_keep_irq(struct device *dev); + #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 0ec05601261..aa97a070f09 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -131,8 +131,13 @@ static inline int pte_exec(pte_t pte) static inline int pte_special(pte_t pte) { - return (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_SPECIAL)) == - (_PAGE_PRESENT|_PAGE_SPECIAL); + /* + * See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h. + * On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 == + * __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL. + */ + return (pte_flags(pte) & _PAGE_SPECIAL) && + (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE)); } static inline unsigned long pte_pfn(pte_t pte) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index b5ea75c4a4b..ada2e2d6be3 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_X86_TSC) += trace_clock.o obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o +obj-$(CONFIG_KEXEC_FILE) += kexec-bzimage64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o obj-y += kprobes/ obj-$(CONFIG_MODULES) += module.o @@ -118,5 +119,4 @@ ifeq ($(CONFIG_X86_64),y) obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o obj-y += vsmp_64.o - obj-$(CONFIG_KEXEC) += kexec-bzimage64.o endif diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 29290f554e7..337ce5a9b15 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1070,6 +1070,11 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, } if (flags & IOAPIC_MAP_ALLOC) { + /* special handling for legacy IRQs */ + if (irq < nr_legacy_irqs() && info->count == 1 && + mp_irqdomain_map(domain, irq, pin) != 0) + irq = -1; + if (irq > 0) info->count++; else if (info->count == 0) @@ -3896,7 +3901,15 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq, info->polarity = 1; } info->node = NUMA_NO_NODE; - info->set = 1; + + /* + * setup_IO_APIC_irqs() programs all legacy IRQs with default + * trigger and polarity attributes. Don't set the flag for that + * case so the first legacy IRQ user could reprogram the pin + * with real trigger and polarity attributes. + */ + if (virq >= nr_legacy_irqs() || info->count) + info->set = 1; } set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger, info->polarity); @@ -3946,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node) return ret; } +bool mp_should_keep_irq(struct device *dev) +{ + if (dev->power.is_prepared) + return true; +#ifdef CONFIG_PM_RUNTIME + if (dev->power.runtime_status == RPM_SUSPENDING) + return true; +#endif + + return false; +} + /* Enable IOAPIC early just for system timer */ void __init pre_init_apic_IRQ0(void) { diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 0553a34fa0d..a618fcd2c07 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -182,8 +182,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs) crash_save_cpu(regs, safe_smp_processor_id()); } -#ifdef CONFIG_X86_64 - +#ifdef CONFIG_KEXEC_FILE static int get_nr_ram_ranges_callback(unsigned long start_pfn, unsigned long nr_pfn, void *arg) { @@ -696,5 +695,4 @@ int crash_load_segments(struct kimage *image) return ret; } - -#endif /* CONFIG_X86_64 */ +#endif /* CONFIG_KEXEC_FILE */ diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 1e6cff5814f..44f1ed42fdf 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -203,7 +203,7 @@ void __init native_init_IRQ(void) set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); } - if (!acpi_ioapic && !of_ioapic) + if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) setup_irq(2, &irq2); #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 8b04018e5d1..485981059a4 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -25,9 +25,11 @@ #include <asm/debugreg.h> #include <asm/kexec-bzimage64.h> +#ifdef CONFIG_KEXEC_FILE static struct kexec_file_ops *kexec_file_loaders[] = { &kexec_bzImage64_ops, }; +#endif static void free_transition_pgtable(struct kimage *image) { @@ -178,6 +180,7 @@ static void load_segments(void) ); } +#ifdef CONFIG_KEXEC_FILE /* Update purgatory as needed after various image segments have been prepared */ static int arch_update_purgatory(struct kimage *image) { @@ -209,6 +212,12 @@ static int arch_update_purgatory(struct kimage *image) return ret; } +#else /* !CONFIG_KEXEC_FILE */ +static inline int arch_update_purgatory(struct kimage *image) +{ + return 0; +} +#endif /* CONFIG_KEXEC_FILE */ int machine_kexec_prepare(struct kimage *image) { @@ -329,6 +338,7 @@ void arch_crash_save_vmcoreinfo(void) /* arch-dependent functionality related to kexec file-based syscall */ +#ifdef CONFIG_KEXEC_FILE int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, unsigned long buf_len) { @@ -522,3 +532,4 @@ overflow: (int)ELF64_R_TYPE(rel[i].r_info), value); return -ENOEXEC; } +#endif /* CONFIG_KEXEC_FILE */ diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index bf7ef5ce29d..0fa29609b2c 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c @@ -68,6 +68,8 @@ static struct irqaction irq0 = { void __init setup_default_timer_irq(void) { + if (!nr_legacy_irqs()) + return; setup_irq(0, &irq0); } diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 3865116c51f..b9958c36407 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c @@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) static void intel_mid_pci_irq_disable(struct pci_dev *dev) { - if (!dev->dev.power.is_prepared && dev->irq > 0) + if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0) mp_unmap_irq(dev->irq); } diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index bc1a2c34189..eb500c2592a 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev) static void pirq_disable_irq(struct pci_dev *dev) { - if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared && + if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && dev->irq) { mp_unmap_irq(dev->irq); dev->irq = 0; diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 7fde9ee438a..899dd245425 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -11,6 +11,7 @@ targets += purgatory.ro # sure how to relocate those. Like kexec-tools, use custom flags. KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large +KBUILD_CFLAGS += -m$(BITS) $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE $(call if_changed,ld) @@ -24,7 +25,4 @@ $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE $(call if_changed,bin2c) -# No loaders for 32bits yet. -ifeq ($(CONFIG_X86_64),y) - obj-$(CONFIG_KEXEC) += kexec-purgatory.o -endif +obj-$(CONFIG_KEXEC_FILE) += kexec-purgatory.o diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 3a617af60d4..49c6c3d9444 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -4,24 +4,23 @@ config ZONE_DMA config XTENSA def_bool y select ARCH_WANT_FRAME_POINTERS - select HAVE_IDE - select GENERIC_ATOMIC64 - select GENERIC_CLOCKEVENTS - select VIRT_TO_BUS - select GENERIC_IRQ_SHOW - select GENERIC_SCHED_CLOCK - select MODULES_USE_ELF_RELA - select GENERIC_PCI_IOMAP select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_OPTIONAL_GPIOLIB select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS - select IRQ_DOMAIN - select HAVE_OPROFILE + select COMMON_CLK + select GENERIC_ATOMIC64 + select GENERIC_CLOCKEVENTS + select GENERIC_IRQ_SHOW + select GENERIC_PCI_IOMAP + select GENERIC_SCHED_CLOCK select HAVE_FUNCTION_TRACER select HAVE_IRQ_TIME_ACCOUNTING + select HAVE_OPROFILE select HAVE_PERF_EVENTS - select COMMON_CLK + select IRQ_DOMAIN + select MODULES_USE_ELF_RELA + select VIRT_TO_BUS help Xtensa processors are 32-bit RISC machines designed by Tensilica primarily for embedded systems. These processors are both @@ -62,7 +61,9 @@ config TRACE_IRQFLAGS_SUPPORT def_bool y config MMU - def_bool n + bool + default n if !XTENSA_VARIANT_CUSTOM + default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM config VARIANT_IRQ_SWITCH def_bool n @@ -102,8 +103,40 @@ config XTENSA_VARIANT_S6000 select VARIANT_IRQ_SWITCH select ARCH_REQUIRE_GPIOLIB select XTENSA_CALIBRATE_CCOUNT + +config XTENSA_VARIANT_CUSTOM + bool "Custom Xtensa processor configuration" + select MAY_HAVE_SMP + select HAVE_XTENSA_GPIO32 + help + Select this variant to use a custom Xtensa processor configuration. + You will be prompted for a processor variant CORENAME. endchoice +config XTENSA_VARIANT_CUSTOM_NAME + string "Xtensa Processor Custom Core Variant Name" + depends on XTENSA_VARIANT_CUSTOM + help + Provide the name of a custom Xtensa processor variant. + This CORENAME selects arch/xtensa/variant/CORENAME. + Dont forget you have to select MMU if you have one. + +config XTENSA_VARIANT_NAME + string + default "dc232b" if XTENSA_VARIANT_DC232B + default "dc233c" if XTENSA_VARIANT_DC233C + default "fsf" if XTENSA_VARIANT_FSF + default "s6000" if XTENSA_VARIANT_S6000 + default XTENSA_VARIANT_CUSTOM_NAME if XTENSA_VARIANT_CUSTOM + +config XTENSA_VARIANT_MMU + bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)" + depends on XTENSA_VARIANT_CUSTOM + default y + help + Build a Conventional Kernel with full MMU support, + ie: it supports a TLB with auto-loading, page protection. + config XTENSA_UNALIGNED_USER bool "Unaligned memory access in use space" help @@ -156,13 +189,9 @@ config HOTPLUG_CPU Say N if you want to disable CPU hotplug. -config MATH_EMULATION - bool "Math emulation" - help - Can we use information of configuration file? - config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX bool "Initialize Xtensa MMU inside the Linux kernel code" + depends on MMU default y help Earlier version initialized the MMU in the exception vector @@ -192,6 +221,7 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX config HIGHMEM bool "High Memory Support" + depends on MMU help Linux can use the full amount of RAM in the system by default. However, the default MMUv2 setup only maps the @@ -208,6 +238,32 @@ config HIGHMEM If unsure, say Y. +config FAST_SYSCALL_XTENSA + bool "Enable fast atomic syscalls" + default n + help + fast_syscall_xtensa is a syscall that can make atomic operations + on UP kernel when processor has no s32c1i support. + + This syscall is deprecated. It may have issues when called with + invalid arguments. It is provided only for backwards compatibility. + Only enable it if your userspace software requires it. + + If unsure, say N. + +config FAST_SYSCALL_SPILL_REGISTERS + bool "Enable spill registers syscall" + default n + help + fast_syscall_spill_registers is a syscall that spills all active + register windows of a calling userspace task onto its stack. + + This syscall is deprecated. It may have issues when called with + invalid arguments. It is provided only for backwards compatibility. + Only enable it if your userspace software requires it. + + If unsure, say N. + endmenu config XTENSA_CALIBRATE_CCOUNT @@ -250,12 +306,14 @@ config XTENSA_PLATFORM_ISS config XTENSA_PLATFORM_XT2000 bool "XT2000" + select HAVE_IDE help XT2000 is the name of Tensilica's feature-rich emulation platform. This hardware is capable of running a full Linux distribution. config XTENSA_PLATFORM_S6105 bool "S6105" + select HAVE_IDE select SERIAL_CONSOLE select NO_IOPORT_MAP diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 81250ece306..472533064b4 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -4,6 +4,7 @@ # for more details. # # Copyright (C) 2001 - 2005 Tensilica Inc. +# Copyright (C) 2014 Cadence Design Systems Inc. # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions @@ -13,11 +14,7 @@ # Core configuration. # (Use VAR=<xtensa_config> to use another default compiler.) -variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf -variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b -variant-$(CONFIG_XTENSA_VARIANT_DC233C) := dc233c -variant-$(CONFIG_XTENSA_VARIANT_S6000) := s6000 -variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom +variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME)) VARIANT = $(variant-y) export VARIANT diff --git a/arch/xtensa/boot/dts/kc705.dts b/arch/xtensa/boot/dts/kc705.dts index 742a347be67..c4d17a34ab8 100644 --- a/arch/xtensa/boot/dts/kc705.dts +++ b/arch/xtensa/boot/dts/kc705.dts @@ -4,8 +4,11 @@ / { compatible = "cdns,xtensa-kc705"; + chosen { + bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000"; + }; memory@0 { device_type = "memory"; - reg = <0x00000000 0x08000000>; + reg = <0x00000000 0x38000000>; }; }; diff --git a/arch/xtensa/configs/common_defconfig b/arch/xtensa/configs/common_defconfig index f6000fe0511..721df1214bc 100644 --- a/arch/xtensa/configs/common_defconfig +++ b/arch/xtensa/configs/common_defconfig @@ -66,7 +66,6 @@ CONFIG_XTENSA_ARCH_LINUX_BE=y CONFIG_MMU=y # CONFIG_XTENSA_UNALIGNED_USER is not set # CONFIG_PREEMPT is not set -# CONFIG_MATH_EMULATION is not set # CONFIG_HIGHMEM is not set # diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig index 1493c68352d..b966baf82ca 100644 --- a/arch/xtensa/configs/iss_defconfig +++ b/arch/xtensa/configs/iss_defconfig @@ -146,7 +146,6 @@ CONFIG_XTENSA_VARIANT_FSF=y # CONFIG_XTENSA_VARIANT_S6000 is not set # CONFIG_XTENSA_UNALIGNED_USER is not set # CONFIG_PREEMPT is not set -# CONFIG_MATH_EMULATION is not set CONFIG_XTENSA_CALIBRATE_CCOUNT=y CONFIG_SERIAL_CONSOLE=y CONFIG_XTENSA_ISS_NETWORK=y @@ -308,7 +307,7 @@ CONFIG_MISC_DEVICES=y # EEPROM support # # CONFIG_EEPROM_93CX6 is not set -CONFIG_HAVE_IDE=y +# CONFIG_HAVE_IDE is not set # CONFIG_IDE is not set # diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig index 12a492ab6d1..9471265b8ca 100644 --- a/arch/xtensa/configs/s6105_defconfig +++ b/arch/xtensa/configs/s6105_defconfig @@ -109,7 +109,6 @@ CONFIG_VARIANT_IRQ_SWITCH=y CONFIG_XTENSA_VARIANT_S6000=y # CONFIG_XTENSA_UNALIGNED_USER is not set CONFIG_PREEMPT=y -# CONFIG_MATH_EMULATION is not set # CONFIG_HIGHMEM is not set CONFIG_XTENSA_CALIBRATE_CCOUNT=y CONFIG_SERIAL_CONSOLE=y diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index 555a98a1845..e72aaca7a77 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h @@ -37,6 +37,7 @@ * specials for cache aliasing: * * __flush_invalidate_dcache_page_alias(vaddr,paddr) + * __invalidate_dcache_page_alias(vaddr,paddr) * __invalidate_icache_page_alias(vaddr,paddr) */ @@ -62,6 +63,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long); #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE) extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long); +extern void __invalidate_dcache_page_alias(unsigned long, unsigned long); #else static inline void __flush_invalidate_dcache_page_alias(unsigned long virt, unsigned long phys) { } diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h index 9f6c33d0428..62b507deea9 100644 --- a/arch/xtensa/include/asm/fixmap.h +++ b/arch/xtensa/include/asm/fixmap.h @@ -23,8 +23,8 @@ * Here we define all the compile-time 'special' virtual * addresses. The point is to have a constant address at * compile time, but to set the physical address only - * in the boot process. We allocate these special addresses - * from the end of the consistent memory region backwards. + * in the boot process. We allocate these special addresses + * from the start of the consistent memory region upwards. * Also this lets us do fail-safe vmalloc(), we * can guarantee that these special addresses and * vmalloc()-ed addresses never overlap. @@ -38,7 +38,8 @@ enum fixed_addresses { #ifdef CONFIG_HIGHMEM /* reserved pte's for temporary kernel mappings */ FIX_KMAP_BEGIN, - FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, + FIX_KMAP_END = FIX_KMAP_BEGIN + + (KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1, #endif __end_of_fixed_addresses }; @@ -47,7 +48,28 @@ enum fixed_addresses { #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK) -#include <asm-generic/fixmap.h> +#define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) +#define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) + +#ifndef __ASSEMBLY__ +/* + * 'index to address' translation. If anyone tries to use the idx + * directly without translation, we catch the bug with a NULL-deference + * kernel oops. Illegal ranges of incoming indices are caught too. + */ +static __always_inline unsigned long fix_to_virt(const unsigned int idx) +{ + BUILD_BUG_ON(idx >= __end_of_fixed_addresses); + return __fix_to_virt(idx); +} + +static inline unsigned long virt_to_fix(const unsigned long vaddr) +{ + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); + return __virt_to_fix(vaddr); +} + +#endif #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel( \ diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h index 2653ef5d55f..2c7901edffa 100644 --- a/arch/xtensa/include/asm/highmem.h +++ b/arch/xtensa/include/asm/highmem.h @@ -12,19 +12,55 @@ #ifndef _XTENSA_HIGHMEM_H #define _XTENSA_HIGHMEM_H +#include <linux/wait.h> #include <asm/cacheflush.h> #include <asm/fixmap.h> #include <asm/kmap_types.h> #include <asm/pgtable.h> -#define PKMAP_BASE (FIXADDR_START - PMD_SIZE) -#define LAST_PKMAP PTRS_PER_PTE +#define PKMAP_BASE ((FIXADDR_START - \ + (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK) +#define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS) #define LAST_PKMAP_MASK (LAST_PKMAP - 1) #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) #define kmap_prot PAGE_KERNEL +#if DCACHE_WAY_SIZE > PAGE_SIZE +#define get_pkmap_color get_pkmap_color +static inline int get_pkmap_color(struct page *page) +{ + return DCACHE_ALIAS(page_to_phys(page)); +} + +extern unsigned int last_pkmap_nr_arr[]; + +static inline unsigned int get_next_pkmap_nr(unsigned int color) +{ + last_pkmap_nr_arr[color] = + (last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK; + return last_pkmap_nr_arr[color] + color; +} + +static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color) +{ + return pkmap_nr < DCACHE_N_COLORS; +} + +static inline int get_pkmap_entries_count(unsigned int color) +{ + return LAST_PKMAP / DCACHE_N_COLORS; +} + +extern wait_queue_head_t pkmap_map_wait_arr[]; + +static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color) +{ + return pkmap_map_wait_arr + color; +} +#endif + extern pte_t *pkmap_page_table; void *kmap_high(struct page *page); diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 47f582333f6..abe24c6f8b2 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h @@ -78,7 +78,9 @@ # define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0) #else # define DCACHE_ALIAS_ORDER 0 +# define DCACHE_ALIAS(a) ((void)(a), 0) #endif +#define DCACHE_N_COLORS (1 << DCACHE_ALIAS_ORDER) #if ICACHE_WAY_SIZE > PAGE_SIZE # define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT) @@ -134,6 +136,7 @@ static inline __attribute_const__ int get_order(unsigned long size) #endif struct page; +struct vm_area_struct; extern void clear_page(void *page); extern void copy_page(void *to, void *from); @@ -143,8 +146,15 @@ extern void copy_page(void *to, void *from); */ #if DCACHE_WAY_SIZE > PAGE_SIZE -extern void clear_user_page(void*, unsigned long, struct page*); -extern void copy_user_page(void*, void*, unsigned long, struct page*); +extern void clear_page_alias(void *vaddr, unsigned long paddr); +extern void copy_page_alias(void *to, void *from, + unsigned long to_paddr, unsigned long from_paddr); + +#define clear_user_highpage clear_user_highpage +void clear_user_highpage(struct page *page, unsigned long vaddr); +#define __HAVE_ARCH_COPY_USER_HIGHPAGE +void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); #else # define clear_user_page(page, vaddr, pg) clear_page(page) # define copy_user_page(to, from, vaddr, pg) copy_page(to, from) diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 4b0ca35a93b..b2173e5da60 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -67,7 +67,12 @@ #define VMALLOC_START 0xC0000000 #define VMALLOC_END 0xC7FEFFFF #define TLBTEMP_BASE_1 0xC7FF0000 -#define TLBTEMP_BASE_2 0xC7FF8000 +#define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE) +#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE +#define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE) +#else +#define TLBTEMP_SIZE ICACHE_WAY_SIZE +#endif /* * For the Xtensa architecture, the PTE layout is as follows: diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index fd686dc45d1..c7211e7e182 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -52,7 +52,12 @@ */ .macro get_fs ad, sp GET_CURRENT(\ad,\sp) +#if THREAD_CURRENT_DS > 1020 + addi \ad, \ad, TASK_THREAD + l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD +#else l32i \ad, \ad, THREAD_CURRENT_DS +#endif .endm /* diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index b4cb1100c0f..a47909f0c34 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -28,17 +28,17 @@ #define TCSETSW 0x5403 #define TCSETSF 0x5404 -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) +#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */ +#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */ +#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */ +#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */ #define TCSBRK _IO('t', 29) #define TCXONC _IO('t', 30) #define TCFLSH _IO('t', 31) -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */ +#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */ #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ #define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ #define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ @@ -88,7 +88,6 @@ #define TIOCSETD _IOW('T', 35, int) #define TIOCGETD _IOR('T', 36, int) #define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/ -#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/ #define TIOCSBRK _IO('T', 39) /* BSD compatibility */ #define TIOCCBRK _IO('T', 40) /* BSD compatibility */ #define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/ @@ -114,8 +113,10 @@ #define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ # define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ -#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */ -#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */ +#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */ + /* _IOR('T', 90, struct serial_multiport_struct) */ +#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */ + /* _IOW('T', 91, struct serial_multiport_struct) */ #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index b9395529f02..8883fc877c5 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -739,7 +739,10 @@ __SYSCALL(334, sys_sched_setattr, 2) #define __NR_sched_getattr 335 __SYSCALL(335, sys_sched_getattr, 3) -#define __NR_syscall_count 336 +#define __NR_renameat2 336 +__SYSCALL(336, sys_renameat2, 5) + +#define __NR_syscall_count 337 /* * sysxtensa syscall handler diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S index d4cef6039a5..890004af03a 100644 --- a/arch/xtensa/kernel/align.S +++ b/arch/xtensa/kernel/align.S @@ -8,6 +8,7 @@ * this archive for more details. * * Copyright (C) 2001 - 2005 Tensilica, Inc. + * Copyright (C) 2014 Cadence Design Systems Inc. * * Rewritten by Chris Zankel <chris@zankel.net> * @@ -174,6 +175,10 @@ ENTRY(fast_unaligned) s32i a0, a2, PT_AREG2 s32i a3, a2, PT_AREG3 + rsr a3, excsave1 + movi a4, fast_unaligned_fixup + s32i a4, a3, EXC_TABLE_FIXUP + /* Keep value of SAR in a0 */ rsr a0, sar @@ -225,10 +230,6 @@ ENTRY(fast_unaligned) addx8 a5, a6, a5 jx a5 # jump into table - /* Invalid instruction, CRITICAL! */ -.Linvalid_instruction_load: - j .Linvalid_instruction - /* Load: Load memory address. */ .Lload: movi a3, ~3 @@ -272,18 +273,6 @@ ENTRY(fast_unaligned) /* Set target register. */ 1: - -#if XCHAL_HAVE_LOOPS - rsr a5, lend # check if we reached LEND - bne a7, a5, 1f - rsr a5, lcount # and LCOUNT != 0 - beqz a5, 1f - addi a5, a5, -1 # decrement LCOUNT and set - rsr a7, lbeg # set PC to LBEGIN - wsr a5, lcount -#endif - -1: wsr a7, epc1 # skip load instruction extui a4, a4, INSN_T, 4 # extract target register movi a5, .Lload_table addx8 a4, a4, a5 @@ -326,6 +315,35 @@ ENTRY(fast_unaligned) mov a3, a14 ; _j 1f; .align 8 mov a3, a15 ; _j 1f; .align 8 + /* We cannot handle this exception. */ + + .extern _kernel_exception +.Linvalid_instruction_load: +.Linvalid_instruction_store: + + movi a4, 0 + rsr a3, excsave1 + s32i a4, a3, EXC_TABLE_FIXUP + + /* Restore a4...a8 and SAR, set SP, and jump to default exception. */ + + l32i a8, a2, PT_AREG8 + l32i a7, a2, PT_AREG7 + l32i a6, a2, PT_AREG6 + l32i a5, a2, PT_AREG5 + l32i a4, a2, PT_AREG4 + wsr a0, sar + mov a1, a2 + + rsr a0, ps + bbsi.l a0, PS_UM_BIT, 2f # jump if user mode + + movi a0, _kernel_exception + jx a0 + +2: movi a0, _user_exception + jx a0 + 1: # a7: instruction pointer, a4: instruction, a3: value movi a6, 0 # mask: ffffffff:00000000 @@ -353,17 +371,6 @@ ENTRY(fast_unaligned) /* Get memory address */ 1: -#if XCHAL_HAVE_LOOPS - rsr a4, lend # check if we reached LEND - bne a7, a4, 1f - rsr a4, lcount # and LCOUNT != 0 - beqz a4, 1f - addi a4, a4, -1 # decrement LCOUNT and set - rsr a7, lbeg # set PC to LBEGIN - wsr a4, lcount -#endif - -1: wsr a7, epc1 # skip store instruction movi a4, ~3 and a4, a4, a8 # align memory address @@ -375,25 +382,25 @@ ENTRY(fast_unaligned) #endif __ssa8r a8 - __src_b a7, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE) + __src_b a8, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE) __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE) #ifdef UNALIGNED_USER_EXCEPTION l32e a5, a4, -8 #else l32i a5, a4, 0 # load lower address word #endif - and a5, a5, a7 # mask - __sh a7, a3 # shift value - or a5, a5, a7 # or with original value + and a5, a5, a8 # mask + __sh a8, a3 # shift value + or a5, a5, a8 # or with original value #ifdef UNALIGNED_USER_EXCEPTION s32e a5, a4, -8 - l32e a7, a4, -4 + l32e a8, a4, -4 #else s32i a5, a4, 0 # store - l32i a7, a4, 4 # same for upper address word + l32i a8, a4, 4 # same for upper address word #endif __sl a5, a3 - and a6, a7, a6 + and a6, a8, a6 or a6, a6, a5 #ifdef UNALIGNED_USER_EXCEPTION s32e a6, a4, -4 @@ -401,9 +408,27 @@ ENTRY(fast_unaligned) s32i a6, a4, 4 #endif - /* Done. restore stack and return */ - .Lexit: +#if XCHAL_HAVE_LOOPS + rsr a4, lend # check if we reached LEND + bne a7, a4, 1f + rsr a4, lcount # and LCOUNT != 0 + beqz a4, 1f + addi a4, a4, -1 # decrement LCOUNT and set + rsr a7, lbeg # set PC to LBEGIN + wsr a4, lcount +#endif + +1: wsr a7, epc1 # skip emulated instruction + + /* Update icount if we're single-stepping in userspace. */ + rsr a4, icountlevel + beqz a4, 1f + bgeui a4, LOCKLEVEL + 1, 1f + rsr a4, icount + addi a4, a4, 1 + wsr a4, icount +1: movi a4, 0 rsr a3, excsave1 s32i a4, a3, EXC_TABLE_FIXUP @@ -424,31 +449,40 @@ ENTRY(fast_unaligned) l32i a2, a2, PT_AREG2 rfe - /* We cannot handle this exception. */ +ENDPROC(fast_unaligned) - .extern _kernel_exception -.Linvalid_instruction_store: -.Linvalid_instruction: +ENTRY(fast_unaligned_fixup) - /* Restore a4...a8 and SAR, set SP, and jump to default exception. */ + l32i a2, a3, EXC_TABLE_DOUBLE_SAVE + wsr a3, excsave1 l32i a8, a2, PT_AREG8 l32i a7, a2, PT_AREG7 l32i a6, a2, PT_AREG6 l32i a5, a2, PT_AREG5 l32i a4, a2, PT_AREG4 + l32i a0, a2, PT_AREG2 + xsr a0, depc # restore depc and a0 wsr a0, sar - mov a1, a2 + + rsr a0, exccause + s32i a0, a2, PT_DEPC # mark as a regular exception rsr a0, ps - bbsi.l a2, PS_UM_BIT, 1f # jump if user mode + bbsi.l a0, PS_UM_BIT, 1f # jump if user mode - movi a0, _kernel_exception + rsr a0, exccause + addx4 a0, a0, a3 # find entry in table + l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler + l32i a3, a2, PT_AREG3 jx a0 - -1: movi a0, _user_exception +1: + rsr a0, exccause + addx4 a0, a0, a3 # find entry in table + l32i a0, a0, EXC_TABLE_FAST_USER # load handler + l32i a3, a2, PT_AREG3 jx a0 -ENDPROC(fast_unaligned) +ENDPROC(fast_unaligned_fixup) #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index ef7f4990722..82bbfa5a05b 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -986,6 +986,8 @@ ENDPROC(fast_syscall_unrecoverable) * j done */ +#ifdef CONFIG_FAST_SYSCALL_XTENSA + #define TRY \ .section __ex_table, "a"; \ .word 66f, 67f; \ @@ -1001,9 +1003,8 @@ ENTRY(fast_syscall_xtensa) movi a7, 4 # sizeof(unsigned int) access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp - addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1 - _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill - _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp + _bgeui a6, SYS_XTENSA_COUNT, .Lill + _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp /* Fall through for ATOMIC_CMP_SWP. */ @@ -1015,27 +1016,26 @@ TRY s32i a5, a3, 0 # different, modify value l32i a7, a2, PT_AREG7 # restore a7 l32i a0, a2, PT_AREG0 # restore a0 movi a2, 1 # and return 1 - addi a6, a6, 1 # restore a6 (really necessary?) rfe 1: l32i a7, a2, PT_AREG7 # restore a7 l32i a0, a2, PT_AREG0 # restore a0 movi a2, 0 # return 0 (note that we cannot set - addi a6, a6, 1 # restore a6 (really necessary?) rfe .Lnswp: /* Atomic set, add, and exg_add. */ TRY l32i a7, a3, 0 # orig + addi a6, a6, -SYS_XTENSA_ATOMIC_SET add a0, a4, a7 # + arg moveqz a0, a4, a6 # set + addi a6, a6, SYS_XTENSA_ATOMIC_SET TRY s32i a0, a3, 0 # write new value mov a0, a2 mov a2, a7 l32i a7, a0, PT_AREG7 # restore a7 l32i a0, a0, PT_AREG0 # restore a0 - addi a6, a6, 1 # restore a6 (really necessary?) rfe CATCH @@ -1044,13 +1044,25 @@ CATCH movi a2, -EFAULT rfe -.Lill: l32i a7, a2, PT_AREG0 # restore a7 +.Lill: l32i a7, a2, PT_AREG7 # restore a7 l32i a0, a2, PT_AREG0 # restore a0 movi a2, -EINVAL rfe ENDPROC(fast_syscall_xtensa) +#else /* CONFIG_FAST_SYSCALL_XTENSA */ + +ENTRY(fast_syscall_xtensa) + + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, -ENOSYS + rfe + +ENDPROC(fast_syscall_xtensa) + +#endif /* CONFIG_FAST_SYSCALL_XTENSA */ + /* fast_syscall_spill_registers. * @@ -1066,6 +1078,8 @@ ENDPROC(fast_syscall_xtensa) * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. */ +#ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS + ENTRY(fast_syscall_spill_registers) /* Register a FIXUP handler (pass current wb as a parameter) */ @@ -1400,6 +1414,18 @@ ENTRY(fast_syscall_spill_registers_fixup_return) ENDPROC(fast_syscall_spill_registers_fixup_return) +#else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */ + +ENTRY(fast_syscall_spill_registers) + + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, -ENOSYS + rfe + +ENDPROC(fast_syscall_spill_registers) + +#endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */ + #ifdef CONFIG_MMU /* * We should never get here. Bail out! @@ -1565,7 +1591,7 @@ ENTRY(fast_second_level_miss) rsr a0, excvaddr bltu a0, a3, 2f - addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) + addi a1, a0, -TLBTEMP_SIZE bgeu a1, a3, 2f /* Check if we have to restore an ITLB mapping. */ @@ -1820,7 +1846,6 @@ ENTRY(_switch_to) entry a1, 16 - mov a10, a2 # preserve 'prev' (a2) mov a11, a3 # and 'next' (a3) l32i a4, a2, TASK_THREAD_INFO @@ -1828,8 +1853,14 @@ ENTRY(_switch_to) save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER - s32i a0, a10, THREAD_RA # save return address - s32i a1, a10, THREAD_SP # save stack pointer +#if THREAD_RA > 1020 || THREAD_SP > 1020 + addi a10, a2, TASK_THREAD + s32i a0, a10, THREAD_RA - TASK_THREAD # save return address + s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer +#else + s32i a0, a2, THREAD_RA # save return address + s32i a1, a2, THREAD_SP # save stack pointer +#endif /* Disable ints while we manipulate the stack pointer. */ @@ -1870,7 +1901,6 @@ ENTRY(_switch_to) load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER wsr a14, ps - mov a2, a10 # return 'prev' rsync retw diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index 2d9cc6dbfd7..e8b76b8e4b2 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c @@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) /* We currently don't support coherent memory outside KSEG */ - if (ret < XCHAL_KSEG_CACHED_VADDR - || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) - BUG(); + BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || + ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); if (ret != 0) { @@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent); void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; + unsigned long addr = (unsigned long)vaddr + + XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; - if (addr < 0 || addr >= XCHAL_KSEG_SIZE) - BUG(); + BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || + addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); free_pages(addr, get_order(size)); } diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index 40b5a3771fb..4d02e38514f 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c @@ -571,6 +571,7 @@ void flush_icache_range(unsigned long start, unsigned long end) }; on_each_cpu(ipi_flush_icache_range, &fd, 1); } +EXPORT_SYMBOL(flush_icache_range); /* ------------------------------------------------------------------------- */ diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index eebbfd8c26f..9d2f45f010e 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION #ifdef CONFIG_XTENSA_UNALIGNED_USER { EXCCAUSE_UNALIGNED, USER, fast_unaligned }, -#else -{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, #endif +{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, { EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, #endif #ifdef CONFIG_MMU @@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *regs) */ #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION -#ifndef CONFIG_XTENSA_UNALIGNED_USER void do_unaligned_user (struct pt_regs *regs) { @@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs) } #endif -#endif void do_debug(struct pt_regs *regs) diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index 8453e6e3989..1b397a90229 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S @@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow: s32i a0, a2, PT_DEPC _DoubleExceptionVector_handle_exception: + addi a0, a0, -EXCCAUSE_UNALIGNED + beqz a0, 2f addx4 a0, a0, a3 - l32i a0, a0, EXC_TABLE_FAST_USER + l32i a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED + xsr a3, excsave1 + jx a0 +2: + movi a0, user_exception xsr a3, excsave1 jx a0 diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index d16db6df86f..fc1bc2ba8d5 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -269,13 +269,13 @@ SECTIONS .UserExceptionVector.literal) SECTION_VECTOR (_DoubleExceptionVector_literal, .DoubleExceptionVector.literal, - DOUBLEEXC_VECTOR_VADDR - 40, + DOUBLEEXC_VECTOR_VADDR - 48, SIZEOF(.UserExceptionVector.text), .UserExceptionVector.text) SECTION_VECTOR (_DoubleExceptionVector_text, .DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR, - 40, + 48, .DoubleExceptionVector.literal) . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 63cbb867dad..d75aa1476da 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c @@ -59,9 +59,68 @@ * */ -#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM) -#error "HIGHMEM is not supported on cores with aliasing cache." -#endif +#if (DCACHE_WAY_SIZE > PAGE_SIZE) +static inline void kmap_invalidate_coherent(struct page *page, + unsigned long vaddr) +{ + if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { + unsigned long kvaddr; + + if (!PageHighMem(page)) { + kvaddr = (unsigned long)page_to_virt(page); + + __invalidate_dcache_page(kvaddr); + } else { + kvaddr = TLBTEMP_BASE_1 + + (page_to_phys(page) & DCACHE_ALIAS_MASK); + + __invalidate_dcache_page_alias(kvaddr, + page_to_phys(page)); + } + } +} + +static inline void *coherent_kvaddr(struct page *page, unsigned long base, + unsigned long vaddr, unsigned long *paddr) +{ + if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { + *paddr = page_to_phys(page); + return (void *)(base + (vaddr & DCACHE_ALIAS_MASK)); + } else { + *paddr = 0; + return page_to_virt(page); + } +} + +void clear_user_highpage(struct page *page, unsigned long vaddr) +{ + unsigned long paddr; + void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr); + + pagefault_disable(); + kmap_invalidate_coherent(page, vaddr); + set_bit(PG_arch_1, &page->flags); + clear_page_alias(kvaddr, paddr); + pagefault_enable(); +} + +void copy_user_highpage(struct page *dst, struct page *src, + unsigned long vaddr, struct vm_area_struct *vma) +{ + unsigned long dst_paddr, src_paddr; + void *dst_vaddr = coherent_kvaddr(dst, TLBTEMP_BASE_1, vaddr, + &dst_paddr); + void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr, + &src_paddr); + + pagefault_disable(); + kmap_invalidate_coherent(dst, vaddr); + set_bit(PG_arch_1, &dst->flags); + copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr); + pagefault_enable(); +} + +#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */ #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK @@ -103,7 +162,8 @@ void flush_dcache_page(struct page *page) if (!alias && !mapping) return; - __flush_invalidate_dcache_page((long)page_address(page)); + virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); + __flush_invalidate_dcache_page_alias(virt, phys); virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK); @@ -168,13 +228,12 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) { - - unsigned long paddr = (unsigned long) page_address(page); unsigned long phys = page_to_phys(page); - unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); - - __flush_invalidate_dcache_page(paddr); + unsigned long tmp; + tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); + __flush_invalidate_dcache_page_alias(tmp, phys); + tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); __flush_invalidate_dcache_page_alias(tmp, phys); __invalidate_icache_page_alias(tmp, phys); diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c index 17a8c0d6fd1..8cfb71ec093 100644 --- a/arch/xtensa/mm/highmem.c +++ b/arch/xtensa/mm/highmem.c @@ -14,23 +14,45 @@ static pte_t *kmap_pte; +#if DCACHE_WAY_SIZE > PAGE_SIZE +unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; +wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS]; + +static void __init kmap_waitqueues_init(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i) + init_waitqueue_head(pkmap_map_wait_arr + i); +} +#else +static inline void kmap_waitqueues_init(void) +{ +} +#endif + +static inline enum fixed_addresses kmap_idx(int type, unsigned long color) +{ + return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS + + color; +} + void *kmap_atomic(struct page *page) { enum fixed_addresses idx; unsigned long vaddr; - int type; pagefault_disable(); if (!PageHighMem(page)) return page_address(page); - type = kmap_atomic_idx_push(); - idx = type + KM_TYPE_NR * smp_processor_id(); + idx = kmap_idx(kmap_atomic_idx_push(), + DCACHE_ALIAS(page_to_phys(page))); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); #ifdef CONFIG_DEBUG_HIGHMEM - BUG_ON(!pte_none(*(kmap_pte - idx))); + BUG_ON(!pte_none(*(kmap_pte + idx))); #endif - set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC)); + set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC)); return (void *)vaddr; } @@ -38,12 +60,10 @@ EXPORT_SYMBOL(kmap_atomic); void __kunmap_atomic(void *kvaddr) { - int idx, type; - if (kvaddr >= (void *)FIXADDR_START && kvaddr < (void *)FIXADDR_TOP) { - type = kmap_atomic_idx(); - idx = type + KM_TYPE_NR * smp_processor_id(); + int idx = kmap_idx(kmap_atomic_idx(), + DCACHE_ALIAS((unsigned long)kvaddr)); /* * Force other mappings to Oops if they'll try to access this @@ -51,7 +71,7 @@ void __kunmap_atomic(void *kvaddr) * is a bad idea also, in case the page changes cacheability * attributes or becomes a protected page in a hypervisor. */ - pte_clear(&init_mm, kvaddr, kmap_pte - idx); + pte_clear(&init_mm, kvaddr, kmap_pte + idx); local_flush_tlb_kernel_range((unsigned long)kvaddr, (unsigned long)kvaddr + PAGE_SIZE); @@ -69,4 +89,5 @@ void __init kmap_init(void) /* cache the first kmap pte */ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); kmap_pte = kmap_get_fixmap_pte(kmap_vstart); + kmap_waitqueues_init(); } diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index 1f68558dbcc..11a01c3e9ce 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S @@ -110,41 +110,24 @@ ENTRY(__tlbtemp_mapping_start) #if (DCACHE_WAY_SIZE > PAGE_SIZE) /* - * clear_user_page (void *addr, unsigned long vaddr, struct page *page) - * a2 a3 a4 + * clear_page_alias(void *addr, unsigned long paddr) + * a2 a3 */ -ENTRY(clear_user_page) +ENTRY(clear_page_alias) entry a1, 32 - /* Mark page dirty and determine alias. */ + /* Skip setting up a temporary DTLB if not aliased low page. */ - movi a7, (1 << PG_ARCH_1) - l32i a5, a4, PAGE_FLAGS - xor a6, a2, a3 - extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER - extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER - or a5, a5, a7 - slli a3, a3, PAGE_SHIFT - s32i a5, a4, PAGE_FLAGS + movi a5, PAGE_OFFSET + movi a6, 0 + beqz a3, 1f - /* Skip setting up a temporary DTLB if not aliased. */ - - beqz a6, 1f - - /* Invalidate kernel page. */ - - mov a10, a2 - call8 __invalidate_dcache_page - - /* Setup a temporary DTLB with the color of the VPN */ - - movi a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff - movi a5, TLBTEMP_BASE_1 # virt - add a6, a2, a4 # ppn - add a2, a5, a3 # add 'color' + /* Setup a temporary DTLB for the addr. */ + addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) + mov a4, a2 wdtlb a6, a2 dsync @@ -165,62 +148,43 @@ ENTRY(clear_user_page) /* We need to invalidate the temporary idtlb entry, if any. */ -1: addi a2, a2, -PAGE_SIZE - idtlb a2 +1: idtlb a4 dsync retw -ENDPROC(clear_user_page) +ENDPROC(clear_page_alias) /* - * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page) - * a2 a3 a4 a5 + * copy_page_alias(void *to, void *from, + * a2 a3 + * unsigned long to_paddr, unsigned long from_paddr) + * a4 a5 */ -ENTRY(copy_user_page) +ENTRY(copy_page_alias) entry a1, 32 - /* Mark page dirty and determine alias for destination. */ - - movi a8, (1 << PG_ARCH_1) - l32i a9, a5, PAGE_FLAGS - xor a6, a2, a4 - xor a7, a3, a4 - extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER - extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER - extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER - or a9, a9, a8 - slli a4, a4, PAGE_SHIFT - s32i a9, a5, PAGE_FLAGS - movi a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff - - beqz a6, 1f - - /* Invalidate dcache */ - - mov a10, a2 - call8 __invalidate_dcache_page + /* Skip setting up a temporary DTLB for destination if not aliased. */ - /* Setup a temporary DTLB with a matching color. */ + movi a6, 0 + movi a7, 0 + beqz a4, 1f - movi a8, TLBTEMP_BASE_1 # base - add a6, a2, a5 # ppn - add a2, a8, a4 # add 'color' + /* Setup a temporary DTLB for destination. */ + addi a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE) wdtlb a6, a2 dsync - /* Skip setting up a temporary DTLB for destination if not aliased. */ + /* Skip setting up a temporary DTLB for source if not aliased. */ -1: beqz a7, 1f +1: beqz a5, 1f - /* Setup a temporary DTLB with a matching color. */ + /* Setup a temporary DTLB for source. */ - movi a8, TLBTEMP_BASE_2 # base - add a7, a3, a5 # ppn - add a3, a8, a4 + addi a7, a5, PAGE_KERNEL addi a8, a3, 1 # way1 wdtlb a7, a8 @@ -271,7 +235,7 @@ ENTRY(copy_user_page) retw -ENDPROC(copy_user_page) +ENDPROC(copy_page_alias) #endif @@ -300,6 +264,30 @@ ENTRY(__flush_invalidate_dcache_page_alias) retw ENDPROC(__flush_invalidate_dcache_page_alias) + +/* + * void __invalidate_dcache_page_alias (addr, phys) + * a2 a3 + */ + +ENTRY(__invalidate_dcache_page_alias) + + entry sp, 16 + + movi a7, 0 # required for exception handler + addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) + mov a4, a2 + wdtlb a6, a2 + dsync + + ___invalidate_dcache_page a2 a3 + + idtlb a4 + dsync + + retw + +ENDPROC(__invalidate_dcache_page_alias) #endif ENTRY(__tlbtemp_mapping_itlb) diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 3429b483d9f..abe4513eb0d 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c @@ -18,32 +18,38 @@ #include <asm/io.h> #if defined(CONFIG_HIGHMEM) -static void * __init init_pmd(unsigned long vaddr) +static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages) { pgd_t *pgd = pgd_offset_k(vaddr); pmd_t *pmd = pmd_offset(pgd, vaddr); + pte_t *pte; + unsigned long i; - if (pmd_none(*pmd)) { - unsigned i; - pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE); + n_pages = ALIGN(n_pages, PTRS_PER_PTE); - for (i = 0; i < 1024; i++) - pte_clear(NULL, 0, pte + i); + pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n", + __func__, vaddr, n_pages); - set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK)); - BUG_ON(pte != pte_offset_kernel(pmd, 0)); - pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n", - __func__, vaddr, pmd, pte); - return pte; - } else { - return pte_offset_kernel(pmd, 0); + pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t)); + + for (i = 0; i < n_pages; ++i) + pte_clear(NULL, 0, pte + i); + + for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) { + pte_t *cur_pte = pte + i; + + BUG_ON(!pmd_none(*pmd)); + set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK)); + BUG_ON(cur_pte != pte_offset_kernel(pmd, 0)); + pr_debug("%s: pmd: 0x%p, pte: 0x%p\n", + __func__, pmd, cur_pte); } + return pte; } static void __init fixedrange_init(void) { - BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE); - init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK); + init_pmd(__fix_to_virt(0), __end_of_fixed_addresses); } #endif @@ -52,7 +58,7 @@ void __init paging_init(void) memset(swapper_pg_dir, 0, PAGE_SIZE); #ifdef CONFIG_HIGHMEM fixedrange_init(); - pkmap_page_table = init_pmd(PKMAP_BASE); + pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP); kmap_init(); #endif } |