diff options
Diffstat (limited to 'arch')
65 files changed, 975 insertions, 673 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 19483aea4bbc..99839c23d453 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -5,6 +5,9 @@ config KEXEC_CORE bool +config HAVE_IMA_KEXEC + bool + config OPROFILE tristate "OProfile system profiling" depends on PROFILING diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index b71086d25195..bfe632808d77 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -165,6 +165,11 @@ extern u64 kimage_vaddr; /* the offset between the kernel virtual and physical mappings */ extern u64 kimage_voffset; +static inline unsigned long kaslr_offset(void) +{ + return kimage_vaddr - KIMAGE_VADDR; +} + /* * Allow all memory at the discovery stage. We will clip it later. */ diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h index 600887e491fd..bf466d1876e3 100644 --- a/arch/arm64/include/asm/numa.h +++ b/arch/arm64/include/asm/numa.h @@ -15,6 +15,8 @@ int __node_distance(int from, int to); extern nodemask_t numa_nodes_parsed __initdata; +extern bool numa_off; + /* Mappings between node number and cpus on that node. */ extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; void numa_clear_node(unsigned int cpu); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index a53f52ac81c6..b051367e2149 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -338,11 +338,11 @@ subsys_initcall(topology_init); static int dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) { - u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR; + const unsigned long offset = kaslr_offset(); - if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) { - pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n", - kaslr_offset, KIMAGE_VADDR); + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0) { + pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n", + offset, KIMAGE_VADDR); } else { pr_emerg("Kernel Offset: disabled\n"); } diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 4b32168cf91a..b388a99fea7b 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -35,7 +35,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE }; static int numa_distance_cnt; static u8 *numa_distance; -static bool numa_off; +bool numa_off; static __init int numa_parse_early_param(char *opt) { diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h index 2db0a6c6daa5..ebef7f40aabb 100644 --- a/arch/ia64/include/asm/numa.h +++ b/arch/ia64/include/asm/numa.h @@ -65,6 +65,8 @@ extern int paddr_to_nid(unsigned long paddr); #define local_nodeid (cpu_to_node_map[smp_processor_id()]) +#define numa_off 0 + extern void map_cpu_to_node(int cpu, int nid); extern void unmap_cpu_from_node(int cpu, int nid); extern void numa_clear_node(int cpu); diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 805ae5d712e8..032fed71223f 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -38,6 +38,6 @@ #endif /* __ASSEMBLY__ */ -#define __NR_syscalls 392 +#define __NR_syscalls 398 #endif /* _ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h index a8bd3fa28bc7..d8086159d996 100644 --- a/arch/microblaze/include/uapi/asm/unistd.h +++ b/arch/microblaze/include/uapi/asm/unistd.h @@ -407,5 +407,11 @@ #define __NR_userfaultfd 389 #define __NR_membarrier 390 #define __NR_mlock2 391 +#define __NR_copy_file_range 392 +#define __NR_preadv2 393 +#define __NR_pwritev2 394 +#define __NR_pkey_mprotect 395 +#define __NR_pkey_alloc 396 +#define __NR_pkey_free 397 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index b70bb538f001..96b3f26d16be 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -49,6 +49,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"9.3", 0x20}, {"9.4", 0x21}, {"9.5", 0x22}, + {"9.6", 0x23}, + {"10.0", 0x24}, {NULL, 0}, }; @@ -75,6 +77,10 @@ const struct family_string_key family_string_lookup[] = { {"zynq7000", 0x12}, {"UltraScale Virtex", 0x13}, {"UltraScale Kintex", 0x14}, + {"UltraScale+ Zynq", 0x15}, + {"UltraScale+ Virtex", 0x16}, + {"UltraScale+ Kintex", 0x17}, + {"Spartan7", 0x18}, {NULL, 0}, }; diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 6b3dd99126d7..6841c2df14d9 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -392,3 +392,9 @@ ENTRY(sys_call_table) .long sys_userfaultfd .long sys_membarrier /* 390 */ .long sys_mlock2 + .long sys_copy_file_range + .long sys_preadv2 + .long sys_pwritev2 + .long sys_pkey_mprotect /* 395 */ + .long sys_pkey_alloc + .long sys_pkey_free diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 5bbf38b916ef..9e954959f605 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -259,7 +259,7 @@ static int __init xilinx_timer_init(struct device_node *timer) int ret; if (initialized) - return; + return -EINVAL; initialized = 1; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index f6ae6ed9c4b1..3e1587f1f77a 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -44,6 +44,17 @@ #clock-cells = <1>; }; + rtc_dev: rtc@10003000 { + compatible = "ingenic,jz4740-rtc"; + reg = <0x10003000 0x40>; + + interrupt-parent = <&intc>; + interrupts = <15>; + + clocks = <&cgu JZ4740_CLK_RTC>; + clock-names = "rtc"; + }; + uart0: serial@10030000 { compatible = "ingenic,jz4740-uart"; reg = <0x10030000 0x100>; diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts index 2414d63ae818..be1a7d3a3e1b 100644 --- a/arch/mips/boot/dts/ingenic/qi_lb60.dts +++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts @@ -13,3 +13,7 @@ &ext { clock-frequency = <12000000>; }; + +&rtc_dev { + system-power-controller; +}; diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 073b8bfbb3b3..3645974b7f65 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -22,7 +22,6 @@ extern struct platform_device jz4740_udc_device; extern struct platform_device jz4740_udc_xceiv_device; extern struct platform_device jz4740_mmc_device; -extern struct platform_device jz4740_rtc_device; extern struct platform_device jz4740_i2c_device; extern struct platform_device jz4740_nand_device; extern struct platform_device jz4740_framebuffer_device; diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 258fd03c9ef5..a5bd94b95263 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -438,7 +438,6 @@ static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_pcm_device, &jz4740_i2s_device, &jz4740_codec_device, - &jz4740_rtc_device, &jz4740_adc_device, &jz4740_pwm_device, &jz4740_dma_device, diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 2f1dab35c061..5b7cdd67a9d9 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -88,27 +88,6 @@ struct platform_device jz4740_mmc_device = { .resource = jz4740_mmc_resources, }; -/* RTC controller */ -static struct resource jz4740_rtc_resources[] = { - { - .start = JZ4740_RTC_BASE_ADDR, - .end = JZ4740_RTC_BASE_ADDR + 0x38 - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = JZ4740_IRQ_RTC, - .end = JZ4740_IRQ_RTC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device jz4740_rtc_device = { - .name = "jz4740-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(jz4740_rtc_resources), - .resource = jz4740_rtc_resources, -}; - /* I2C controller */ static struct resource jz4740_i2c_resources[] = { { diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c index 954e669c9e6b..67780c4b6573 100644 --- a/arch/mips/jz4740/reset.c +++ b/arch/mips/jz4740/reset.c @@ -57,71 +57,8 @@ static void jz4740_restart(char *command) jz4740_halt(); } -#define JZ_REG_RTC_CTRL 0x00 -#define JZ_REG_RTC_HIBERNATE 0x20 -#define JZ_REG_RTC_WAKEUP_FILTER 0x24 -#define JZ_REG_RTC_RESET_COUNTER 0x28 - -#define JZ_RTC_CTRL_WRDY BIT(7) -#define JZ_RTC_WAKEUP_FILTER_MASK 0x0000FFE0 -#define JZ_RTC_RESET_COUNTER_MASK 0x00000FE0 - -static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base) -{ - uint32_t ctrl; - - do { - ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); - } while (!(ctrl & JZ_RTC_CTRL_WRDY)); -} - -static void jz4740_power_off(void) -{ - void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38); - unsigned long wakeup_filter_ticks; - unsigned long reset_counter_ticks; - struct clk *rtc_clk; - unsigned long rtc_rate; - - rtc_clk = clk_get(NULL, "rtc"); - if (IS_ERR(rtc_clk)) - panic("unable to get RTC clock"); - rtc_rate = clk_get_rate(rtc_clk); - clk_put(rtc_clk); - - /* - * Set minimum wakeup pin assertion time: 100 ms. - * Range is 0 to 2 sec if RTC is clocked at 32 kHz. - */ - wakeup_filter_ticks = (100 * rtc_rate) / 1000; - if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) - wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; - else - wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK; - jz4740_rtc_wait_ready(rtc_base); - writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER); - - /* - * Set reset pin low-level assertion time after wakeup: 60 ms. - * Range is 0 to 125 ms if RTC is clocked at 32 kHz. - */ - reset_counter_ticks = (60 * rtc_rate) / 1000; - if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) - reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; - else - reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK; - jz4740_rtc_wait_ready(rtc_base); - writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER); - - jz4740_rtc_wait_ready(rtc_base); - writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); - - jz4740_halt(); -} - void jz4740_reset_init(void) { _machine_restart = jz4740_restart; _machine_halt = jz4740_halt; - pm_power_off = jz4740_power_off; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 3da87e198878..a8ee573fe610 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -469,6 +469,7 @@ config KEXEC config KEXEC_FILE bool "kexec file based system call" select KEXEC_CORE + select HAVE_IMA_KEXEC select BUILD_BIN2C depends on PPC64 depends on CRYPTO=y diff --git a/arch/powerpc/include/asm/ima.h b/arch/powerpc/include/asm/ima.h new file mode 100644 index 000000000000..2313bdface34 --- /dev/null +++ b/arch/powerpc/include/asm/ima.h @@ -0,0 +1,29 @@ +#ifndef _ASM_POWERPC_IMA_H +#define _ASM_POWERPC_IMA_H + +struct kimage; + +int ima_get_kexec_buffer(void **addr, size_t *size); +int ima_free_kexec_buffer(void); + +#ifdef CONFIG_IMA +void remove_ima_buffer(void *fdt, int chosen_node); +#else +static inline void remove_ima_buffer(void *fdt, int chosen_node) {} +#endif + +#ifdef CONFIG_IMA_KEXEC +int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr, + size_t size); + +int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node); +#else +static inline int setup_ima_buffer(const struct kimage *image, void *fdt, + int chosen_node) +{ + remove_ima_buffer(fdt, chosen_node); + return 0; +} +#endif /* CONFIG_IMA_KEXEC */ + +#endif /* _ASM_POWERPC_IMA_H */ diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index 6c3b71502fbc..25668bc8cb2a 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h @@ -94,11 +94,22 @@ static inline bool kdump_in_progress(void) #ifdef CONFIG_KEXEC_FILE extern struct kexec_file_ops kexec_elf64_ops; +#ifdef CONFIG_IMA_KEXEC +#define ARCH_HAS_KIMAGE_ARCH + +struct kimage_arch { + phys_addr_t ima_buffer_addr; + size_t ima_buffer_size; +}; +#endif + int setup_purgatory(struct kimage *image, const void *slave_code, const void *fdt, unsigned long kernel_load_addr, unsigned long fdt_load_addr); -int setup_new_fdt(void *fdt, unsigned long initrd_load_addr, - unsigned long initrd_len, const char *cmdline); +int setup_new_fdt(const struct kimage *image, void *fdt, + unsigned long initrd_load_addr, unsigned long initrd_len, + const char *cmdline); +int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size); #endif /* CONFIG_KEXEC_FILE */ #else /* !CONFIG_KEXEC_CORE */ diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index a3a6047fd395..23f8082d7bfa 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -112,6 +112,10 @@ obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o crash.o \ machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file_$(BITS).o kexec_elf_$(BITS).o +ifeq ($(CONFIG_HAVE_IMA_KEXEC)$(CONFIG_IMA),yy) +obj-y += ima_kexec.o +endif + obj-$(CONFIG_AUDIT) += audit.o obj64-$(CONFIG_AUDIT) += compat_audit.o diff --git a/arch/powerpc/kernel/ima_kexec.c b/arch/powerpc/kernel/ima_kexec.c new file mode 100644 index 000000000000..5ea42c937ca9 --- /dev/null +++ b/arch/powerpc/kernel/ima_kexec.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2016 IBM Corporation + * + * Authors: + * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/slab.h> +#include <linux/kexec.h> +#include <linux/of.h> +#include <linux/memblock.h> +#include <linux/libfdt.h> + +static int get_addr_size_cells(int *addr_cells, int *size_cells) +{ + struct device_node *root; + + root = of_find_node_by_path("/"); + if (!root) + return -EINVAL; + + *addr_cells = of_n_addr_cells(root); + *size_cells = of_n_size_cells(root); + + of_node_put(root); + + return 0; +} + +static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr, + size_t *size) +{ + int ret, addr_cells, size_cells; + + ret = get_addr_size_cells(&addr_cells, &size_cells); + if (ret) + return ret; + + if (len < 4 * (addr_cells + size_cells)) + return -ENOENT; + + *addr = of_read_number(prop, addr_cells); + *size = of_read_number(prop + 4 * addr_cells, size_cells); + + return 0; +} + +/** + * ima_get_kexec_buffer - get IMA buffer from the previous kernel + * @addr: On successful return, set to point to the buffer contents. + * @size: On successful return, set to the buffer size. + * + * Return: 0 on success, negative errno on error. + */ +int ima_get_kexec_buffer(void **addr, size_t *size) +{ + int ret, len; + unsigned long tmp_addr; + size_t tmp_size; + const void *prop; + + prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len); + if (!prop) + return -ENOENT; + + ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size); + if (ret) + return ret; + + *addr = __va(tmp_addr); + *size = tmp_size; + + return 0; +} + +/** + * ima_free_kexec_buffer - free memory used by the IMA buffer + */ +int ima_free_kexec_buffer(void) +{ + int ret; + unsigned long addr; + size_t size; + struct property *prop; + + prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL); + if (!prop) + return -ENOENT; + < |