From patchwork Mon Jan 20 06:57:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederik Harwath X-Patchwork-Id: 1225702 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-517710-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=PaZhoo45; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 481Mvc5wJZz9sRf for ; Mon, 20 Jan 2020 17:58:34 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=WvafCa+ixUWN9rqe2tceEA9zpBvRnNnk4koJ2aV0t0YtSIKDB4 8AUkDPIhRnfePl7cQMHyKEXPfVRjhuuznZp0Mql7Nq1Tchh4QdgnUdtwqK4SRWbz Kl27NdxYoyYjULU4x3IFI5HtQ/83d0Eji5NL30EKN2oHYvxgBwfqokfaM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=Lnlz0u1+lIm9KMT36OkMSP6rEOI=; b=PaZhoo45PX6CqT43DWNi 99jnpwjBuNqB3wNc4tVRSUaSNpnUlgRBn8599qpS0y/zbIVS0jWvB5jsy/GCZIep dH1EpoMgTZge7EmaTH/dgaM2ajaYWUNmx/hg/tb/SB9Ut22UJapXramnWrXKMrmn iVbkKCYIGaY75U3l97Izs9M= Received: (qmail 16512 invoked by alias); 20 Jan 2020 06:58:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 16502 invoked by uid 89); 20 Jan 2020 06:58:25 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-20.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.1 spammy=strncmp, HX-Envelope-From:sk:Frederi, offload, aborted X-HELO: esa4.mentor.iphmx.com Received: from esa4.mentor.iphmx.com (HELO esa4.mentor.iphmx.com) (68.232.137.252) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 Jan 2020 06:58:15 +0000 IronPort-SDR: NpB7wwFASfOfqmDlASbhAzx4sdyDzMYZ/eh1TCyUmVEhJA0dyjjyhGp8n2ZBFpU5ZXq08iAMiU D/bGyjuMU9O3dT2kespg6bBFsH+qiNaGt94R7MLk724RJU9Hm5gwvr+exjluVrNM4aXCd18p+7 99TX5pJLwtdkoQtXdDPa7elJOOSVGNSFhIT3qsX3Orh950sUHAXLJra4Y0LUNogiDr4e0d9mZx 5xhlZrztBOrqg3FEj6TlupHWvxYhkqwSbYVPVBQqulfrwuj+iz8eMev99Ye8+u9XlwrZ55zES6 wvU= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa4.mentor.iphmx.com with ESMTP; 19 Jan 2020 22:58:12 -0800 IronPort-SDR: YwHdqQvtCm+KV/CARYn9+zoh1JFkzy1Y0aOyCi2o/aLvLT10cPVJW6qyH4CqUglrdG1xVPQrTh pKuzWG8Zdeug== From: "Harwath, Frederik" Subject: [PATCH][amdgcn] Add runtime ISA check for amdgcn offloading To: GCC Patches , "Stubbs, Andrew" CC: Jakub Jelinek X-Pep-Version: 2.0 Message-ID: Date: Mon, 20 Jan 2020 07:57:55 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.4.1 MIME-Version: 1.0 X-IsSubscribed: yes Hi, this patch implements a runtime ISA check for amdgcn offloading. The check verifies that the ISA of the GPU to which we try to offload matches the ISA for which the code to be offloaded has been compiled. If it detects a mismatch, it emits an error message which contains a hint at the correct compilation parameters for the GPU. For instance: "libgomp: GCN fatal error: GCN code object ISA 'gfx906' does not match GPU ISA 'gfx900'. Try to recompile with '-foffload=-march=gfx900'." or "libgomp: GCN fatal error: GCN code object ISA 'gfx900' does not match agent ISA 'gfx803'. Try to recompile with '-foffload=-march=fiji'." (By the way, the names that we use for the ISAs are a bit inconsistent. Perhaps we should just use the gfx-names for all ISAs everywhere?.) Without this patch, the user only gets an confusing error message from the HSA runtime which fails to load the GCN object code. I have checked that the code does not lead to any regressions when running the test suite correctly, i.e. with the "-foffload=-march=..." option given to the compiler matching the architecture of the GPU. It seems difficult to implement an automated test that triggers an ISA mismatch. I have tested manually (for different combinations of the compilation flags and offloading GPU ISAs) that the runtime ISA check produces the expected error messages. Is it ok to commit this patch to the master branch? Frederik From 27981f9c93d1efed6d943dae4ea0c52147c02d5b Mon Sep 17 00:00:00 2001 From: Frederik Harwath Date: Mon, 20 Jan 2020 07:45:43 +0100 Subject: [PATCH] Add runtime ISA check for amdgcn offloading When executing code that uses amdgcn GPU offloading, the ISA of the GPU must match the ISA for which the code has been compiled. So far, the libgomp amdgcn plugin did not attempt to verify this. In case of a mismatch, the user is confronted with an unhelpful error message produced by the HSA runtime. This commit implements a runtime ISA check. In the case of a ISA mismatch, the execution is aborted with a clear error message and a hint at the correct compilation parameters for the GPU on which the execution has been attempted. libgomp/ * plugin/plugin-gcn.c (EF_AMDGPU_MACH): New enum. (EF_AMDGPU_MACH_MASK): New constant. (gcn_isa): New typedef. (gcn_gfx801_s): New constant. (gcn_gfx803_s): New constant. (gcn_gfx900_s): New constant. (gcn_gfx906_s): New constant. (gcn_isa_name_len): New constant. (elf_gcn_isa_field): New function. (isa_hsa_name): New function. (isa_gcc_name): New function. (isa_code): New function. (struct agent_info): Add field "device_isa" ... (GOMP_OFFLOAD_init_device): ... and init from here, failing if device has unknown ISA; adapt init of "gfx900_p" to use new constants. (isa_matches_agent): New function ... (create_and_finalize_hsa_program): ... used from here to check that the GPU ISA and the code-object ISA match. --- libgomp/plugin/plugin-gcn.c | 127 +++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c index 16ce251f3a5..14f4a707a7c 100644 --- a/libgomp/plugin/plugin-gcn.c +++ b/libgomp/plugin/plugin-gcn.c @@ -396,6 +396,88 @@ struct gcn_image_desc struct global_var_info *global_variables; }; +/* This enum mirrors the corresponding LLVM enum's values for all ISAs that we + support. + See https://llvm.org/docs/AMDGPUUsage.html#amdgpu-ef-amdgpu-mach-table */ + +typedef enum { + EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, + EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, + EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, + EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, +} EF_AMDGPU_MACH; + +const static int EF_AMDGPU_MACH_MASK = 0x000000ff; +typedef EF_AMDGPU_MACH gcn_isa; + +const static char* gcn_gfx801_s = "gfx801"; +const static char* gcn_gfx803_s = "gfx803"; +const static char* gcn_gfx900_s = "gfx900"; +const static char* gcn_gfx906_s = "gfx906"; +const static int gcn_isa_name_len = 6; + +static int +elf_gcn_isa_field (Elf64_Ehdr *image) +{ + return image->e_flags & EF_AMDGPU_MACH_MASK; +} + +/* Returns the name that the HSA runtime uses for the ISA or NULL if we do not + support the ISA. */ + +static const char* +isa_hsa_name (int isa) { + switch(isa) + { + case EF_AMDGPU_MACH_AMDGCN_GFX801: + return gcn_gfx801_s; + case EF_AMDGPU_MACH_AMDGCN_GFX803: + return gcn_gfx803_s; + case EF_AMDGPU_MACH_AMDGCN_GFX900: + return gcn_gfx900_s; + case EF_AMDGPU_MACH_AMDGCN_GFX906: + return gcn_gfx906_s; + } + return NULL; +} + +/* Returns the user-facing name that GCC uses to identify the architecture (e.g. + with -march) or NULL if we do not support the ISA. + Keep in sync with /gcc/config/gcn/gcn.{c,opt}. */ + +static const char* +isa_gcc_name (int isa) { + switch(isa) + { + case EF_AMDGPU_MACH_AMDGCN_GFX801: + return "carrizo"; + case EF_AMDGPU_MACH_AMDGCN_GFX803: + return "fiji"; + default: + return isa_hsa_name (isa); + } +} + +/* Returns the code which is used in the GCN object code to identify the ISA with + the given name (as used by the HSA runtime). */ + +static gcn_isa +isa_code(const char *isa) { + if (!strncmp (isa, gcn_gfx801_s, gcn_isa_name_len)) + return EF_AMDGPU_MACH_AMDGCN_GFX801; + + if (!strncmp (isa, gcn_gfx803_s, gcn_isa_name_len)) + return EF_AMDGPU_MACH_AMDGCN_GFX803; + + if (!strncmp (isa, gcn_gfx900_s, gcn_isa_name_len)) + return EF_AMDGPU_MACH_AMDGCN_GFX900; + + if (!strncmp (isa, gcn_gfx906_s, gcn_isa_name_len)) + return EF_AMDGPU_MACH_AMDGCN_GFX906; + + return -1; +} + /* Description of an HSA GPU agent (device) and the program associated with it. */ @@ -411,6 +493,9 @@ struct agent_info /* Precomputed check for problem architectures. */ bool gfx900_p; + /* The instruction set architecture of the device. */ + gcn_isa device_isa; + /* Command queues of the agent. */ hsa_queue_t *sync_queue; struct goacc_asyncqueue *async_queues, *omp_async_queue; @@ -2257,6 +2342,39 @@ find_load_offset (Elf64_Addr *load_offset, struct agent_info *agent, return res; } +/* Check that the GCN ISA of the given image matches the ISA of the agent. */ + +static bool +isa_matches_agent (struct agent_info *agent, Elf64_Ehdr *image) +{ + int isa_field = elf_gcn_isa_field (image); + const char* isa_s = isa_hsa_name (isa_field); + if (!isa_s) + { + hsa_error ("Unsupported ISA in GCN code object.", HSA_STATUS_ERROR); + return false; + } + + if (isa_field != agent->device_isa) + { + char msg[120]; + const char *agent_isa_s = isa_hsa_name (agent->device_isa); + const char *agent_isa_gcc_s = isa_gcc_name (agent->device_isa); + assert (agent_isa_s); + assert (agent_isa_gcc_s); + + snprintf (msg, sizeof msg, + "GCN code object ISA '%s' does not match GPU ISA '%s'.\n" + "Try to recompile with '-foffload=-march=%s'.\n", + isa_s, agent_isa_s, agent_isa_gcc_s); + + hsa_error (msg, HSA_STATUS_ERROR); + return false; + } + + return true; +} + /* Create and finalize the program consisting of all loaded modules. */ static bool @@ -2289,6 +2407,9 @@ create_and_finalize_hsa_program (struct agent_info *agent) { Elf64_Ehdr *image = (Elf64_Ehdr *)module->image_desc->gcn_image->image; + if (!isa_matches_agent (agent, image)) + goto fail; + /* Hide relocations from the HSA runtime loader. Keep a copy of the unmodified section headers to use later. */ Elf64_Shdr *image_sections = (Elf64_Shdr *)((char *)image @@ -3294,7 +3415,11 @@ GOMP_OFFLOAD_init_device (int n) &buf); if (status != HSA_STATUS_SUCCESS) return hsa_error ("Error querying the name of the agent", status); - agent->gfx900_p = (strncmp (buf, "gfx900", 6) == 0); + agent->gfx900_p = (strncmp (buf, gcn_gfx900_s, gcn_isa_name_len) == 0); + + agent->device_isa = isa_code (buf); + if (agent->device_isa < 0) + return hsa_error ("Unknown GCN agent architecture.", HSA_STATUS_ERROR); status = hsa_fns.hsa_queue_create_fn (agent->id, queue_size, HSA_QUEUE_TYPE_MULTI, -- 2.17.1