Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "The s390 patches for the 4.7 merge window have the usual bug fixes and cleanups, and the following new features: - An interface for dasd driver to query if a volume is online to another operating system - A new ioctl for the dasd driver to verify the format for a range of tracks - Following the example of x86 the struct fpu is now allocated with the task_struct - The 'report_error' interface for the PCI bus to send an adapter-error notification from user space to the service element of the machine" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (29 commits) s390/vmem: remove unused function parameter s390/vmem: fix identity mapping s390: add missing include statements s390: add missing declarations s390: make couple of variables and functions static s390/cache: remove superfluous locking s390/cpuinfo: simplify locking and skip offline cpus early s390/3270: hangup the 3270 tty after a disconnect s390/3270: handle reconnect of a tty with a different size s390/3270: avoid endless I/O loop with disconnected 3270 terminals s390/3270: fix garbled output on 3270 tty view s390/3270: fix view reference counting s390/3270: add missing tty_kref_put s390/dumpstack: implement and use return_address() s390/cpum_sf: Remove superfluous SMP function call s390/cpum_cf: Remove superfluous SMP function call s390/Kconfig: make z196 the default processor type s390/sclp: avoid compile warning in sclp_pci_report s390/fpu: allocate 'struct fpu' with the task_struct s390/crypto: cleanup and move the header with the cpacf definitions ...
This commit is contained in:
@@ -631,6 +631,29 @@ void pfault_fini(void)
|
||||
static DEFINE_SPINLOCK(pfault_lock);
|
||||
static LIST_HEAD(pfault_list);
|
||||
|
||||
#define PF_COMPLETE 0x0080
|
||||
|
||||
/*
|
||||
* The mechanism of our pfault code: if Linux is running as guest, runs a user
|
||||
* space process and the user space process accesses a page that the host has
|
||||
* paged out we get a pfault interrupt.
|
||||
*
|
||||
* This allows us, within the guest, to schedule a different process. Without
|
||||
* this mechanism the host would have to suspend the whole virtual cpu until
|
||||
* the page has been paged in.
|
||||
*
|
||||
* So when we get such an interrupt then we set the state of the current task
|
||||
* to uninterruptible and also set the need_resched flag. Both happens within
|
||||
* interrupt context(!). If we later on want to return to user space we
|
||||
* recognize the need_resched flag and then call schedule(). It's not very
|
||||
* obvious how this works...
|
||||
*
|
||||
* Of course we have a lot of additional fun with the completion interrupt (->
|
||||
* host signals that a page of a process has been paged in and the process can
|
||||
* continue to run). This interrupt can arrive on any cpu and, since we have
|
||||
* virtual cpus, actually appear before the interrupt that signals that a page
|
||||
* is missing.
|
||||
*/
|
||||
static void pfault_interrupt(struct ext_code ext_code,
|
||||
unsigned int param32, unsigned long param64)
|
||||
{
|
||||
@@ -639,10 +662,9 @@ static void pfault_interrupt(struct ext_code ext_code,
|
||||
pid_t pid;
|
||||
|
||||
/*
|
||||
* Get the external interruption subcode & pfault
|
||||
* initial/completion signal bit. VM stores this
|
||||
* in the 'cpu address' field associated with the
|
||||
* external interrupt.
|
||||
* Get the external interruption subcode & pfault initial/completion
|
||||
* signal bit. VM stores this in the 'cpu address' field associated
|
||||
* with the external interrupt.
|
||||
*/
|
||||
subcode = ext_code.subcode;
|
||||
if ((subcode & 0xff00) != __SUBCODE_MASK)
|
||||
@@ -658,7 +680,7 @@ static void pfault_interrupt(struct ext_code ext_code,
|
||||
if (!tsk)
|
||||
return;
|
||||
spin_lock(&pfault_lock);
|
||||
if (subcode & 0x0080) {
|
||||
if (subcode & PF_COMPLETE) {
|
||||
/* signal bit is set -> a page has been swapped in by VM */
|
||||
if (tsk->thread.pfault_wait == 1) {
|
||||
/* Initial interrupt was faster than the completion
|
||||
@@ -687,8 +709,7 @@ static void pfault_interrupt(struct ext_code ext_code,
|
||||
goto out;
|
||||
if (tsk->thread.pfault_wait == 1) {
|
||||
/* Already on the list with a reference: put to sleep */
|
||||
__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
|
||||
set_tsk_need_resched(tsk);
|
||||
goto block;
|
||||
} else if (tsk->thread.pfault_wait == -1) {
|
||||
/* Completion interrupt was faster than the initial
|
||||
* interrupt (pfault_wait == -1). Set pfault_wait
|
||||
@@ -703,7 +724,11 @@ static void pfault_interrupt(struct ext_code ext_code,
|
||||
get_task_struct(tsk);
|
||||
tsk->thread.pfault_wait = 1;
|
||||
list_add(&tsk->thread.list, &pfault_list);
|
||||
__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
|
||||
block:
|
||||
/* Since this must be a userspace fault, there
|
||||
* is no kernel task state to trample. Rely on the
|
||||
* return to userspace schedule() to block. */
|
||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
set_tsk_need_resched(tsk);
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@
|
||||
* Started by Ingo Molnar <mingo@elte.hu>
|
||||
*/
|
||||
|
||||
#include <linux/elf-randomize.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
|
@@ -56,7 +56,7 @@ static inline pmd_t *vmem_pmd_alloc(void)
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static pte_t __ref *vmem_pte_alloc(unsigned long address)
|
||||
static pte_t __ref *vmem_pte_alloc(void)
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
@@ -121,7 +121,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
|
||||
continue;
|
||||
}
|
||||
if (pmd_none(*pm_dir)) {
|
||||
pt_dir = vmem_pte_alloc(address);
|
||||
pt_dir = vmem_pte_alloc();
|
||||
if (!pt_dir)
|
||||
goto out;
|
||||
pmd_populate(&init_mm, pm_dir, pt_dir);
|
||||
@@ -233,7 +233,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
|
||||
address = (address + PMD_SIZE) & PMD_MASK;
|
||||
continue;
|
||||
}
|
||||
pt_dir = vmem_pte_alloc(address);
|
||||
pt_dir = vmem_pte_alloc();
|
||||
if (!pt_dir)
|
||||
goto out;
|
||||
pmd_populate(&init_mm, pm_dir, pt_dir);
|
||||
@@ -370,7 +370,7 @@ void __init vmem_map_init(void)
|
||||
ro_end = (unsigned long)&_eshared & PAGE_MASK;
|
||||
for_each_memblock(memory, reg) {
|
||||
start = reg->base;
|
||||
end = reg->base + reg->size - 1;
|
||||
end = reg->base + reg->size;
|
||||
if (start >= ro_end || end <= ro_start)
|
||||
vmem_add_mem(start, end - start, 0);
|
||||
else if (start >= ro_start && end <= ro_end)
|
||||
|
Reference in New Issue
Block a user