Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aec040e2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
  [S390] fix kvm defines for 31 bit compile
  [S390] use generic RCU page-table freeing code
  [S390] qdio: Split SBAL entry flags
  [S390] kvm-s390: fix stfle facilities numbers >=64
  [S390] kvm-s390: Fix host crash on misbehaving guests
parents 8ea656bd 6c61cfe9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ config S390
	select HAVE_GET_USER_PAGES_FAST
	select HAVE_ARCH_MUTEX_CPU_RELAX
	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
	select HAVE_RCU_TABLE_FREE if SMP
	select ARCH_INLINE_SPIN_TRYLOCK
	select ARCH_INLINE_SPIN_TRYLOCK_BH
	select ARCH_INLINE_SPIN_LOCK
+4 −4
Original line number Diff line number Diff line
@@ -17,15 +17,15 @@
#include <linux/gfp.h>
#include <linux/mm.h>

#define check_pgt_cache()	do {} while (0)

unsigned long *crst_table_alloc(struct mm_struct *);
void crst_table_free(struct mm_struct *, unsigned long *);
void crst_table_free_rcu(struct mm_struct *, unsigned long *);

unsigned long *page_table_alloc(struct mm_struct *);
void page_table_free(struct mm_struct *, unsigned long *);
void page_table_free_rcu(struct mm_struct *, unsigned long *);
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
void __tlb_remove_table(void *_table);
#endif

static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
+26 −13
Original line number Diff line number Diff line
@@ -293,19 +293,6 @@ extern unsigned long VMALLOC_START;
 * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
 */

/* Page status table bits for virtualization */
#define RCP_ACC_BITS	0xf000000000000000UL
#define RCP_FP_BIT	0x0800000000000000UL
#define RCP_PCL_BIT	0x0080000000000000UL
#define RCP_HR_BIT	0x0040000000000000UL
#define RCP_HC_BIT	0x0020000000000000UL
#define RCP_GR_BIT	0x0004000000000000UL
#define RCP_GC_BIT	0x0002000000000000UL

/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT	0x0000800000000000UL
#define KVM_UC_BIT	0x0000400000000000UL

#ifndef __s390x__

/* Bits in the segment table address-space-control-element */
@@ -325,6 +312,19 @@ extern unsigned long VMALLOC_START;
#define _SEGMENT_ENTRY		(_SEGMENT_ENTRY_PTL)
#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INV)

/* Page status table bits for virtualization */
#define RCP_ACC_BITS	0xf0000000UL
#define RCP_FP_BIT	0x08000000UL
#define RCP_PCL_BIT	0x00800000UL
#define RCP_HR_BIT	0x00400000UL
#define RCP_HC_BIT	0x00200000UL
#define RCP_GR_BIT	0x00040000UL
#define RCP_GC_BIT	0x00020000UL

/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT	0x00008000UL
#define KVM_UC_BIT	0x00004000UL

#else /* __s390x__ */

/* Bits in the segment/region table address-space-control-element */
@@ -367,6 +367,19 @@ extern unsigned long VMALLOC_START;
#define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */
#define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */

/* Page status table bits for virtualization */
#define RCP_ACC_BITS	0xf000000000000000UL
#define RCP_FP_BIT	0x0800000000000000UL
#define RCP_PCL_BIT	0x0080000000000000UL
#define RCP_HR_BIT	0x0040000000000000UL
#define RCP_HC_BIT	0x0020000000000000UL
#define RCP_GR_BIT	0x0004000000000000UL
#define RCP_GC_BIT	0x0002000000000000UL

/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT	0x0000800000000000UL
#define KVM_UC_BIT	0x0000400000000000UL

#endif /* __s390x__ */

/*
+28 −91
Original line number Diff line number Diff line
@@ -139,110 +139,47 @@ struct slib {
	struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q];
} __attribute__ ((packed, aligned(2048)));

/**
 * struct sbal_flags - storage block address list flags
 * @last: last entry
 * @cont: contiguous storage
 * @frag: fragmentation
 */
struct sbal_flags {
	u8	: 1;
	u8 last : 1;
	u8 cont : 1;
	u8	: 1;
	u8 frag : 2;
	u8	: 2;
} __attribute__ ((packed));

#define SBAL_FLAGS_FIRST_FRAG		0x04000000UL
#define SBAL_FLAGS_MIDDLE_FRAG		0x08000000UL
#define SBAL_FLAGS_LAST_FRAG		0x0c000000UL
#define SBAL_FLAGS_LAST_ENTRY		0x40000000UL
#define SBAL_FLAGS_CONTIGUOUS		0x20000000UL
#define SBAL_EFLAGS_LAST_ENTRY		0x40
#define SBAL_EFLAGS_CONTIGUOUS		0x20
#define SBAL_EFLAGS_FIRST_FRAG		0x04
#define SBAL_EFLAGS_MIDDLE_FRAG		0x08
#define SBAL_EFLAGS_LAST_FRAG		0x0c
#define SBAL_EFLAGS_MASK		0x6f

#define SBAL_FLAGS0_DATA_CONTINUATION	0x20UL
#define SBAL_SFLAGS0_PCI_REQ		0x40
#define SBAL_SFLAGS0_DATA_CONTINUATION	0x20

/* Awesome OpenFCP extensions */
#define SBAL_FLAGS0_TYPE_STATUS		0x00UL
#define SBAL_FLAGS0_TYPE_WRITE		0x08UL
#define SBAL_FLAGS0_TYPE_READ		0x10UL
#define SBAL_FLAGS0_TYPE_WRITE_READ	0x18UL
#define SBAL_FLAGS0_MORE_SBALS		0x04UL
#define SBAL_FLAGS0_COMMAND		0x02UL
#define SBAL_FLAGS0_LAST_SBAL		0x00UL
#define SBAL_FLAGS0_ONLY_SBAL		SBAL_FLAGS0_COMMAND
#define SBAL_FLAGS0_MIDDLE_SBAL		SBAL_FLAGS0_MORE_SBALS
#define SBAL_FLAGS0_FIRST_SBAL SBAL_FLAGS0_MORE_SBALS | SBAL_FLAGS0_COMMAND
#define SBAL_FLAGS0_PCI			0x40

/**
 * struct sbal_sbalf_0 - sbal flags for sbale 0
 * @pci: PCI indicator
 * @cont: data continuation
 * @sbtype: storage-block type (FCP)
 */
struct sbal_sbalf_0 {
	u8	  : 1;
	u8 pci	  : 1;
	u8 cont   : 1;
	u8 sbtype : 2;
	u8	  : 3;
} __attribute__ ((packed));

/**
 * struct sbal_sbalf_1 - sbal flags for sbale 1
 * @key: storage key
 */
struct sbal_sbalf_1 {
	u8     : 4;
	u8 key : 4;
} __attribute__ ((packed));

/**
 * struct sbal_sbalf_14 - sbal flags for sbale 14
 * @erridx: error index
 */
struct sbal_sbalf_14 {
	u8	  : 4;
	u8 erridx : 4;
} __attribute__ ((packed));

/**
 * struct sbal_sbalf_15 - sbal flags for sbale 15
 * @reason: reason for error state
 */
struct sbal_sbalf_15 {
	u8 reason;
} __attribute__ ((packed));

/**
 * union sbal_sbalf - storage block address list flags
 * @i0: sbalf0
 * @i1: sbalf1
 * @i14: sbalf14
 * @i15: sblaf15
 * @value: raw value
 */
union sbal_sbalf {
	struct sbal_sbalf_0  i0;
	struct sbal_sbalf_1  i1;
	struct sbal_sbalf_14 i14;
	struct sbal_sbalf_15 i15;
	u8 value;
};
#define SBAL_SFLAGS0_TYPE_STATUS	0x00
#define SBAL_SFLAGS0_TYPE_WRITE		0x08
#define SBAL_SFLAGS0_TYPE_READ		0x10
#define SBAL_SFLAGS0_TYPE_WRITE_READ	0x18
#define SBAL_SFLAGS0_MORE_SBALS		0x04
#define SBAL_SFLAGS0_COMMAND		0x02
#define SBAL_SFLAGS0_LAST_SBAL		0x00
#define SBAL_SFLAGS0_ONLY_SBAL		SBAL_SFLAGS0_COMMAND
#define SBAL_SFLAGS0_MIDDLE_SBAL	SBAL_SFLAGS0_MORE_SBALS
#define SBAL_SFLAGS0_FIRST_SBAL (SBAL_SFLAGS0_MORE_SBALS | SBAL_SFLAGS0_COMMAND)

/**
 * struct qdio_buffer_element - SBAL entry
 * @flags: flags
 * @eflags: SBAL entry flags
 * @scount: SBAL count
 * @sflags: whole SBAL flags
 * @length: length
 * @addr: address
*/
struct qdio_buffer_element {
	u32 flags;
	u8 eflags;
	/* private: */
	u8 res1;
	/* public: */
	u8 scount;
	u8 sflags;
	u32 length;
#ifdef CONFIG_32BIT
	/* private: */
	void *reserved;
	void *res2;
	/* public: */
#endif
	void *addr;
+42 −52
Original line number Diff line number Diff line
@@ -26,67 +26,60 @@
#include <linux/swap.h>
#include <asm/processor.h>
#include <asm/pgalloc.h>
#include <asm/smp.h>
#include <asm/tlbflush.h>

struct mmu_gather {
	struct mm_struct *mm;
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	struct mmu_table_batch *batch;
#endif
	unsigned int fullmm;
	unsigned int nr_ptes;
	unsigned int nr_pxds;
	unsigned int max;
	void **array;
	void *local[8];
	unsigned int need_flush;
};

static inline void __tlb_alloc_page(struct mmu_gather *tlb)
{
	unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch {
	struct rcu_head		rcu;
	unsigned int		nr;
	void			*tables[0];
};

	if (addr) {
		tlb->array = (void *) addr;
		tlb->max = PAGE_SIZE / sizeof(void *);
	}
}
#define MAX_TABLE_BATCH		\
	((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))

extern void tlb_table_flush(struct mmu_gather *tlb);
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
#endif

static inline void tlb_gather_mmu(struct mmu_gather *tlb,
				  struct mm_struct *mm,
				  unsigned int full_mm_flush)
{
	tlb->mm = mm;
	tlb->max = ARRAY_SIZE(tlb->local);
	tlb->array = tlb->local;
	tlb->fullmm = full_mm_flush;
	tlb->need_flush = 0;
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	tlb->batch = NULL;
#endif
	if (tlb->fullmm)
		__tlb_flush_mm(mm);
	else
		__tlb_alloc_page(tlb);
	tlb->nr_ptes = 0;
	tlb->nr_pxds = tlb->max;
}

static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{
	if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < tlb->max))
	if (!tlb->need_flush)
		return;
	tlb->need_flush = 0;
	__tlb_flush_mm(tlb->mm);
	while (tlb->nr_ptes > 0)
		page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]);
	while (tlb->nr_pxds < tlb->max)
		crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]);
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	tlb_table_flush(tlb);
#endif
}

static inline void tlb_finish_mmu(struct mmu_gather *tlb,
				  unsigned long start, unsigned long end)
{
	tlb_flush_mmu(tlb);

	rcu_table_freelist_finish();

	/* keep the page table cache within bounds */
	check_pgt_cache();

	if (tlb->array != tlb->local)
		free_pages((unsigned long) tlb->array, 0);
}

/*
@@ -112,11 +105,10 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
				unsigned long address)
{
	if (!tlb->fullmm) {
		tlb->array[tlb->nr_ptes++] = pte;
		if (tlb->nr_ptes >= tlb->nr_pxds)
			tlb_flush_mmu(tlb);
	} else
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	if (!tlb->fullmm)
		return page_table_free_rcu(tlb, (unsigned long *) pte);
#endif
	page_table_free(tlb->mm, (unsigned long *) pte);
}

@@ -133,11 +125,10 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
#ifdef __s390x__
	if (tlb->mm->context.asce_limit <= (1UL << 31))
		return;
	if (!tlb->fullmm) {
		tlb->array[--tlb->nr_pxds] = pmd;
		if (tlb->nr_ptes >= tlb->nr_pxds)
			tlb_flush_mmu(tlb);
	} else
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	if (!tlb->fullmm)
		return tlb_remove_table(tlb, pmd);
#endif
	crst_table_free(tlb->mm, (unsigned long *) pmd);
#endif
}
@@ -155,11 +146,10 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
#ifdef __s390x__
	if (tlb->mm->context.asce_limit <= (1UL << 42))
		return;
	if (!tlb->fullmm) {
		tlb->array[--tlb->nr_pxds] = pud;
		if (tlb->nr_ptes >= tlb->nr_pxds)
			tlb_flush_mmu(tlb);
	} else
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
	if (!tlb->fullmm)
		return tlb_remove_table(tlb, pud);
#endif
	crst_table_free(tlb->mm, (unsigned long *) pud);
#endif
}
Loading