Skip to content

Commit

Permalink
Merge branch 'tlb-flushing' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/s390/linux into kernelorgnext

base patches for tlb flushing optimizations
  • Loading branch information
Christian Borntraeger committed Jul 25, 2017
2 parents 520eccd + cd774b9 commit 962734f
Show file tree
Hide file tree
Showing 13 changed files with 411 additions and 81 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/page-states.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define ESSA_SET_POT_VOLATILE 4
#define ESSA_SET_STABLE_RESIDENT 5
#define ESSA_SET_STABLE_IF_RESIDENT 6
#define ESSA_SET_STABLE_NODAT 7

#define ESSA_MAX ESSA_SET_STABLE_IF_RESIDENT

Expand Down
3 changes: 3 additions & 0 deletions arch/s390/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ static inline int page_reset_referenced(unsigned long addr)
struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);
void arch_set_page_dat(struct page *page, int order);
void arch_set_page_nodat(struct page *page, int order);
int arch_test_page_nodat(struct page *page);
void arch_set_page_states(int make_stable);

static inline int devmem_is_allowed(unsigned long pfn)
Expand Down
88 changes: 67 additions & 21 deletions arch/s390/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ static inline int is_module_addr(void *addr)

/* Guest Page State used for virtualization */
#define _PGSTE_GPS_ZERO 0x0000000080000000UL
#define _PGSTE_GPS_NODAT 0x0000000040000000UL
#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL
#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
Expand Down Expand Up @@ -952,15 +953,30 @@ static inline pte_t pte_mkhuge(pte_t pte)
#define IPTE_GLOBAL 0
#define IPTE_LOCAL 1

static inline void __ptep_ipte(unsigned long address, pte_t *ptep, int local)
#define IPTE_NODAT 0x400
#define IPTE_GUEST_ASCE 0x800

static inline void __ptep_ipte(unsigned long address, pte_t *ptep,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long pto = (unsigned long) ptep;

/* Invalidation + TLB flush for the pte */
if (__builtin_constant_p(opt) && opt == 0) {
/* Invalidation + TLB flush for the pte */
asm volatile(
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
[m4] "i" (local));
return;
}

/* Invalidate ptes with options + TLB flush of the ptes */
opt = opt | (asce & _ASCE_ORIGIN);
asm volatile(
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
[m4] "i" (local));
" .insn rrf,0xb2210000,%[r1],%[r2],%[r3],%[m4]"
: [r2] "+a" (address), [r3] "+a" (opt)
: [r1] "a" (pto), [m4] "i" (local) : "memory");
}

static inline void __ptep_ipte_range(unsigned long address, int nr,
Expand Down Expand Up @@ -1341,31 +1357,61 @@ static inline void __pmdp_csp(pmd_t *pmdp)
#define IDTE_GLOBAL 0
#define IDTE_LOCAL 1

static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp, int local)
#define IDTE_PTOA 0x0800
#define IDTE_NODAT 0x1000
#define IDTE_GUEST_ASCE 0x2000

static inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long sto;

sto = (unsigned long) pmdp - pmd_index(address) * sizeof(pmd_t);
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((address & HPAGE_MASK)),
[m4] "i" (local)
: "cc" );
sto = (unsigned long) pmdp - pmd_index(addr) * sizeof(pmd_t);
if (__builtin_constant_p(opt) && opt == 0) {
/* flush without guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK)),
[m4] "i" (local)
: "cc" );
} else {
/* flush with guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK) | opt),
[r3] "a" (asce), [m4] "i" (local)
: "cc" );
}
}

static inline void __pudp_idte(unsigned long address, pud_t *pudp, int local)
static inline void __pudp_idte(unsigned long addr, pud_t *pudp,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long r3o;

r3o = (unsigned long) pudp - pud_index(address) * sizeof(pud_t);
r3o = (unsigned long) pudp - pud_index(addr) * sizeof(pud_t);
r3o |= _ASCE_TYPE_REGION3;
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((address & PUD_MASK)),
[m4] "i" (local)
: "cc");
if (__builtin_constant_p(opt) && opt == 0) {
/* flush without guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK)),
[m4] "i" (local)
: "cc");
} else {
/* flush with guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK) | opt),
[r3] "a" (asce), [m4] "i" (local)
: "cc" );
}
}

pmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
Expand Down
9 changes: 6 additions & 3 deletions arch/s390/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
#define MACHINE_FLAG_TE _BITUL(11)
#define MACHINE_FLAG_TLB_LC _BITUL(12)
#define MACHINE_FLAG_VX _BITUL(13)
#define MACHINE_FLAG_NX _BITUL(14)
#define MACHINE_FLAG_GS _BITUL(15)
#define MACHINE_FLAG_TLB_GUEST _BITUL(14)
#define MACHINE_FLAG_NX _BITUL(15)
#define MACHINE_FLAG_GS _BITUL(16)

#define LPP_MAGIC _BITUL(31)
#define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL)
Expand Down Expand Up @@ -68,6 +69,7 @@ extern void detect_memory_memblock(void);
#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
#define MACHINE_HAS_TLB_GUEST (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_GUEST)
#define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX)
#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS)

Expand Down Expand Up @@ -106,7 +108,8 @@ extern void pfault_fini(void);

void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);

extern void cmma_init(void);
void cmma_init(void);
void cmma_init_nodat(void);

extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
Expand Down
7 changes: 6 additions & 1 deletion arch/s390/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ static inline void __tlb_flush_local(void)
*/
static inline void __tlb_flush_idte(unsigned long asce)
{
unsigned long opt;

opt = IDTE_PTOA;
if (MACHINE_HAS_TLB_GUEST)
opt |= IDTE_GUEST_ASCE;
/* Global TLB flush for the mm */
asm volatile(
" .insn rrf,0xb98e0000,0,%0,%1,0"
: : "a" (2048), "a" (asce) : "cc");
: : "a" (opt), "a" (asce) : "cc");
}

#ifdef CONFIG_SMP
Expand Down
24 changes: 19 additions & 5 deletions arch/s390/kernel/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@ int page_key_alloc(unsigned long pages)
*/
void page_key_read(unsigned long *pfn)
{
struct page *page;
unsigned long addr;

addr = (unsigned long) page_address(pfn_to_page(*pfn));
*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
unsigned char key;

page = pfn_to_page(*pfn);
addr = (unsigned long) page_address(page);
key = (unsigned char) page_get_storage_key(addr) & 0x7f;
if (arch_test_page_nodat(page))
key |= 0x80;
*(unsigned char *) pfn = key;
}

/*
Expand All @@ -126,8 +132,16 @@ void page_key_memorize(unsigned long *pfn)
*/
void page_key_write(void *address)
{
page_set_storage_key((unsigned long) address,
page_key_rp->data[page_key_rx], 0);
struct page *page;
unsigned char key;

key = page_key_rp->data[page_key_rx];
page_set_storage_key((unsigned long) address, key & 0x7f, 0);
page = virt_to_page(address);
if (key & 0x80)
arch_set_page_nodat(page, 0);
else
arch_set_page_dat(page, 0);
if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
return;
page_key_rp = page_key_rp->next;
Expand Down
2 changes: 2 additions & 0 deletions arch/s390/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore)
page_frame = get_zeroed_page(GFP_KERNEL);
if (!segment_table || !page_table || !page_frame)
goto out;
arch_set_page_dat(virt_to_page(segment_table), SEGMENT_ORDER);
arch_set_page_dat(virt_to_page(page_table), 0);

/* Initialize per-cpu vdso data page */
vd = (struct vdso_per_cpu_data *) page_frame;
Expand Down
2 changes: 2 additions & 0 deletions arch/s390/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ void __init mem_init(void)
free_all_bootmem();
setup_zero_pages(); /* Setup zeroed pages. */

cmma_init_nodat();

mem_init_print_info(NULL);
}

Expand Down
Loading

0 comments on commit 962734f

Please sign in to comment.