@@ -257,41 +257,148 @@ void slb_vmalloc_update(void)
257
257
slb_flush_and_rebolt ();
258
258
}
259
259
260
- /* Helper function to compare esids. There are four cases to handle.
261
- * 1. The system is not 1T segment size capable. Use the GET_ESID compare.
262
- * 2. The system is 1T capable, both addresses are < 1T, use the GET_ESID compare.
263
- * 3. The system is 1T capable, only one of the two addresses is > 1T. This is not a match.
264
- * 4. The system is 1T capable, both addresses are > 1T, use the GET_ESID_1T macro to compare.
265
- */
266
- static inline int esids_match (unsigned long addr1 , unsigned long addr2 )
260
+ static bool preload_hit (struct thread_info * ti , unsigned long esid )
267
261
{
268
- int esid_1t_count ;
262
+ unsigned char i ;
269
263
270
- /* System is not 1T segment size capable. */
271
- if (!mmu_has_feature (MMU_FTR_1T_SEGMENT ))
272
- return (GET_ESID (addr1 ) == GET_ESID (addr2 ));
264
+ for (i = 0 ; i < ti -> slb_preload_nr ; i ++ ) {
265
+ unsigned char idx ;
266
+
267
+ idx = (ti -> slb_preload_tail + i ) % SLB_PRELOAD_NR ;
268
+ if (esid == ti -> slb_preload_esid [idx ])
269
+ return true;
270
+ }
271
+ return false;
272
+ }
273
+
274
+ static bool preload_add (struct thread_info * ti , unsigned long ea )
275
+ {
276
+ unsigned char idx ;
277
+ unsigned long esid ;
278
+
279
+ if (mmu_has_feature (MMU_FTR_1T_SEGMENT )) {
280
+ /* EAs are stored >> 28 so 256MB segments don't need clearing */
281
+ if (ea & ESID_MASK_1T )
282
+ ea &= ESID_MASK_1T ;
283
+ }
273
284
274
- esid_1t_count = (((addr1 >> SID_SHIFT_1T ) != 0 ) +
275
- ((addr2 >> SID_SHIFT_1T ) != 0 ));
285
+ esid = ea >> SID_SHIFT ;
276
286
277
- /* both addresses are < 1T */
278
- if (esid_1t_count == 0 )
279
- return (GET_ESID (addr1 ) == GET_ESID (addr2 ));
287
+ if (preload_hit (ti , esid ))
288
+ return false;
280
289
281
- /* One address < 1T, the other > 1T. Not a match */
282
- if (esid_1t_count == 1 )
283
- return 0 ;
290
+ idx = (ti -> slb_preload_tail + ti -> slb_preload_nr ) % SLB_PRELOAD_NR ;
291
+ ti -> slb_preload_esid [idx ] = esid ;
292
+ if (ti -> slb_preload_nr == SLB_PRELOAD_NR )
293
+ ti -> slb_preload_tail = (ti -> slb_preload_tail + 1 ) % SLB_PRELOAD_NR ;
294
+ else
295
+ ti -> slb_preload_nr ++ ;
284
296
285
- /* Both addresses are > 1T. */
286
- return (GET_ESID_1T (addr1 ) == GET_ESID_1T (addr2 ));
297
+ return true;
287
298
}
288
299
300
+ static void preload_age (struct thread_info * ti )
301
+ {
302
+ if (!ti -> slb_preload_nr )
303
+ return ;
304
+ ti -> slb_preload_nr -- ;
305
+ ti -> slb_preload_tail = (ti -> slb_preload_tail + 1 ) % SLB_PRELOAD_NR ;
306
+ }
307
+
308
+ void slb_setup_new_exec (void )
309
+ {
310
+ struct thread_info * ti = current_thread_info ();
311
+ struct mm_struct * mm = current -> mm ;
312
+ unsigned long exec = 0x10000000 ;
313
+
314
+ WARN_ON (irqs_disabled ());
315
+
316
+ /*
317
+ * preload cache can only be used to determine whether a SLB
318
+ * entry exists if it does not start to overflow.
319
+ */
320
+ if (ti -> slb_preload_nr + 2 > SLB_PRELOAD_NR )
321
+ return ;
322
+
323
+ hard_irq_disable ();
324
+
325
+ /*
326
+ * We have no good place to clear the slb preload cache on exec,
327
+ * flush_thread is about the earliest arch hook but that happens
328
+ * after we switch to the mm and have aleady preloaded the SLBEs.
329
+ *
330
+ * For the most part that's probably okay to use entries from the
331
+ * previous exec, they will age out if unused. It may turn out to
332
+ * be an advantage to clear the cache before switching to it,
333
+ * however.
334
+ */
335
+
336
+ /*
337
+ * preload some userspace segments into the SLB.
338
+ * Almost all 32 and 64bit PowerPC executables are linked at
339
+ * 0x10000000 so it makes sense to preload this segment.
340
+ */
341
+ if (!is_kernel_addr (exec )) {
342
+ if (preload_add (ti , exec ))
343
+ slb_allocate_user (mm , exec );
344
+ }
345
+
346
+ /* Libraries and mmaps. */
347
+ if (!is_kernel_addr (mm -> mmap_base )) {
348
+ if (preload_add (ti , mm -> mmap_base ))
349
+ slb_allocate_user (mm , mm -> mmap_base );
350
+ }
351
+
352
+ /* see switch_slb */
353
+ asm volatile ("isync" : : : "memory" );
354
+
355
+ local_irq_enable ();
356
+ }
357
+
358
+ void preload_new_slb_context (unsigned long start , unsigned long sp )
359
+ {
360
+ struct thread_info * ti = current_thread_info ();
361
+ struct mm_struct * mm = current -> mm ;
362
+ unsigned long heap = mm -> start_brk ;
363
+
364
+ WARN_ON (irqs_disabled ());
365
+
366
+ /* see above */
367
+ if (ti -> slb_preload_nr + 3 > SLB_PRELOAD_NR )
368
+ return ;
369
+
370
+ hard_irq_disable ();
371
+
372
+ /* Userspace entry address. */
373
+ if (!is_kernel_addr (start )) {
374
+ if (preload_add (ti , start ))
375
+ slb_allocate_user (mm , start );
376
+ }
377
+
378
+ /* Top of stack, grows down. */
379
+ if (!is_kernel_addr (sp )) {
380
+ if (preload_add (ti , sp ))
381
+ slb_allocate_user (mm , sp );
382
+ }
383
+
384
+ /* Bottom of heap, grows up. */
385
+ if (heap && !is_kernel_addr (heap )) {
386
+ if (preload_add (ti , heap ))
387
+ slb_allocate_user (mm , heap );
388
+ }
389
+
390
+ /* see switch_slb */
391
+ asm volatile ("isync" : : : "memory" );
392
+
393
+ local_irq_enable ();
394
+ }
395
+
396
+
289
397
/* Flush all user entries from the segment table of the current processor. */
290
398
void switch_slb (struct task_struct * tsk , struct mm_struct * mm )
291
399
{
292
- unsigned long pc = KSTK_EIP (tsk );
293
- unsigned long stack = KSTK_ESP (tsk );
294
- unsigned long exec_base ;
400
+ struct thread_info * ti = task_thread_info (tsk );
401
+ unsigned char i ;
295
402
296
403
/*
297
404
* We need interrupts hard-disabled here, not just soft-disabled,
@@ -300,23 +407,22 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
300
407
* which would update the slb_cache/slb_cache_ptr fields in the PACA.
301
408
*/
302
409
hard_irq_disable ();
410
+ asm volatile ("isync" : : : "memory" );
303
411
if (cpu_has_feature (CPU_FTR_ARCH_300 )) {
304
412
/*
305
413
* SLBIA IH=3 invalidates all Class=1 SLBEs and their
306
414
* associated lookaside structures, which matches what
307
415
* switch_slb wants. So ARCH_300 does not use the slb
308
416
* cache.
309
417
*/
310
- asm volatile ("isync ; " PPC_SLBIA (3 )" ; isync " );
418
+ asm volatile (PPC_SLBIA (3 ));
311
419
} else {
312
420
unsigned long offset = get_paca ()-> slb_cache_ptr ;
313
421
314
422
if (!mmu_has_feature (MMU_FTR_NO_SLBIE_B ) &&
315
423
offset <= SLB_CACHE_ENTRIES ) {
316
424
unsigned long slbie_data = 0 ;
317
- int i ;
318
425
319
- asm volatile ("isync" : : : "memory" );
320
426
for (i = 0 ; i < offset ; i ++ ) {
321
427
/* EA */
322
428
slbie_data = (unsigned long )
@@ -331,16 +437,14 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
331
437
if (!cpu_has_feature (CPU_FTR_ARCH_207S ) && offset == 1 )
332
438
asm volatile ("slbie %0" : : "r" (slbie_data ));
333
439
334
- asm volatile ("isync" : : : "memory" );
335
440
} else {
336
441
struct slb_shadow * p = get_slb_shadow ();
337
442
unsigned long ksp_esid_data =
338
443
be64_to_cpu (p -> save_area [KSTACK_INDEX ].esid );
339
444
unsigned long ksp_vsid_data =
340
445
be64_to_cpu (p -> save_area [KSTACK_INDEX ].vsid );
341
446
342
- asm volatile ("isync\n"
343
- PPC_SLBIA (1 ) "\n"
447
+ asm volatile (PPC_SLBIA (1 ) "\n"
344
448
"slbmte %0,%1\n"
345
449
"isync"
346
450
:: "r" (ksp_vsid_data ),
@@ -356,24 +460,35 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
356
460
copy_mm_to_paca (mm );
357
461
358
462
/*
359
- * preload some userspace segments into the SLB.
360
- * Almost all 32 and 64bit PowerPC executables are linked at
361
- * 0x10000000 so it makes sense to preload this segment.
463
+ * We gradually age out SLBs after a number of context switches to
464
+ * reduce reload overhead of unused entries (like we do with FP/VEC
465
+ * reload). Each time we wrap 256 switches, take an entry out of the
466
+ * SLB preload cache.
362
467
*/
363
- exec_base = 0x10000000 ;
468
+ tsk -> thread .load_slb ++ ;
469
+ if (!tsk -> thread .load_slb ) {
470
+ unsigned long pc = KSTK_EIP (tsk );
364
471
365
- if (is_kernel_addr (pc ) || is_kernel_addr (stack ) ||
366
- is_kernel_addr (exec_base ))
367
- return ;
472
+ preload_age (ti );
473
+ preload_add (ti , pc );
474
+ }
475
+
476
+ for (i = 0 ; i < ti -> slb_preload_nr ; i ++ ) {
477
+ unsigned char idx ;
478
+ unsigned long ea ;
368
479
369
- slb_allocate_user (mm , pc );
480
+ idx = (ti -> slb_preload_tail + i ) % SLB_PRELOAD_NR ;
481
+ ea = (unsigned long )ti -> slb_preload_esid [idx ] << SID_SHIFT ;
370
482
371
- if (! esids_match ( pc , stack ))
372
- slb_allocate_user ( mm , stack );
483
+ slb_allocate_user ( mm , ea );
484
+ }
373
485
374
- if (!esids_match (pc , exec_base ) &&
375
- !esids_match (stack , exec_base ))
376
- slb_allocate_user (mm , exec_base );
486
+ /*
487
+ * Synchronize slbmte preloads with possible subsequent user memory
488
+ * address accesses by the kernel (user mode won't happen until
489
+ * rfid, which is safe).
490
+ */
491
+ asm volatile ("isync" : : : "memory" );
377
492
}
378
493
379
494
void slb_set_size (u16 size )
@@ -642,11 +757,16 @@ long do_slb_fault(struct pt_regs *regs, unsigned long ea)
642
757
return slb_allocate_kernel (ea , id );
643
758
} else {
644
759
struct mm_struct * mm = current -> mm ;
760
+ long err ;
645
761
646
762
if (unlikely (!mm ))
647
763
return - EFAULT ;
648
764
649
- return slb_allocate_user (mm , ea );
765
+ err = slb_allocate_user (mm , ea );
766
+ if (!err )
767
+ preload_add (current_thread_info (), ea );
768
+
769
+ return err ;
650
770
}
651
771
}
652
772
0 commit comments