Skip to content

Commit 962734f

Browse files
committed
Merge branch 'tlb-flushing' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux into kernelorgnext
base patches for tlb flushing optimizations
2 parents 520eccd + cd774b9 commit 962734f

File tree

13 files changed

+411
-81
lines changed

13 files changed

+411
-81
lines changed

arch/s390/include/asm/page-states.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define ESSA_SET_POT_VOLATILE 4
1414
#define ESSA_SET_STABLE_RESIDENT 5
1515
#define ESSA_SET_STABLE_IF_RESIDENT 6
16+
#define ESSA_SET_STABLE_NODAT 7
1617

1718
#define ESSA_MAX ESSA_SET_STABLE_IF_RESIDENT
1819

arch/s390/include/asm/page.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ static inline int page_reset_referenced(unsigned long addr)
133133
struct page;
134134
void arch_free_page(struct page *page, int order);
135135
void arch_alloc_page(struct page *page, int order);
136+
void arch_set_page_dat(struct page *page, int order);
137+
void arch_set_page_nodat(struct page *page, int order);
138+
int arch_test_page_nodat(struct page *page);
136139
void arch_set_page_states(int make_stable);
137140

138141
static inline int devmem_is_allowed(unsigned long pfn)

arch/s390/include/asm/pgtable.h

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ static inline int is_module_addr(void *addr)
376376

377377
/* Guest Page State used for virtualization */
378378
#define _PGSTE_GPS_ZERO 0x0000000080000000UL
379+
#define _PGSTE_GPS_NODAT 0x0000000040000000UL
379380
#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL
380381
#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
381382
#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
@@ -952,15 +953,30 @@ static inline pte_t pte_mkhuge(pte_t pte)
952953
#define IPTE_GLOBAL 0
953954
#define IPTE_LOCAL 1
954955

955-
static inline void __ptep_ipte(unsigned long address, pte_t *ptep, int local)
956+
#define IPTE_NODAT 0x400
957+
#define IPTE_GUEST_ASCE 0x800
958+
959+
static inline void __ptep_ipte(unsigned long address, pte_t *ptep,
960+
unsigned long opt, unsigned long asce,
961+
int local)
956962
{
957963
unsigned long pto = (unsigned long) ptep;
958964

959-
/* Invalidation + TLB flush for the pte */
965+
if (__builtin_constant_p(opt) && opt == 0) {
966+
/* Invalidation + TLB flush for the pte */
967+
asm volatile(
968+
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
969+
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
970+
[m4] "i" (local));
971+
return;
972+
}
973+
974+
/* Invalidate ptes with options + TLB flush of the ptes */
975+
opt = opt | (asce & _ASCE_ORIGIN);
960976
asm volatile(
961-
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
962-
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
963-
[m4] "i" (local));
977+
" .insn rrf,0xb2210000,%[r1],%[r2],%[r3],%[m4]"
978+
: [r2] "+a" (address), [r3] "+a" (opt)
979+
: [r1] "a" (pto), [m4] "i" (local) : "memory");
964980
}
965981

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

1344-
static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp, int local)
1360+
#define IDTE_PTOA 0x0800
1361+
#define IDTE_NODAT 0x1000
1362+
#define IDTE_GUEST_ASCE 0x2000
1363+
1364+
static inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp,
1365+
unsigned long opt, unsigned long asce,
1366+
int local)
13451367
{
13461368
unsigned long sto;
13471369

1348-
sto = (unsigned long) pmdp - pmd_index(address) * sizeof(pmd_t);
1349-
asm volatile(
1350-
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
1351-
: "+m" (*pmdp)
1352-
: [r1] "a" (sto), [r2] "a" ((address & HPAGE_MASK)),
1353-
[m4] "i" (local)
1354-
: "cc" );
1370+
sto = (unsigned long) pmdp - pmd_index(addr) * sizeof(pmd_t);
1371+
if (__builtin_constant_p(opt) && opt == 0) {
1372+
/* flush without guest asce */
1373+
asm volatile(
1374+
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
1375+
: "+m" (*pmdp)
1376+
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK)),
1377+
[m4] "i" (local)
1378+
: "cc" );
1379+
} else {
1380+
/* flush with guest asce */
1381+
asm volatile(
1382+
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
1383+
: "+m" (*pmdp)
1384+
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK) | opt),
1385+
[r3] "a" (asce), [m4] "i" (local)
1386+
: "cc" );
1387+
}
13551388
}
13561389

1357-
static inline void __pudp_idte(unsigned long address, pud_t *pudp, int local)
1390+
static inline void __pudp_idte(unsigned long addr, pud_t *pudp,
1391+
unsigned long opt, unsigned long asce,
1392+
int local)
13581393
{
13591394
unsigned long r3o;
13601395

1361-
r3o = (unsigned long) pudp - pud_index(address) * sizeof(pud_t);
1396+
r3o = (unsigned long) pudp - pud_index(addr) * sizeof(pud_t);
13621397
r3o |= _ASCE_TYPE_REGION3;
1363-
asm volatile(
1364-
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
1365-
: "+m" (*pudp)
1366-
: [r1] "a" (r3o), [r2] "a" ((address & PUD_MASK)),
1367-
[m4] "i" (local)
1368-
: "cc");
1398+
if (__builtin_constant_p(opt) && opt == 0) {
1399+
/* flush without guest asce */
1400+
asm volatile(
1401+
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
1402+
: "+m" (*pudp)
1403+
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK)),
1404+
[m4] "i" (local)
1405+
: "cc");
1406+
} else {
1407+
/* flush with guest asce */
1408+
asm volatile(
1409+
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
1410+
: "+m" (*pudp)
1411+
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK) | opt),
1412+
[r3] "a" (asce), [m4] "i" (local)
1413+
: "cc" );
1414+
}
13691415
}
13701416

13711417
pmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t);

arch/s390/include/asm/setup.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
#define MACHINE_FLAG_TE _BITUL(11)
3030
#define MACHINE_FLAG_TLB_LC _BITUL(12)
3131
#define MACHINE_FLAG_VX _BITUL(13)
32-
#define MACHINE_FLAG_NX _BITUL(14)
33-
#define MACHINE_FLAG_GS _BITUL(15)
32+
#define MACHINE_FLAG_TLB_GUEST _BITUL(14)
33+
#define MACHINE_FLAG_NX _BITUL(15)
34+
#define MACHINE_FLAG_GS _BITUL(16)
3435

3536
#define LPP_MAGIC _BITUL(31)
3637
#define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL)
@@ -68,6 +69,7 @@ extern void detect_memory_memblock(void);
6869
#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
6970
#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
7071
#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
72+
#define MACHINE_HAS_TLB_GUEST (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_GUEST)
7173
#define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX)
7274
#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS)
7375

@@ -106,7 +108,8 @@ extern void pfault_fini(void);
106108

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

109-
extern void cmma_init(void);
111+
void cmma_init(void);
112+
void cmma_init_nodat(void);
110113

111114
extern void (*_machine_restart)(char *command);
112115
extern void (*_machine_halt)(void);

arch/s390/include/asm/tlbflush.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ static inline void __tlb_flush_local(void)
2020
*/
2121
static inline void __tlb_flush_idte(unsigned long asce)
2222
{
23+
unsigned long opt;
24+
25+
opt = IDTE_PTOA;
26+
if (MACHINE_HAS_TLB_GUEST)
27+
opt |= IDTE_GUEST_ASCE;
2328
/* Global TLB flush for the mm */
2429
asm volatile(
2530
" .insn rrf,0xb98e0000,0,%0,%1,0"
26-
: : "a" (2048), "a" (asce) : "cc");
31+
: : "a" (opt), "a" (asce) : "cc");
2732
}
2833

2934
#ifdef CONFIG_SMP

arch/s390/kernel/suspend.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,16 @@ int page_key_alloc(unsigned long pages)
9898
*/
9999
void page_key_read(unsigned long *pfn)
100100
{
101+
struct page *page;
101102
unsigned long addr;
102-
103-
addr = (unsigned long) page_address(pfn_to_page(*pfn));
104-
*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
103+
unsigned char key;
104+
105+
page = pfn_to_page(*pfn);
106+
addr = (unsigned long) page_address(page);
107+
key = (unsigned char) page_get_storage_key(addr) & 0x7f;
108+
if (arch_test_page_nodat(page))
109+
key |= 0x80;
110+
*(unsigned char *) pfn = key;
105111
}
106112

107113
/*
@@ -126,8 +132,16 @@ void page_key_memorize(unsigned long *pfn)
126132
*/
127133
void page_key_write(void *address)
128134
{
129-
page_set_storage_key((unsigned long) address,
130-
page_key_rp->data[page_key_rx], 0);
135+
struct page *page;
136+
unsigned char key;
137+
138+
key = page_key_rp->data[page_key_rx];
139+
page_set_storage_key((unsigned long) address, key & 0x7f, 0);
140+
page = virt_to_page(address);
141+
if (key & 0x80)
142+
arch_set_page_nodat(page, 0);
143+
else
144+
arch_set_page_dat(page, 0);
131145
if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
132146
return;
133147
page_key_rp = page_key_rp->next;

arch/s390/kernel/vdso.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore)
157157
page_frame = get_zeroed_page(GFP_KERNEL);
158158
if (!segment_table || !page_table || !page_frame)
159159
goto out;
160+
arch_set_page_dat(virt_to_page(segment_table), SEGMENT_ORDER);
161+
arch_set_page_dat(virt_to_page(page_table), 0);
160162

161163
/* Initialize per-cpu vdso data page */
162164
vd = (struct vdso_per_cpu_data *) page_frame;

arch/s390/mm/init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ void __init mem_init(void)
137137
free_all_bootmem();
138138
setup_zero_pages(); /* Setup zeroed pages. */
139139

140+
cmma_init_nodat();
141+
140142
mem_init_print_info(NULL);
141143
}
142144

0 commit comments

Comments
 (0)