From patchwork Thu Feb 12 01:57:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Neuling X-Patchwork-Id: 438993 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45DCC1400EA for ; Thu, 12 Feb 2015 12:58:45 +1100 (AEDT) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id 20AD71A0A40 for ; Thu, 12 Feb 2015 12:58:45 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id D03AD1A0A00 for ; Thu, 12 Feb 2015 12:58:13 +1100 (AEDT) Received: from localhost.localdomain (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 882F9140188; Thu, 12 Feb 2015 12:58:13 +1100 (AEDT) Received: by localhost.localdomain (Postfix, from userid 1000) id 70D0BD46EE9; Thu, 12 Feb 2015 12:58:13 +1100 (AEDT) From: Michael Neuling To: stewart@linux.vnet.ibm.com Date: Thu, 12 Feb 2015 12:57:58 +1100 Message-Id: <1423706279-12170-9-git-send-email-mikey@neuling.org> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1423706279-12170-1-git-send-email-mikey@neuling.org> References: <1423706279-12170-1-git-send-email-mikey@neuling.org> Cc: grimm@linux.vnet.ibm.com, imunsie@au.ibm.com, skiboot@lists.ozlabs.org Subject: [Skiboot] [PATCH 09/10] capi: Make microcode lid parsing code endian safe X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" The current CAPP microcode lid parsing code assumes skiboot is running big endian which may not always be the case. This rewrites the lid parsing code to be endian safe. It also cleans up the code a bunch. Signed-off-by: Michael Neuling --- hw/phb3.c | 106 ++++++++++++++++++++++++++++++++------------------------- include/capp.h | 67 ++++++++++++++++++++---------------- 2 files changed, 97 insertions(+), 76 deletions(-) diff --git a/hw/phb3.c b/hw/phb3.c index 4b53948..8cf5196 100644 --- a/hw/phb3.c +++ b/hw/phb3.c @@ -2200,13 +2200,11 @@ static uint64_t capp_fsp_lid_load(struct phb3 *p) static int64_t capp_load_ucode(struct phb3 *p) { - - struct capp_ucode_lid_hdr *ucode_hdr; - struct capp_ucode_data_hdr *data_hdr; - struct capp_lid_hdr *lid_hdr; - uint64_t data, *val; - int size_read = 0; - int tmp; + struct capp_lid_hdr *lid; + struct capp_ucode_lid *ucode; + struct capp_ucode_data *data; + uint64_t val, addr; + uint32_t chunk_count, offset; int i; /* if fsp not present p->ucode_base gotten from device tree */ @@ -2219,53 +2217,69 @@ static int64_t capp_load_ucode(struct phb3 *p) } PHBINF(p, "Loading capp microcode @%llx\n", p->capp_ucode_base); - lid_hdr = (struct capp_lid_hdr *)p->capp_ucode_base; - if (lid_hdr->eyecatcher != 0x434150504c494448) - /* lid header not present due to older fw or bml boot */ - ucode_hdr = (struct capp_ucode_lid_hdr *)(p->capp_ucode_base); - else - ucode_hdr = (struct capp_ucode_lid_hdr *)(p->capp_ucode_base + - lid_hdr->ucode_offset); + lid = (struct capp_lid_hdr *)p->capp_ucode_base; + /* + * If lid header is present (on FSP machines), it'll tell us where to + * find the ucode. Otherwise this is the ucode. + */ + ucode = (struct capp_ucode_lid *)lid; + if (be64_to_cpu(lid->eyecatcher) == 0x434150504c494448) { + if (be64_to_cpu(lid->version) != 0x1) { + PHBERR(p, "capi ucode lid header invalid\n"); + return OPAL_HARDWARE; + } + ucode = (struct capp_ucode_lid *) + ((char *)ucode + be64_to_cpu(lid->ucode_offset)); + } - if (ucode_hdr->eyecatcher != 0x43415050554C4944) { - PHBERR(p, "capi ucode lid header eyecatcher not found\n"); - return OPAL_HARDWARE; + if ((be64_to_cpu(ucode->eyecatcher) != 0x43415050554C4944) || + (ucode->version != 1)) { + PHBERR(p, "CAPP: ucode header invalid\n"); + return OPAL_HARDWARE; } - data_hdr = (struct capp_ucode_data_hdr *)(ucode_hdr + 1); - while (size_read < ucode_hdr->data_size) { - if (data_hdr->eyecatcher != 0x4341505055434F44) { - PHBERR(p, "capi ucode data header eyecatcher not found!\n"); + offset = 0; + while (offset < be64_to_cpu(ucode->data_size)) { + data = (struct capp_ucode_data *) + ((char *)&ucode->data + offset); + chunk_count = be32_to_cpu(data->hdr.chunk_count); + offset += sizeof(struct capp_ucode_data_hdr) + chunk_count * 8; + + if (be64_to_cpu(data->hdr.eyecatcher) != 0x4341505055434F44) { + PHBERR(p, "CAPP: ucode data header invalid:%i\n", + offset); return OPAL_HARDWARE; } - val = (uint64_t *)(data_hdr + 1); - if (data_hdr->reg == apc_master_cresp) { - xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, 0); - for (i = 0; i < data_hdr->num_data_chunks; i++) - xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_WRITE_REG, *val++); - xscom_read(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, &data); - } else if (data_hdr->reg == apc_master_uop_table) { - xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, 0x180ULL << 52); - for (i = 0; i < data_hdr->num_data_chunks; i++) - xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_WRITE_REG, *val++); - xscom_read(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, &data); - } else if (data_hdr->reg == snp_ttype) { - xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, 0x5000ULL << 48); - for (i = 0; i < data_hdr->num_data_chunks; i++) - xscom_write(p->chip_id, CAPP_SNP_ARRAY_WRITE_REG, *val++); - xscom_read(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, &data); - } else if (data_hdr->reg == snp_uop_table) { - xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, 0x4000ULL << 48); - for (i = 0; i < data_hdr->num_data_chunks; i++) - xscom_write(p->chip_id, CAPP_SNP_ARRAY_WRITE_REG, *val++); - xscom_read(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, &data); + switch (data->hdr.reg) { + case apc_master_cresp: + xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, + 0); + addr = CAPP_APC_MASTER_ARRAY_WRITE_REG; + break; + case apc_master_uop_table: + xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG, + 0x180ULL << 52); + addr = CAPP_APC_MASTER_ARRAY_WRITE_REG; + break; + case snp_ttype: + xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, + 0x5000ULL << 48); + addr = CAPP_SNP_ARRAY_WRITE_REG; + break; + case snp_uop_table: + xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG, + 0x4000ULL << 48); + addr = CAPP_SNP_ARRAY_WRITE_REG; + break; + default: + continue; } - size_read += sizeof(*data_hdr) + data_hdr->num_data_chunks * 8; - tmp = data_hdr->num_data_chunks; - data_hdr++; - data_hdr = (struct capp_ucode_data_hdr *)((uint64_t *)data_hdr + tmp); + for (i = 0; i < chunk_count; i++) { + val = be64_to_cpu(data->data[i]); + xscom_write(p->chip_id, addr, val); + } } p->capp_ucode_loaded = true; diff --git a/include/capp.h b/include/capp.h index ef052b8..4b53e37 100644 --- a/include/capp.h +++ b/include/capp.h @@ -13,43 +13,50 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -struct capp_ucode_lid_hdr { - uint64_t eyecatcher; /* 'CAPPULID' in ASCII */ - uint64_t version; - uint64_t data_size; /* total size of all capp microcode data following header */ - u8 reserved[40]; /* zeroed, pads to 64 byte boundary */ + +struct capp_lid_hdr { + be64 eyecatcher; /* 'CAPPLIDH' in ASCII */ + be64 version; + be64 lid_no; + be64 pad; + be64 ucode_offset; + be64 total_size; }; -struct capp_ucode_data_hdr -{ - uint64_t eyecatcher; /* 'CAPPUCOD' in ASCII */ - u8 version; - u8 reg; - u8 reserved[2]; - uint32_t num_data_chunks; /* Number of 8-byte chunks of data that follow this header */ +struct capp_ucode_data_hdr { + be64 eyecatcher; /* 'CAPPUCOD' in ASCII */ + u8 version; + u8 reg; + u8 reserved[2]; + be32 chunk_count; /* Num of 8-byte chunks that follow */ }; -struct capp_lid_hdr { - uint64_t eyecatcher; - uint64_t version; - uint64_t lid_no; - uint64_t pad; - uint64_t ucode_offset; - uint64_t total_size; +struct capp_ucode_data { + struct capp_ucode_data_hdr hdr; + be64 data[]; }; +struct capp_ucode_lid { + be64 eyecatcher; /* 'CAPPULID' in ASCII */ + be64 version; + be64 data_size; /* Total size of all capp microcode data */ + u8 reserved[40]; + struct capp_ucode_data data; /* This repeats */ +}; + + enum capp_reg { - apc_master_cresp = 0x1, - apc_master_uop_table = 0x2, - snp_ttype = 0x3, - snp_uop_table = 0x4, - apt_master_capi_ctrl = 0x5, - snoop_capi_cnfg = 0x6, - canned_presp_map0 = 0x7, - canned_presp_map1 = 0x8, - canned_presp_map2 = 0x9, - flush_sue_state_map = 0xA, - apc_master_powerbus_ctrl = 0xB + apc_master_cresp = 0x1, + apc_master_uop_table = 0x2, + snp_ttype = 0x3, + snp_uop_table = 0x4, + apt_master_capi_ctrl = 0x5, + snoop_capi_cnfg = 0x6, + canned_presp_map0 = 0x7, + canned_presp_map1 = 0x8, + canned_presp_map2 = 0x9, + flush_sue_state_map = 0xA, + apc_master_powerbus_ctrl = 0xB }; #define CAPP_SNP_ARRAY_ADDR_REG 0x2013028