From f24be42aab37c6d07c05126673138e06223a6399 Mon Sep 17 00:00:00 2001 From: Christophe Lombard Date: Wed, 12 Apr 2017 16:34:07 +0200 Subject: cxl: Add psl9 specific code The new Coherent Accelerator Interface Architecture, level 2, for the IBM POWER9 brings new content and features: - POWER9 Service Layer - Registers - Radix mode - Process element entry - Dedicated-Shared Process Programming Model - Translation Fault Handling - CAPP - Memory Context ID If a valid mm_struct is found the memory context id is used for each transaction associated with the process handle. The PSL uses the context ID to find the corresponding process element. Signed-off-by: Christophe Lombard Acked-by: Frederic Barrat [mpe: Fixup comment formatting, unsplit long strings] Signed-off-by: Michael Ellerman --- drivers/misc/cxl/fault.c | 64 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'drivers/misc/cxl/fault.c') diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index e6f8f05446be..5344448f514e 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c @@ -146,25 +146,26 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, return cxl_ack_ae(ctx); } - /* - * update_mmu_cache() will not have loaded the hash since current->trap - * is not a 0x400 or 0x300, so just call hash_page_mm() here. - */ - access = _PAGE_PRESENT | _PAGE_READ; - if (dsisr & CXL_PSL_DSISR_An_S) - access |= _PAGE_WRITE; - - access |= _PAGE_PRIVILEGED; - if ((!ctx->kernel) || (REGION_ID(dar) == USER_REGION_ID)) - access &= ~_PAGE_PRIVILEGED; - - if (dsisr & DSISR_NOHPTE) - inv_flags |= HPTE_NOHPTE_UPDATE; - - local_irq_save(flags); - hash_page_mm(mm, dar, access, 0x300, inv_flags); - local_irq_restore(flags); - + if (!radix_enabled()) { + /* + * update_mmu_cache() will not have loaded the hash since current->trap + * is not a 0x400 or 0x300, so just call hash_page_mm() here. + */ + access = _PAGE_PRESENT | _PAGE_READ; + if (dsisr & CXL_PSL_DSISR_An_S) + access |= _PAGE_WRITE; + + access |= _PAGE_PRIVILEGED; + if ((!ctx->kernel) || (REGION_ID(dar) == USER_REGION_ID)) + access &= ~_PAGE_PRIVILEGED; + + if (dsisr & DSISR_NOHPTE) + inv_flags |= HPTE_NOHPTE_UPDATE; + + local_irq_save(flags); + hash_page_mm(mm, dar, access, 0x300, inv_flags); + local_irq_restore(flags); + } pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0); } @@ -184,7 +185,28 @@ static struct mm_struct *get_mem_context(struct cxl_context *ctx) return ctx->mm; } +static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr) +{ + if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DS)) + return true; + + return false; +} + +static bool cxl_is_page_fault(struct cxl_context *ctx, u64 dsisr) +{ + if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DM)) + return true; + + if ((cxl_is_psl9(ctx->afu)) && + ((dsisr & CXL_PSL9_DSISR_An_CO_MASK) & + (CXL_PSL9_DSISR_An_PF_SLR | CXL_PSL9_DSISR_An_PF_RGC | + CXL_PSL9_DSISR_An_PF_RGP | CXL_PSL9_DSISR_An_PF_HRH | + CXL_PSL9_DSISR_An_PF_STEG))) + return true; + return false; +} void cxl_handle_fault(struct work_struct *fault_work) { @@ -230,9 +252,9 @@ void cxl_handle_fault(struct work_struct *fault_work) } } - if (dsisr & CXL_PSL_DSISR_An_DS) + if (cxl_is_segment_miss(ctx, dsisr)) cxl_handle_segment_miss(ctx, mm, dar); - else if (dsisr & CXL_PSL_DSISR_An_DM) + else if (cxl_is_page_fault(ctx, dsisr)) cxl_handle_page_fault(ctx, mm, dsisr, dar); else WARN(1, "cxl_handle_fault has nothing to handle\n"); -- cgit