mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
RISC-V Patches for the 5.16 Merge Window, Part 1
* Support for time namespaces in the VDSO, along with some associated cleanups. * Support for building rv32 randconfigs. * Improvements to the XIP port that allow larger kernels to function * Various device tree cleanups for both the SiFive and Microchip boards * A handful of defconfig updates, including enabling Nouveau. There are also various small cleanups. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmGN9T4THHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYiQEBD/9EvGe5jPb8binNiLN81ExYh3HGBJ9A sY+/rhVWnTUX/igBU4M9gNHu5Rts2ITlsBda9YnYRgMunAS1cnZJ/jbvckfsFA+s svehPgDZSR+BqBnVDN1hEsY+TrNbFFFZIApGDbImuC5+81np/p3u1zkl3hhO0amJ 7T46qxRq4iazbuohi47/ba6ufXyLb8XBg3LTUfp+lTnH7/VLbwspPWdzNgiJpMzB qEWfYd4au2zfqHC6SYHXidy/tkquhJ6DgKq0G3+XUCugeennMeisDWI9GsxTAzIa Pynm9GHA/AuK1/kt9qB/Czsg7bqY8RUreUMLNZEyHzwKA1OWQVxlfCdl5zIpxlkq eJkxjbhhPuneVRGUSJgKQqBEUtGlH9yISqO2CFFdKRqzm1ImJtkAJGC+SubpKSbU D+ZAGbAyEwDUfl1yyKzKRg6YnzntMxh8sfNdJRYMrOhczk8L//R8yxG6SX6bjw7W lTQk7wkpo2yS7L799dukKdlllYbUvqavZwsIHTyb1TsRoavQeqoJq/6jKXJNhFHD rA/OQgCUXuHTmpgdDUhHuLZVvJqT5n8Vxigi30nIq24KOgTom8tRRtiAWOJv7G+Z b/Y3eq0VE8yjhPSbtsAxooZnpEVgXsVqx3t/lBt0MiJE1a3JLSSchRTHBjWllCiV +yvCerCh8PoT8w== =Mpen -----END PGP SIGNATURE----- Merge tag 'riscv-for-linus-5.16-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux Pull RISC-V updates from Palmer Dabbelt: - Support for time namespaces in the VDSO, along with some associated cleanups. - Support for building rv32 randconfigs. - Improvements to the XIP port that allow larger kernels to function - Various device tree cleanups for both the SiFive and Microchip boards - A handful of defconfig updates, including enabling Nouveau. There are also various small cleanups. * tag 'riscv-for-linus-5.16-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: riscv: defconfig: enable DRM_NOUVEAU riscv/vdso: Drop unneeded part due to merge issue riscv: remove .text section size limitation for XIP riscv: dts: sifive: add missing compatible for plic riscv: dts: microchip: add missing compatibles for clint and plic riscv: dts: sifive: drop duplicated nodes and properties in sifive riscv: dts: sifive: fix Unleashed board compatible riscv: dts: sifive: use only generic JEDEC SPI NOR flash compatible riscv: dts: microchip: use vendor compatible for Cadence SD4HC riscv: dts: microchip: drop unused pinctrl-names riscv: dts: microchip: drop duplicated MMC/SDHC node riscv: dts: microchip: fix board compatible riscv: dts: microchip: drop duplicated nodes dt-bindings: mmc: cdns: document Microchip MPFS MMC/SDHCI controller riscv: add rv32 and rv64 randconfig build targets riscv: mm: don't advertise 1 num_asid for 0 asid bits riscv: set default pm_power_off to NULL riscv/vdso: Add support for time namespaces
This commit is contained in:
commit
b89f311d7e
@ -62,6 +62,7 @@ config RISCV
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
|
@ -136,3 +136,13 @@ zinstall: install-image = Image.gz
|
||||
install zinstall:
|
||||
$(CONFIG_SHELL) $(srctree)/$(boot)/install.sh $(KERNELRELEASE) \
|
||||
$(boot)/$(install-image) System.map "$(INSTALL_PATH)"
|
||||
|
||||
PHONY += rv32_randconfig
|
||||
rv32_randconfig:
|
||||
$(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/riscv/configs/32-bit.config \
|
||||
-f $(srctree)/Makefile randconfig
|
||||
|
||||
PHONY += rv64_randconfig
|
||||
rv64_randconfig:
|
||||
$(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/riscv/configs/64-bit.config \
|
||||
-f $(srctree)/Makefile randconfig
|
||||
|
@ -9,10 +9,8 @@
|
||||
#define RTCCLK_FREQ 1000000
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
model = "Microchip PolarFire-SoC Icicle Kit";
|
||||
compatible = "microchip,mpfs-icicle-kit";
|
||||
compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &emac1;
|
||||
@ -35,9 +33,6 @@
|
||||
reg = <0x0 0x80000000 0x0 0x40000000>;
|
||||
clocks = <&clkcfg 26>;
|
||||
};
|
||||
|
||||
soc {
|
||||
};
|
||||
};
|
||||
|
||||
&serial0 {
|
||||
@ -56,8 +51,17 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdcard {
|
||||
&mmc {
|
||||
status = "okay";
|
||||
|
||||
bus-width = <4>;
|
||||
disable-wp;
|
||||
cap-sd-highspeed;
|
||||
card-detect-delay = <200>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
};
|
||||
|
||||
&emac0 {
|
||||
|
@ -6,8 +6,8 @@
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
model = "Microchip MPFS Icicle Kit";
|
||||
compatible = "microchip,mpfs-icicle-kit";
|
||||
model = "Microchip PolarFire SoC";
|
||||
compatible = "microchip,mpfs";
|
||||
|
||||
chosen {
|
||||
};
|
||||
@ -161,7 +161,7 @@
|
||||
};
|
||||
|
||||
clint@2000000 {
|
||||
compatible = "sifive,clint0";
|
||||
compatible = "sifive,fu540-c000-clint", "sifive,clint0";
|
||||
reg = <0x0 0x2000000 0x0 0xC000>;
|
||||
interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7
|
||||
&cpu1_intc 3 &cpu1_intc 7
|
||||
@ -172,7 +172,7 @@
|
||||
|
||||
plic: interrupt-controller@c000000 {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "sifive,plic-1.0.0";
|
||||
compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
|
||||
reg = <0x0 0xc000000 0x0 0x4000000>;
|
||||
riscv,ndev = <186>;
|
||||
interrupt-controller;
|
||||
@ -262,39 +262,13 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emmc: mmc@20008000 {
|
||||
compatible = "cdns,sd4hc";
|
||||
/* Common node entry for emmc/sd */
|
||||
mmc: mmc@20008000 {
|
||||
compatible = "microchip,mpfs-sd4hc", "cdns,sd4hc";
|
||||
reg = <0x0 0x20008000 0x0 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <88 89>;
|
||||
pinctrl-names = "default";
|
||||
clocks = <&clkcfg 6>;
|
||||
bus-width = <4>;
|
||||
cap-mmc-highspeed;
|
||||
mmc-ddr-3_3v;
|
||||
max-frequency = <200000000>;
|
||||
non-removable;
|
||||
no-sd;
|
||||
no-sdio;
|
||||
voltage-ranges = <3300 3300>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdcard: sdhc@20008000 {
|
||||
compatible = "cdns,sd4hc";
|
||||
reg = <0x0 0x20008000 0x0 0x1000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <88>;
|
||||
pinctrl-names = "default";
|
||||
clocks = <&clkcfg 6>;
|
||||
bus-width = <4>;
|
||||
disable-wp;
|
||||
cap-sd-highspeed;
|
||||
card-detect-delay = <200>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
max-frequency = <200000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -141,7 +141,7 @@
|
||||
ranges;
|
||||
plic0: interrupt-controller@c000000 {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "sifive,plic-1.0.0";
|
||||
compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
|
||||
reg = <0x0 0xc000000 0x0 0x4000000>;
|
||||
riscv,ndev = <53>;
|
||||
interrupt-controller;
|
||||
|
@ -8,10 +8,9 @@
|
||||
#define RTCCLK_FREQ 1000000
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
model = "SiFive HiFive Unleashed A00";
|
||||
compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
|
||||
compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000",
|
||||
"sifive,fu540";
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0";
|
||||
@ -26,9 +25,6 @@
|
||||
reg = <0x0 0x80000000 0x2 0x00000000>;
|
||||
};
|
||||
|
||||
soc {
|
||||
};
|
||||
|
||||
hfclk: hfclk {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
@ -63,7 +59,7 @@
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "issi,is25wp256", "jedec,spi-nor";
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
m25p,fast-read;
|
||||
|
@ -8,8 +8,6 @@
|
||||
#define RTCCLK_FREQ 1000000
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
model = "SiFive HiFive Unmatched A00";
|
||||
compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
|
||||
"sifive,fu740";
|
||||
@ -27,9 +25,6 @@
|
||||
reg = <0x0 0x80000000 0x4 0x00000000>;
|
||||
};
|
||||
|
||||
soc {
|
||||
};
|
||||
|
||||
hfclk: hfclk {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
@ -211,7 +206,7 @@
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "issi,is25wp256", "jedec,spi-nor";
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
m25p,fast-read;
|
||||
|
2
arch/riscv/configs/32-bit.config
Normal file
2
arch/riscv/configs/32-bit.config
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_ARCH_RV32I=y
|
||||
CONFIG_32BIT=y
|
2
arch/riscv/configs/64-bit.config
Normal file
2
arch/riscv/configs/64-bit.config
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_ARCH_RV64I=y
|
||||
CONFIG_64BIT=y
|
@ -72,9 +72,10 @@ CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_SIFIVE=y
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_RADEON=y
|
||||
CONFIG_DRM_VIRTIO_GPU=y
|
||||
CONFIG_DRM=m
|
||||
CONFIG_DRM_RADEON=m
|
||||
CONFIG_DRM_NOUVEAU=m
|
||||
CONFIG_DRM_VIRTIO_GPU=m
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
|
@ -157,6 +157,8 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
|
||||
#define page_to_bus(page) (page_to_phys(page))
|
||||
#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr)))
|
||||
|
||||
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
|
||||
|
||||
#ifdef CONFIG_FLATMEM
|
||||
#define pfn_valid(pfn) \
|
||||
(((pfn) >= ARCH_PFN_OFFSET) && (((pfn) - ARCH_PFN_OFFSET) < max_mapnr))
|
||||
|
@ -75,7 +75,8 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define XIP_OFFSET SZ_8M
|
||||
#define XIP_OFFSET SZ_32M
|
||||
#define XIP_OFFSET_MASK (SZ_32M - 1)
|
||||
#else
|
||||
#define XIP_OFFSET 0
|
||||
#endif
|
||||
@ -97,7 +98,8 @@
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define XIP_FIXUP(addr) ({ \
|
||||
uintptr_t __a = (uintptr_t)(addr); \
|
||||
(__a >= CONFIG_XIP_PHYS_ADDR && __a < CONFIG_XIP_PHYS_ADDR + SZ_16M) ? \
|
||||
(__a >= CONFIG_XIP_PHYS_ADDR && \
|
||||
__a < CONFIG_XIP_PHYS_ADDR + XIP_OFFSET * 2) ? \
|
||||
__a - CONFIG_XIP_PHYS_ADDR + CONFIG_PHYS_RAM_BASE - XIP_OFFSET :\
|
||||
__a; \
|
||||
})
|
||||
|
@ -8,30 +8,19 @@
|
||||
#ifndef _ASM_RISCV_VDSO_H
|
||||
#define _ASM_RISCV_VDSO_H
|
||||
|
||||
|
||||
/*
|
||||
* All systems with an MMU have a VDSO, but systems without an MMU don't
|
||||
* support shared libraries and therefor don't have one.
|
||||
*/
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#include <linux/types.h>
|
||||
/*
|
||||
* All systems with an MMU have a VDSO, but systems without an MMU don't
|
||||
* support shared libraries and therefor don't have one.
|
||||
*/
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#define __VVAR_PAGES 1
|
||||
#define __VVAR_PAGES 2
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <generated/vdso-offsets.h>
|
||||
|
||||
#define VDSO_SYMBOL(base, name) \
|
||||
(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
@ -76,6 +76,13 @@ static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
|
||||
return _vdso_data;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
static __always_inline
|
||||
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
|
||||
{
|
||||
return _timens_data;
|
||||
}
|
||||
#endif
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
|
||||
|
@ -20,10 +20,20 @@
|
||||
REG_L t0, _xip_fixup
|
||||
add \reg, \reg, t0
|
||||
.endm
|
||||
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||
la t1, __data_loc
|
||||
li t0, XIP_OFFSET_MASK
|
||||
and t1, t1, t0
|
||||
li t1, XIP_OFFSET
|
||||
sub t0, t0, t1
|
||||
sub \reg, \reg, t0
|
||||
.endm
|
||||
_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET
|
||||
#else
|
||||
.macro XIP_FIXUP_OFFSET reg
|
||||
.endm
|
||||
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||
.endm
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
__HEAD
|
||||
@ -267,6 +277,7 @@ pmp_done:
|
||||
la a3, hart_lottery
|
||||
mv a2, a3
|
||||
XIP_FIXUP_OFFSET a2
|
||||
XIP_FIXUP_FLASH_OFFSET a3
|
||||
lw t1, (a3)
|
||||
amoswap.w t0, t1, (a2)
|
||||
/* first time here if hart_lottery in RAM is not set */
|
||||
@ -305,6 +316,7 @@ clear_bss_done:
|
||||
XIP_FIXUP_OFFSET sp
|
||||
#ifdef CONFIG_BUILTIN_DTB
|
||||
la a0, __dtb_start
|
||||
XIP_FIXUP_OFFSET a0
|
||||
#else
|
||||
mv a0, s1
|
||||
#endif /* CONFIG_BUILTIN_DTB */
|
||||
|
@ -12,7 +12,7 @@ static void default_power_off(void)
|
||||
wait_for_interrupt();
|
||||
}
|
||||
|
||||
void (*pm_power_off)(void) = default_power_off;
|
||||
void (*pm_power_off)(void) = NULL;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
void machine_restart(char *cmd)
|
||||
@ -23,10 +23,16 @@ void machine_restart(char *cmd)
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
if (pm_power_off != NULL)
|
||||
pm_power_off();
|
||||
else
|
||||
default_power_off();
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
if (pm_power_off != NULL)
|
||||
pm_power_off();
|
||||
else
|
||||
default_power_off();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/vdso.h>
|
||||
#include <linux/time_namespace.h>
|
||||
|
||||
#ifdef CONFIG_GENERIC_TIME_VSYSCALL
|
||||
#include <vdso/datapage.h>
|
||||
@ -25,14 +26,12 @@ extern char vdso_start[], vdso_end[];
|
||||
|
||||
enum vvar_pages {
|
||||
VVAR_DATA_PAGE_OFFSET,
|
||||
VVAR_TIMENS_PAGE_OFFSET,
|
||||
VVAR_NR_PAGES,
|
||||
};
|
||||
|
||||
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
|
||||
|
||||
static unsigned int vdso_pages __ro_after_init;
|
||||
static struct page **vdso_pagelist __ro_after_init;
|
||||
|
||||
/*
|
||||
* The vDSO data page.
|
||||
*/
|
||||
@ -42,83 +41,228 @@ static union {
|
||||
} vdso_data_store __page_aligned_data;
|
||||
struct vdso_data *vdso_data = &vdso_data_store.data;
|
||||
|
||||
static int __init vdso_init(void)
|
||||
struct __vdso_info {
|
||||
const char *name;
|
||||
const char *vdso_code_start;
|
||||
const char *vdso_code_end;
|
||||
unsigned long vdso_pages;
|
||||
/* Data Mapping */
|
||||
struct vm_special_mapping *dm;
|
||||
/* Code Mapping */
|
||||
struct vm_special_mapping *cm;
|
||||
};
|
||||
|
||||
static struct __vdso_info vdso_info __ro_after_init = {
|
||||
.name = "vdso",
|
||||
.vdso_code_start = vdso_start,
|
||||
.vdso_code_end = vdso_end,
|
||||
};
|
||||
|
||||
static int vdso_mremap(const struct vm_special_mapping *sm,
|
||||
struct vm_area_struct *new_vma)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
|
||||
vdso_pagelist =
|
||||
kcalloc(vdso_pages + VVAR_NR_PAGES, sizeof(struct page *), GFP_KERNEL);
|
||||
if (unlikely(vdso_pagelist == NULL)) {
|
||||
pr_err("vdso: pagelist allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < vdso_pages; i++) {
|
||||
struct page *pg;
|
||||
|
||||
pg = virt_to_page(vdso_start + (i << PAGE_SHIFT));
|
||||
vdso_pagelist[i] = pg;
|
||||
}
|
||||
vdso_pagelist[i] = virt_to_page(vdso_data);
|
||||
current->mm->context.vdso = (void *)new_vma->vm_start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init __vdso_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct page **vdso_pagelist;
|
||||
unsigned long pfn;
|
||||
|
||||
if (memcmp(vdso_info.vdso_code_start, "\177ELF", 4)) {
|
||||
pr_err("vDSO is not a valid ELF object!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vdso_info.vdso_pages = (
|
||||
vdso_info.vdso_code_end -
|
||||
vdso_info.vdso_code_start) >>
|
||||
PAGE_SHIFT;
|
||||
|
||||
vdso_pagelist = kcalloc(vdso_info.vdso_pages,
|
||||
sizeof(struct page *),
|
||||
GFP_KERNEL);
|
||||
if (vdso_pagelist == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Grab the vDSO code pages. */
|
||||
pfn = sym_to_pfn(vdso_info.vdso_code_start);
|
||||
|
||||
for (i = 0; i < vdso_info.vdso_pages; i++)
|
||||
vdso_pagelist[i] = pfn_to_page(pfn + i);
|
||||
|
||||
vdso_info.cm->pages = vdso_pagelist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
struct vdso_data *arch_get_vdso_data(void *vvar_page)
|
||||
{
|
||||
return (struct vdso_data *)(vvar_page);
|
||||
}
|
||||
|
||||
/*
|
||||
* The vvar mapping contains data for a specific time namespace, so when a task
|
||||
* changes namespace we must unmap its vvar data for the old namespace.
|
||||
* Subsequent faults will map in data for the new namespace.
|
||||
*
|
||||
* For more details see timens_setup_vdso_data().
|
||||
*/
|
||||
int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
{
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
mmap_read_lock(mm);
|
||||
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
|
||||
if (vma_is_special_mapping(vma, vdso_info.dm))
|
||||
zap_page_range(vma, vma->vm_start, size);
|
||||
}
|
||||
|
||||
mmap_read_unlock(mm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
|
||||
{
|
||||
if (likely(vma->vm_mm == current->mm))
|
||||
return current->nsproxy->time_ns->vvar_page;
|
||||
|
||||
/*
|
||||
* VM_PFNMAP | VM_IO protect .fault() handler from being called
|
||||
* through interfaces like /proc/$pid/mem or
|
||||
* process_vm_{readv,writev}() as long as there's no .access()
|
||||
* in special_mapping_vmops.
|
||||
* For more details check_vma_flags() and __access_remote_vm()
|
||||
*/
|
||||
WARN(1, "vvar_page accessed remotely");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||
struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
struct page *timens_page = find_timens_vvar_page(vma);
|
||||
unsigned long pfn;
|
||||
|
||||
switch (vmf->pgoff) {
|
||||
case VVAR_DATA_PAGE_OFFSET:
|
||||
if (timens_page)
|
||||
pfn = page_to_pfn(timens_page);
|
||||
else
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
break;
|
||||
#ifdef CONFIG_TIME_NS
|
||||
case VVAR_TIMENS_PAGE_OFFSET:
|
||||
/*
|
||||
* If a task belongs to a time namespace then a namespace
|
||||
* specific VVAR is mapped with the VVAR_DATA_PAGE_OFFSET and
|
||||
* the real VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET
|
||||
* offset.
|
||||
* See also the comment near timens_setup_vdso_data().
|
||||
*/
|
||||
if (!timens_page)
|
||||
return VM_FAULT_SIGBUS;
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
break;
|
||||
#endif /* CONFIG_TIME_NS */
|
||||
default:
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
return vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
}
|
||||
|
||||
enum rv_vdso_map {
|
||||
RV_VDSO_MAP_VVAR,
|
||||
RV_VDSO_MAP_VDSO,
|
||||
};
|
||||
|
||||
static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
|
||||
[RV_VDSO_MAP_VVAR] = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
[RV_VDSO_MAP_VDSO] = {
|
||||
.name = "[vdso]",
|
||||
.mremap = vdso_mremap,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init vdso_init(void)
|
||||
{
|
||||
vdso_info.dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR];
|
||||
vdso_info.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO];
|
||||
|
||||
return __vdso_init();
|
||||
}
|
||||
arch_initcall(vdso_init);
|
||||
|
||||
int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
static int __setup_additional_pages(struct mm_struct *mm,
|
||||
struct linux_binprm *bprm,
|
||||
int uses_interp)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long vdso_base, vdso_len;
|
||||
int ret;
|
||||
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
|
||||
void *ret;
|
||||
|
||||
BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
|
||||
|
||||
vdso_len = (vdso_pages + VVAR_NR_PAGES) << PAGE_SHIFT;
|
||||
vdso_text_len = vdso_info.vdso_pages << PAGE_SHIFT;
|
||||
/* Be sure to map the data page */
|
||||
vdso_mapping_len = vdso_text_len + VVAR_SIZE;
|
||||
|
||||
vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
|
||||
if (IS_ERR_VALUE(vdso_base)) {
|
||||
ret = ERR_PTR(vdso_base);
|
||||
goto up_fail;
|
||||
}
|
||||
|
||||
ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE,
|
||||
(VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info.dm);
|
||||
if (IS_ERR(ret))
|
||||
goto up_fail;
|
||||
|
||||
vdso_base += VVAR_SIZE;
|
||||
mm->context.vdso = (void *)vdso_base;
|
||||
ret =
|
||||
_install_special_mapping(mm, vdso_base, vdso_text_len,
|
||||
(VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC),
|
||||
vdso_info.cm);
|
||||
|
||||
if (IS_ERR(ret))
|
||||
goto up_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
up_fail:
|
||||
mm->context.vdso = NULL;
|
||||
return PTR_ERR(ret);
|
||||
}
|
||||
|
||||
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
int ret;
|
||||
|
||||
if (mmap_write_lock_killable(mm))
|
||||
return -EINTR;
|
||||
|
||||
vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0);
|
||||
if (IS_ERR_VALUE(vdso_base)) {
|
||||
ret = vdso_base;
|
||||
goto end;
|
||||
}
|
||||
|
||||
mm->context.vdso = NULL;
|
||||
ret = install_special_mapping(mm, vdso_base, VVAR_SIZE,
|
||||
(VM_READ | VM_MAYREAD), &vdso_pagelist[vdso_pages]);
|
||||
if (unlikely(ret))
|
||||
goto end;
|
||||
|
||||
ret =
|
||||
install_special_mapping(mm, vdso_base + VVAR_SIZE,
|
||||
vdso_pages << PAGE_SHIFT,
|
||||
(VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC),
|
||||
vdso_pagelist);
|
||||
|
||||
if (unlikely(ret))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Put vDSO base into mm struct. We need to do this before calling
|
||||
* install_special_mapping or the perf counter mmap tracking code
|
||||
* will fail to recognise it as a vDSO (since arch_vma_name fails).
|
||||
*/
|
||||
mm->context.vdso = (void *)vdso_base + VVAR_SIZE;
|
||||
|
||||
end:
|
||||
ret = __setup_additional_pages(mm, bprm, uses_interp);
|
||||
mmap_write_unlock(mm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *arch_vma_name(struct vm_area_struct *vma)
|
||||
{
|
||||
if (vma->vm_mm && (vma->vm_start == (long)vma->vm_mm->context.vdso))
|
||||
return "[vdso]";
|
||||
if (vma->vm_mm && (vma->vm_start ==
|
||||
(long)vma->vm_mm->context.vdso - VVAR_SIZE))
|
||||
return "[vdso_data]";
|
||||
return NULL;
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ OUTPUT_ARCH(riscv)
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE);
|
||||
#ifdef CONFIG_TIME_NS
|
||||
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
|
||||
#endif
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
.hash : { *(.hash) } :text
|
||||
|
@ -64,8 +64,11 @@ SECTIONS
|
||||
/*
|
||||
* From this point, stuff is considered writable and will be copied to RAM
|
||||
*/
|
||||
__data_loc = ALIGN(16); /* location in file */
|
||||
. = LOAD_OFFSET + XIP_OFFSET; /* location in memory */
|
||||
__data_loc = ALIGN(PAGE_SIZE); /* location in file */
|
||||
. = KERNEL_LINK_ADDR + XIP_OFFSET; /* location in memory */
|
||||
|
||||
#undef LOAD_OFFSET
|
||||
#define LOAD_OFFSET (KERNEL_LINK_ADDR + XIP_OFFSET - (__data_loc & XIP_OFFSET_MASK))
|
||||
|
||||
_sdata = .; /* Start of data section */
|
||||
_data = .;
|
||||
@ -96,7 +99,6 @@ SECTIONS
|
||||
KEEP(*(__soc_builtin_dtb_table))
|
||||
__soc_builtin_dtb_table_end = .;
|
||||
}
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
|
||||
. = ALIGN(8);
|
||||
.alternative : {
|
||||
@ -122,6 +124,8 @@ SECTIONS
|
||||
|
||||
BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
|
||||
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
|
||||
.rel.dyn : AT(ADDR(.rel.dyn) - LOAD_OFFSET) {
|
||||
*(.rel.dyn*)
|
||||
}
|
||||
|
@ -233,8 +233,10 @@ static int __init asids_init(void)
|
||||
local_flush_tlb_all();
|
||||
|
||||
/* Pre-compute ASID details */
|
||||
if (asid_bits) {
|
||||
num_asids = 1 << asid_bits;
|
||||
asid_mask = num_asids - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use ASID allocator only if number of HW ASIDs are
|
||||
@ -255,7 +257,7 @@ static int __init asids_init(void)
|
||||
pr_info("ASID allocator using %lu bits (%lu entries)\n",
|
||||
asid_bits, num_asids);
|
||||
} else {
|
||||
pr_info("ASID allocator disabled\n");
|
||||
pr_info("ASID allocator disabled (%lu bits)\n", asid_bits);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -41,7 +41,7 @@ phys_addr_t phys_ram_base __ro_after_init;
|
||||
EXPORT_SYMBOL(phys_ram_base);
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
extern char _xiprom[], _exiprom[];
|
||||
extern char _xiprom[], _exiprom[], __data_loc;
|
||||
#endif
|
||||
|
||||
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
|
||||
@ -454,10 +454,9 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
|
||||
/* called from head.S with MMU off */
|
||||
asmlinkage void __init __copy_data(void)
|
||||
{
|
||||
void *from = (void *)(&_sdata);
|
||||
void *end = (void *)(&_end);
|
||||
void *from = (void *)(&__data_loc);
|
||||
void *to = (void *)CONFIG_PHYS_RAM_BASE;
|
||||
size_t sz = (size_t)(end - from + 1);
|
||||
size_t sz = (size_t)((uintptr_t)(&_end) - (uintptr_t)(&_sdata));
|
||||
|
||||
memcpy(to, from, sz);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user