Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocxl: Initiate a TLB invalidate command

When a TLB Invalidate is required for the Logical Partition, the following
sequence has to be performed:

1. Load MMIO ATSD AVA register with the necessary value, if required.
2. Write the MMIO ATSD launch register to initiate the TLB Invalidate
command.
3. Poll the MMIO ATSD status register to determine when the TLB Invalidate
has been completed.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Acked-by: Frederic Barrat <fbarrat@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201125155013.39955-3-clombard@linux.vnet.ibm.com

authored by

Christophe Lombard and committed by
Michael Ellerman
19b311ca fc1347b5

+120
+51
arch/powerpc/include/asm/pnv-ocxl.h
··· 3 3 #ifndef _ASM_PNV_OCXL_H 4 4 #define _ASM_PNV_OCXL_H 5 5 6 + #include <linux/bitfield.h> 6 7 #include <linux/pci.h> 7 8 8 9 #define PNV_OCXL_TL_MAX_TEMPLATE 63 9 10 #define PNV_OCXL_TL_BITS_PER_RATE 4 10 11 #define PNV_OCXL_TL_RATE_BUF_SIZE ((PNV_OCXL_TL_MAX_TEMPLATE+1) * PNV_OCXL_TL_BITS_PER_RATE / 8) 12 + 13 + #define PNV_OCXL_ATSD_TIMEOUT 1 14 + 15 + /* TLB Management Instructions */ 16 + #define PNV_OCXL_ATSD_LNCH 0x00 17 + /* Radix Invalidate */ 18 + #define PNV_OCXL_ATSD_LNCH_R PPC_BIT(0) 19 + /* Radix Invalidation Control 20 + * 0b00 Just invalidate TLB. 21 + * 0b01 Invalidate just Page Walk Cache. 22 + * 0b10 Invalidate TLB, Page Walk Cache, and any 23 + * caching of Partition and Process Table Entries. 24 + */ 25 + #define PNV_OCXL_ATSD_LNCH_RIC PPC_BITMASK(1, 2) 26 + /* Number and Page Size of translations to be invalidated */ 27 + #define PNV_OCXL_ATSD_LNCH_LP PPC_BITMASK(3, 10) 28 + /* Invalidation Criteria 29 + * 0b00 Invalidate just the target VA. 30 + * 0b01 Invalidate matching PID. 31 + */ 32 + #define PNV_OCXL_ATSD_LNCH_IS PPC_BITMASK(11, 12) 33 + /* 0b1: Process Scope, 0b0: Partition Scope */ 34 + #define PNV_OCXL_ATSD_LNCH_PRS PPC_BIT(13) 35 + /* Invalidation Flag */ 36 + #define PNV_OCXL_ATSD_LNCH_B PPC_BIT(14) 37 + /* Actual Page Size to be invalidated 38 + * 000 4KB 39 + * 101 64KB 40 + * 001 2MB 41 + * 010 1GB 42 + */ 43 + #define PNV_OCXL_ATSD_LNCH_AP PPC_BITMASK(15, 17) 44 + /* Defines the large page select 45 + * L=0b0 for 4KB pages 46 + * L=0b1 for large pages) 47 + */ 48 + #define PNV_OCXL_ATSD_LNCH_L PPC_BIT(18) 49 + /* Process ID */ 50 + #define PNV_OCXL_ATSD_LNCH_PID PPC_BITMASK(19, 38) 51 + /* NoFlush – Assumed to be 0b0 */ 52 + #define PNV_OCXL_ATSD_LNCH_F PPC_BIT(39) 53 + #define PNV_OCXL_ATSD_LNCH_OCAPI_SLBI PPC_BIT(40) 54 + #define PNV_OCXL_ATSD_LNCH_OCAPI_SINGLETON PPC_BIT(41) 55 + #define PNV_OCXL_ATSD_AVA 0x08 56 + #define PNV_OCXL_ATSD_AVA_AVA PPC_BITMASK(0, 51) 57 + #define PNV_OCXL_ATSD_STAT 0x10 11 58 12 59 int pnv_ocxl_get_actag(struct pci_dev *dev, u16 *base, u16 *enabled, u16 *supported); 13 60 int pnv_ocxl_get_pasid_count(struct pci_dev *dev, int *count); ··· 78 31 int pnv_ocxl_map_lpar(struct pci_dev *dev, uint64_t lparid, 79 32 uint64_t lpcr, void __iomem **arva); 80 33 void pnv_ocxl_unmap_lpar(void __iomem *arva); 34 + void pnv_ocxl_tlb_invalidate(void __iomem *arva, 35 + unsigned long pid, 36 + unsigned long addr, 37 + unsigned long page_size); 81 38 #endif /* _ASM_PNV_OCXL_H */
+69
arch/powerpc/platforms/powernv/ocxl.c
··· 528 528 iounmap(arva); 529 529 } 530 530 EXPORT_SYMBOL_GPL(pnv_ocxl_unmap_lpar); 531 + 532 + void pnv_ocxl_tlb_invalidate(void __iomem *arva, 533 + unsigned long pid, 534 + unsigned long addr, 535 + unsigned long page_size) 536 + { 537 + unsigned long timeout = jiffies + (HZ * PNV_OCXL_ATSD_TIMEOUT); 538 + u64 val = 0ull; 539 + int pend; 540 + u8 size; 541 + 542 + if (!(arva)) 543 + return; 544 + 545 + if (addr) { 546 + /* load Abbreviated Virtual Address register with 547 + * the necessary value 548 + */ 549 + val |= FIELD_PREP(PNV_OCXL_ATSD_AVA_AVA, addr >> (63-51)); 550 + out_be64(arva + PNV_OCXL_ATSD_AVA, val); 551 + } 552 + 553 + /* Write access initiates a shoot down to initiate the 554 + * TLB Invalidate command 555 + */ 556 + val = PNV_OCXL_ATSD_LNCH_R; 557 + val |= FIELD_PREP(PNV_OCXL_ATSD_LNCH_RIC, 0b10); 558 + if (addr) 559 + val |= FIELD_PREP(PNV_OCXL_ATSD_LNCH_IS, 0b00); 560 + else { 561 + val |= FIELD_PREP(PNV_OCXL_ATSD_LNCH_IS, 0b01); 562 + val |= PNV_OCXL_ATSD_LNCH_OCAPI_SINGLETON; 563 + } 564 + val |= PNV_OCXL_ATSD_LNCH_PRS; 565 + /* Actual Page Size to be invalidated 566 + * 000 4KB 567 + * 101 64KB 568 + * 001 2MB 569 + * 010 1GB 570 + */ 571 + size = 0b101; 572 + if (page_size == 0x1000) 573 + size = 0b000; 574 + if (page_size == 0x200000) 575 + size = 0b001; 576 + if (page_size == 0x40000000) 577 + size = 0b010; 578 + val |= FIELD_PREP(PNV_OCXL_ATSD_LNCH_AP, size); 579 + val |= FIELD_PREP(PNV_OCXL_ATSD_LNCH_PID, pid); 580 + out_be64(arva + PNV_OCXL_ATSD_LNCH, val); 581 + 582 + /* Poll the ATSD status register to determine when the 583 + * TLB Invalidate has been completed. 584 + */ 585 + val = in_be64(arva + PNV_OCXL_ATSD_STAT); 586 + pend = val >> 63; 587 + 588 + while (pend) { 589 + if (time_after_eq(jiffies, timeout)) { 590 + pr_err("%s - Timeout while reading XTS MMIO ATSD status register (val=%#llx, pidr=0x%lx)\n", 591 + __func__, val, pid); 592 + return; 593 + } 594 + cpu_relax(); 595 + val = in_be64(arva + PNV_OCXL_ATSD_STAT); 596 + pend = val >> 63; 597 + } 598 + } 599 + EXPORT_SYMBOL_GPL(pnv_ocxl_tlb_invalidate);