Skip to content

Commit 64b3d0e

Browse files
ozbenhpaulusmack
authored andcommitted
powerpc/mm: Rework usage of _PAGE_COHERENT/NO_CACHE/GUARDED
Currently, we never set _PAGE_COHERENT in the PTEs, we just OR it in in the hash code based on some CPU feature bit. We also manipulate _PAGE_NO_CACHE and _PAGE_GUARDED by hand in all sorts of places. This changes the logic so that instead, the PTE now contains _PAGE_COHERENT for all normal RAM pages thay have I = 0 on platforms that need it. The hash code clears it if the feature bit is not set. It also adds some clean accessors to setup various valid combinations of access flags and change various bits of code to use them instead. This should help having the PTE actually containing the bit combinations that we really want. I also removed _PAGE_GUARDED from _PAGE_BASE on 44x and instead set it explicitely from the TLB miss. I will ultimately remove it completely as it appears that it might not be needed after all but in the meantime, having it in the TLB miss makes things a lot easier. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Acked-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
1 parent 7752035 commit 64b3d0e

File tree

9 files changed

+68
-77
lines changed

9 files changed

+68
-77
lines changed

arch/powerpc/include/asm/pgtable-ppc32.h

+17-25
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,10 @@ extern int icache_44x_need_flush;
228228
* - FILE *must* be in the bottom three bits because swap cache
229229
* entries use the top 29 bits for TLB2.
230230
*
231-
* - CACHE COHERENT bit (M) has no effect on PPC440 core, because it
232-
* doesn't support SMP. So we can use this as software bit, like
233-
* DIRTY.
231+
* - CACHE COHERENT bit (M) has no effect on original PPC440 cores,
232+
* because it doesn't support SMP. However, some later 460 variants
233+
* have -some- form of SMP support and so I keep the bit there for
234+
* future use
234235
*
235236
* With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used
236237
* for memory protection related functions (see PTE structure in
@@ -436,20 +437,23 @@ extern int icache_44x_need_flush;
436437
_PAGE_USER | _PAGE_ACCESSED | \
437438
_PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
438439
_PAGE_EXEC | _PAGE_HWEXEC)
440+
439441
/*
440-
* Note: the _PAGE_COHERENT bit automatically gets set in the hardware
441-
* PTE if CONFIG_SMP is defined (hash_page does this); there is no need
442-
* to have it in the Linux PTE, and in fact the bit could be reused for
443-
* another purpose. -- paulus.
442+
* We define 2 sets of base prot bits, one for basic pages (ie,
443+
* cacheable kernel and user pages) and one for non cacheable
444+
* pages. We always set _PAGE_COHERENT when SMP is enabled or
445+
* the processor might need it for DMA coherency.
444446
*/
445-
446-
#ifdef CONFIG_44x
447-
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
447+
#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
448+
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
448449
#else
449450
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
450451
#endif
452+
#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE)
453+
451454
#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE)
452455
#define _PAGE_KERNEL (_PAGE_BASE | _PAGE_SHARED | _PAGE_WRENABLE)
456+
#define _PAGE_KERNEL_NC (_PAGE_BASE_NC | _PAGE_SHARED | _PAGE_WRENABLE)
453457

454458
#ifdef CONFIG_PPC_STD_MMU
455459
/* On standard PPC MMU, no user access implies kernel read/write access,
@@ -459,7 +463,7 @@ extern int icache_44x_need_flush;
459463
#define _PAGE_KERNEL_RO (_PAGE_BASE | _PAGE_SHARED)
460464
#endif
461465

462-
#define _PAGE_IO (_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
466+
#define _PAGE_IO (_PAGE_KERNEL_NC | _PAGE_GUARDED)
463467
#define _PAGE_RAM (_PAGE_KERNEL | _PAGE_HWEXEC)
464468

465469
#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
@@ -552,9 +556,6 @@ static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;
552556
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
553557
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
554558

555-
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
556-
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
557-
558559
static inline pte_t pte_wrprotect(pte_t pte) {
559560
pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
560561
static inline pte_t pte_mkclean(pte_t pte) {
@@ -693,10 +694,11 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
693694
#endif
694695
}
695696

697+
696698
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
697699
pte_t *ptep, pte_t pte)
698700
{
699-
#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
701+
#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) && defined(CONFIG_DEBUG_VM)
700702
WARN_ON(pte_present(*ptep));
701703
#endif
702704
__set_pte_at(mm, addr, ptep, pte);
@@ -760,16 +762,6 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
760762
__changed; \
761763
})
762764

763-
/*
764-
* Macro to mark a page protection value as "uncacheable".
765-
*/
766-
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
767-
768-
struct file;
769-
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
770-
unsigned long size, pgprot_t vma_prot);
771-
#define __HAVE_PHYS_MEM_ACCESS_PROT
772-
773765
#define __HAVE_ARCH_PTE_SAME
774766
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
775767

arch/powerpc/include/asm/pgtable-ppc64.h

-13
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,6 @@ static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
245245
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
246246
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
247247

248-
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
249-
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
250-
251248
static inline pte_t pte_wrprotect(pte_t pte) {
252249
pte_val(pte) &= ~(_PAGE_RW); return pte; }
253250
static inline pte_t pte_mkclean(pte_t pte) {
@@ -405,16 +402,6 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
405402
__changed; \
406403
})
407404

408-
/*
409-
* Macro to mark a page protection value as "uncacheable".
410-
*/
411-
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
412-
413-
struct file;
414-
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
415-
unsigned long size, pgprot_t vma_prot);
416-
#define __HAVE_PHYS_MEM_ACCESS_PROT
417-
418405
#define __HAVE_ARCH_PTE_SAME
419406
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
420407

arch/powerpc/include/asm/pgtable.h

+26
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,32 @@ struct mm_struct;
1616
#endif
1717

1818
#ifndef __ASSEMBLY__
19+
20+
/*
21+
* Macro to mark a page protection value as "uncacheable".
22+
*/
23+
24+
#define _PAGE_CACHE_CTL (_PAGE_COHERENT | _PAGE_GUARDED | _PAGE_NO_CACHE | \
25+
_PAGE_WRITETHRU)
26+
27+
#define pgprot_noncached(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
28+
_PAGE_NO_CACHE | _PAGE_GUARDED))
29+
30+
#define pgprot_noncached_wc(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
31+
_PAGE_NO_CACHE))
32+
33+
#define pgprot_cached(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
34+
_PAGE_COHERENT))
35+
36+
#define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
37+
_PAGE_COHERENT | _PAGE_WRITETHRU))
38+
39+
40+
struct file;
41+
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
42+
unsigned long size, pgprot_t vma_prot);
43+
#define __HAVE_PHYS_MEM_ACCESS_PROT
44+
1945
/*
2046
* ZERO_PAGE is a global shared page that is always zero: used
2147
* for zero-mapped memory areas etc..

arch/powerpc/kernel/head_44x.S

+1
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ finish_tlb_load:
570570
rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */
571571
and r11,r12,r10 /* Mask PTE bits to keep */
572572
andi. r10,r12,_PAGE_USER /* User page ? */
573+
ori r11,r11,_PAGE_GUARDED /* 440 errata, needs G set */
573574
beq 1f /* nope, leave U bits empty */
574575
rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */
575576
1: tlbwe r11,r13,PPC44x_TLB_ATTRIB /* Write ATTRIB */

arch/powerpc/kernel/pci-common.c

+9-15
Original file line numberDiff line numberDiff line change
@@ -370,13 +370,10 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
370370
}
371371

372372
/* XXX would be nice to have a way to ask for write-through */
373-
prot |= _PAGE_NO_CACHE;
374373
if (write_combine)
375-
prot &= ~_PAGE_GUARDED;
374+
return pgprot_noncached_wc(prot);
376375
else
377-
prot |= _PAGE_GUARDED;
378-
379-
return __pgprot(prot);
376+
return pgprot_noncached(prot);
380377
}
381378

382379
/*
@@ -387,19 +384,17 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
387384
pgprot_t pci_phys_mem_access_prot(struct file *file,
388385
unsigned long pfn,
389386
unsigned long size,
390-
pgprot_t protection)
387+
pgprot_t prot)
391388
{
392389
struct pci_dev *pdev = NULL;
393390
struct resource *found = NULL;
394-
unsigned long prot = pgprot_val(protection);
395391
resource_size_t offset = ((resource_size_t)pfn) << PAGE_SHIFT;
396392
int i;
397393

398394
if (page_is_ram(pfn))
399-
return __pgprot(prot);
400-
401-
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
395+
return prot;
402396

397+
prot = pgprot_noncached(prot);
403398
for_each_pci_dev(pdev) {
404399
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
405400
struct resource *rp = &pdev->resource[i];
@@ -420,14 +415,14 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
420415
}
421416
if (found) {
422417
if (found->flags & IORESOURCE_PREFETCH)
423-
prot &= ~_PAGE_GUARDED;
418+
prot = pgprot_noncached_wc(prot);
424419
pci_dev_put(pdev);
425420
}
426421

427422
pr_debug("PCI: Non-PCI map for %llx, prot: %lx\n",
428-
(unsigned long long)offset, prot);
423+
(unsigned long long)offset, pgprot_val(prot));
429424

430-
return __pgprot(prot);
425+
return prot;
431426
}
432427

433428

@@ -583,8 +578,7 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus,
583578
pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset);
584579

585580
vma->vm_pgoff = offset >> PAGE_SHIFT;
586-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
587-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
581+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
588582
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
589583
vma->vm_end - vma->vm_start,
590584
vma->vm_page_prot);

arch/powerpc/mm/hash_low_32.S

+2-2
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,8 @@ _GLOBAL(create_hpte)
323323
ori r8,r8,0xe14 /* clear out reserved bits and M */
324324
andc r8,r5,r8 /* PP = user? (rw&dirty? 2: 3): 0 */
325325
BEGIN_FTR_SECTION
326-
ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */
327-
END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
326+
rlwinm r8,r8,0,~_PAGE_COHERENT /* clear M (coherence not required) */
327+
END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
328328
#ifdef CONFIG_PTE_64BIT
329329
/* Put the XPN bits into the PTE */
330330
rlwimi r8,r10,8,20,22

arch/powerpc/mm/mem.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
102102
return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
103103

104104
if (!page_is_ram(pfn))
105-
vma_prot = __pgprot(pgprot_val(vma_prot)
106-
| _PAGE_GUARDED | _PAGE_NO_CACHE);
105+
vma_prot = pgprot_noncached(vma_prot);
106+
107107
return vma_prot;
108108
}
109109
EXPORT_SYMBOL(phys_mem_access_prot);

arch/powerpc/platforms/cell/spufs/file.c

+9-18
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,10 @@ spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
273273
return VM_FAULT_NOPAGE;
274274

275275
if (ctx->state == SPU_STATE_SAVED) {
276-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
277-
& ~_PAGE_NO_CACHE);
276+
vma->vm_page_prot = pgprot_cached(vma->vm_page_prot);
278277
pfn = vmalloc_to_pfn(ctx->csa.lscsa->ls + offset);
279278
} else {
280-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
281-
| _PAGE_NO_CACHE);
279+
vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
282280
pfn = (ctx->spu->local_store_phys + offset) >> PAGE_SHIFT;
283281
}
284282
vm_insert_pfn(vma, address, pfn);
@@ -338,8 +336,7 @@ static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
338336
return -EINVAL;
339337

340338
vma->vm_flags |= VM_IO | VM_PFNMAP;
341-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
342-
| _PAGE_NO_CACHE);
339+
vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
343340

344341
vma->vm_ops = &spufs_mem_mmap_vmops;
345342
return 0;
@@ -452,8 +449,7 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
452449
return -EINVAL;
453450

454451
vma->vm_flags |= VM_IO | VM_PFNMAP;
455-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
456-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
452+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
457453

458454
vma->vm_ops = &spufs_cntl_mmap_vmops;
459455
return 0;
@@ -1155,8 +1151,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
11551151
return -EINVAL;
11561152

11571153
vma->vm_flags |= VM_IO | VM_PFNMAP;
1158-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1159-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
1154+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
11601155

11611156
vma->vm_ops = &spufs_signal1_mmap_vmops;
11621157
return 0;
@@ -1292,8 +1287,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
12921287
return -EINVAL;
12931288

12941289
vma->vm_flags |= VM_IO | VM_PFNMAP;
1295-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1296-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
1290+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
12971291

12981292
vma->vm_ops = &spufs_signal2_mmap_vmops;
12991293
return 0;
@@ -1414,8 +1408,7 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
14141408
return -EINVAL;
14151409

14161410
vma->vm_flags |= VM_IO | VM_PFNMAP;
1417-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1418-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
1411+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
14191412

14201413
vma->vm_ops = &spufs_mss_mmap_vmops;
14211414
return 0;
@@ -1476,8 +1469,7 @@ static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
14761469
return -EINVAL;
14771470

14781471
vma->vm_flags |= VM_IO | VM_PFNMAP;
1479-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1480-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
1472+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
14811473

14821474
vma->vm_ops = &spufs_psmap_mmap_vmops;
14831475
return 0;
@@ -1536,8 +1528,7 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
15361528
return -EINVAL;
15371529

15381530
vma->vm_flags |= VM_IO | VM_PFNMAP;
1539-
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1540-
| _PAGE_NO_CACHE | _PAGE_GUARDED);
1531+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
15411532

15421533
vma->vm_ops = &spufs_mfc_mmap_vmops;
15431534
return 0;

drivers/video/controlfb.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,10 @@ static int controlfb_mmap(struct fb_info *info,
298298
return -EINVAL;
299299
start = info->fix.mmio_start;
300300
len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len);
301-
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
301+
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
302302
} else {
303303
/* framebuffer */
304-
pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU;
304+
vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
305305
}
306306
start &= PAGE_MASK;
307307
if ((vma->vm_end - vma->vm_start + off) > len)

0 commit comments

Comments
 (0)