s390/kvm: avoid global config of vm.alloc_pgste=1
The system control vm.alloc_pgste is used to control the size of the page tables, either 2K or 4K. The idea is that a KVM host sets the vm.alloc_pgste control to 1 which causes *all* new processes to run with 4K page tables. For a non-kvm system the control should stay off to save on memory used for page tables. Trouble is that distributions choose to set the control globally to be able to run KVM guests. This wastes memory on non-KVM systems. Introduce the PT_S390_PGSTE ELF segment type to "mark" the qemu executable with it. All executables with this (empty) segment in its ELF phdr array will be started with 4K page tables. Any executable without PT_S390_PGSTE will run with the default 2K page tables. This removes the need to set vm.alloc_pgste=1 for a KVM host and minimizes the waste of memory for page tables. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
a752598254
commit
23fefe119c
|
@ -64,6 +64,7 @@ config ARCH_SUPPORTS_UPROBES
|
||||||
|
|
||||||
config S390
|
config S390
|
||||||
def_bool y
|
def_bool y
|
||||||
|
select ARCH_BINFMT_ELF_STATE
|
||||||
select ARCH_HAS_DEVMEM_IS_ALLOWED
|
select ARCH_HAS_DEVMEM_IS_ALLOWED
|
||||||
select ARCH_HAS_ELF_RANDOMIZE
|
select ARCH_HAS_ELF_RANDOMIZE
|
||||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||||
|
|
|
@ -117,6 +117,9 @@
|
||||||
#define ELF_DATA ELFDATA2MSB
|
#define ELF_DATA ELFDATA2MSB
|
||||||
#define ELF_ARCH EM_S390
|
#define ELF_ARCH EM_S390
|
||||||
|
|
||||||
|
/* s390 specific phdr types */
|
||||||
|
#define PT_S390_PGSTE 0x70000000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ELF register definitions..
|
* ELF register definitions..
|
||||||
*/
|
*/
|
||||||
|
@ -151,6 +154,35 @@ extern unsigned int vdso_enabled;
|
||||||
&& (x)->e_ident[EI_CLASS] == ELF_CLASS)
|
&& (x)->e_ident[EI_CLASS] == ELF_CLASS)
|
||||||
#define compat_start_thread start_thread31
|
#define compat_start_thread start_thread31
|
||||||
|
|
||||||
|
struct arch_elf_state {
|
||||||
|
int rc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INIT_ARCH_ELF_STATE { .rc = 0 }
|
||||||
|
|
||||||
|
#define arch_check_elf(ehdr, interp, interp_ehdr, state) (0)
|
||||||
|
#ifdef CONFIG_PGSTE
|
||||||
|
#define arch_elf_pt_proc(ehdr, phdr, elf, interp, state) \
|
||||||
|
({ \
|
||||||
|
struct arch_elf_state *_state = state; \
|
||||||
|
if ((phdr)->p_type == PT_S390_PGSTE && \
|
||||||
|
!page_table_allocate_pgste && \
|
||||||
|
!test_thread_flag(TIF_PGSTE) && \
|
||||||
|
!current->mm->context.alloc_pgste) { \
|
||||||
|
set_thread_flag(TIF_PGSTE); \
|
||||||
|
set_pt_regs_flag(task_pt_regs(current), \
|
||||||
|
PIF_SYSCALL_RESTART); \
|
||||||
|
_state->rc = -EAGAIN; \
|
||||||
|
} \
|
||||||
|
_state->rc; \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
#define arch_elf_pt_proc(ehdr, phdr, elf, interp, state) \
|
||||||
|
({ \
|
||||||
|
(state)->rc; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For SVR4/S390 the function pointer to be registered with `atexit` is
|
/* For SVR4/S390 the function pointer to be registered with `atexit` is
|
||||||
passed in R14. */
|
passed in R14. */
|
||||||
#define ELF_PLAT_INIT(_r, load_addr) \
|
#define ELF_PLAT_INIT(_r, load_addr) \
|
||||||
|
|
|
@ -25,7 +25,9 @@ static inline int init_new_context(struct task_struct *tsk,
|
||||||
mm->context.gmap_asce = 0;
|
mm->context.gmap_asce = 0;
|
||||||
mm->context.flush_mm = 0;
|
mm->context.flush_mm = 0;
|
||||||
#ifdef CONFIG_PGSTE
|
#ifdef CONFIG_PGSTE
|
||||||
mm->context.alloc_pgste = page_table_allocate_pgste;
|
mm->context.alloc_pgste = page_table_allocate_pgste ||
|
||||||
|
test_thread_flag(TIF_PGSTE) ||
|
||||||
|
current->mm->context.alloc_pgste;
|
||||||
mm->context.has_pgste = 0;
|
mm->context.has_pgste = 0;
|
||||||
mm->context.use_skey = 0;
|
mm->context.use_skey = 0;
|
||||||
mm->context.use_cmma = 0;
|
mm->context.use_cmma = 0;
|
||||||
|
|
|
@ -11,9 +11,11 @@
|
||||||
|
|
||||||
#define PIF_SYSCALL 0 /* inside a system call */
|
#define PIF_SYSCALL 0 /* inside a system call */
|
||||||
#define PIF_PER_TRAP 1 /* deliver sigtrap on return to user */
|
#define PIF_PER_TRAP 1 /* deliver sigtrap on return to user */
|
||||||
|
#define PIF_SYSCALL_RESTART 2 /* restart the current system call */
|
||||||
|
|
||||||
#define _PIF_SYSCALL _BITUL(PIF_SYSCALL)
|
#define _PIF_SYSCALL _BITUL(PIF_SYSCALL)
|
||||||
#define _PIF_PER_TRAP _BITUL(PIF_PER_TRAP)
|
#define _PIF_PER_TRAP _BITUL(PIF_PER_TRAP)
|
||||||
|
#define _PIF_SYSCALL_RESTART _BITUL(PIF_SYSCALL_RESTART)
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
|
||||||
#define TIF_UPROBE 3 /* breakpointed or single-stepping */
|
#define TIF_UPROBE 3 /* breakpointed or single-stepping */
|
||||||
#define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */
|
#define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */
|
||||||
#define TIF_PATCH_PENDING 5 /* pending live patching update */
|
#define TIF_PATCH_PENDING 5 /* pending live patching update */
|
||||||
|
#define TIF_PGSTE 6 /* New mm's will use 4K page tables */
|
||||||
|
|
||||||
#define TIF_31BIT 16 /* 32bit process */
|
#define TIF_31BIT 16 /* 32bit process */
|
||||||
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
|
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
|
||||||
|
|
|
@ -52,7 +52,7 @@ _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
|
||||||
_TIF_SYSCALL_TRACEPOINT)
|
_TIF_SYSCALL_TRACEPOINT)
|
||||||
_CIF_WORK = (_CIF_MCCK_PENDING | _CIF_ASCE_PRIMARY | \
|
_CIF_WORK = (_CIF_MCCK_PENDING | _CIF_ASCE_PRIMARY | \
|
||||||
_CIF_ASCE_SECONDARY | _CIF_FPU)
|
_CIF_ASCE_SECONDARY | _CIF_FPU)
|
||||||
_PIF_WORK = (_PIF_PER_TRAP)
|
_PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCALL_RESTART)
|
||||||
|
|
||||||
#define BASED(name) name-cleanup_critical(%r13)
|
#define BASED(name) name-cleanup_critical(%r13)
|
||||||
|
|
||||||
|
@ -334,6 +334,8 @@ ENTRY(system_call)
|
||||||
jo .Lsysc_mcck_pending
|
jo .Lsysc_mcck_pending
|
||||||
TSTMSK __TI_flags(%r12),_TIF_NEED_RESCHED
|
TSTMSK __TI_flags(%r12),_TIF_NEED_RESCHED
|
||||||
jo .Lsysc_reschedule
|
jo .Lsysc_reschedule
|
||||||
|
TSTMSK __PT_FLAGS(%r11),_PIF_SYSCALL_RESTART
|
||||||
|
jo .Lsysc_syscall_restart
|
||||||
#ifdef CONFIG_UPROBES
|
#ifdef CONFIG_UPROBES
|
||||||
TSTMSK __TI_flags(%r12),_TIF_UPROBE
|
TSTMSK __TI_flags(%r12),_TIF_UPROBE
|
||||||
jo .Lsysc_uprobe_notify
|
jo .Lsysc_uprobe_notify
|
||||||
|
@ -347,6 +349,8 @@ ENTRY(system_call)
|
||||||
jo .Lsysc_patch_pending # handle live patching just before
|
jo .Lsysc_patch_pending # handle live patching just before
|
||||||
# signals and possible syscall restart
|
# signals and possible syscall restart
|
||||||
#endif
|
#endif
|
||||||
|
TSTMSK __PT_FLAGS(%r11),_PIF_SYSCALL_RESTART
|
||||||
|
jo .Lsysc_syscall_restart
|
||||||
TSTMSK __TI_flags(%r12),_TIF_SIGPENDING
|
TSTMSK __TI_flags(%r12),_TIF_SIGPENDING
|
||||||
jo .Lsysc_sigpending
|
jo .Lsysc_sigpending
|
||||||
TSTMSK __TI_flags(%r12),_TIF_NOTIFY_RESUME
|
TSTMSK __TI_flags(%r12),_TIF_NOTIFY_RESUME
|
||||||
|
@ -447,6 +451,15 @@ ENTRY(system_call)
|
||||||
larl %r14,.Lsysc_return
|
larl %r14,.Lsysc_return
|
||||||
jg do_per_trap
|
jg do_per_trap
|
||||||
|
|
||||||
|
#
|
||||||
|
# _PIF_SYSCALL_RESTART is set, repeat the current system call
|
||||||
|
#
|
||||||
|
.Lsysc_syscall_restart:
|
||||||
|
ni __PT_FLAGS+7(%r11),255-_PIF_SYSCALL_RESTART
|
||||||
|
lmg %r1,%r7,__PT_R1(%r11) # load svc arguments
|
||||||
|
lg %r2,__PT_ORIG_GPR2(%r11)
|
||||||
|
j .Lsysc_do_svc
|
||||||
|
|
||||||
#
|
#
|
||||||
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
||||||
# and after the system call
|
# and after the system call
|
||||||
|
|
Loading…
Reference in New Issue