From nobody Tue May 21 11:48:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1655757118508863.7133713380763; Mon, 20 Jun 2022 13:31:58 -0700 (PDT) Received: from localhost ([::1]:58984 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3O3x-0003Ec-7D for importer@patchew.org; Mon, 20 Jun 2022 16:31:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45132) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3Nzk-00015Z-RJ; Mon, 20 Jun 2022 16:27:36 -0400 Received: from [187.72.171.209] (port=41085 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3Nzj-0000Ag-7r; Mon, 20 Jun 2022 16:27:36 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Mon, 20 Jun 2022 17:27:23 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id B7B7A8007AF; Mon, 20 Jun 2022 17:27:22 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: clg@kaod.org, danielhb413@gmail.com, david@gibson.dropbear.id.au, groug@kaod.org, Leandro Lupori Subject: [PATCH 1/3] ppc: Check partition and process table alignment Date: Mon, 20 Jun 2022 17:27:02 -0300 Message-Id: <20220620202704.78978-2-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> References: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-OriginalArrivalTime: 20 Jun 2022 20:27:23.0084 (UTC) FILETIME=[25E898C0:01D884E4] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1655757120761100001 Content-Type: text/plain; charset="utf-8" Check if partition and process tables are properly aligned, in their size, according to PowerISA 3.1B, Book III 6.7.6 programming note. Hardware and KVM also raise an exception in these cases. Signed-off-by: Leandro Lupori --- hw/ppc/spapr.c | 5 +++++ hw/ppc/spapr_hcall.c | 9 +++++++++ target/ppc/mmu-book3s-v3.c | 5 +++++ target/ppc/mmu-radix64.c | 17 +++++++++++++---- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index fd4942e881..4b1f346087 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1329,6 +1329,11 @@ static bool spapr_get_pate(PPCVirtualHypervisor *vhy= p, PowerPCCPU *cpu, patb =3D spapr->nested_ptcr & PTCR_PATB; pats =3D spapr->nested_ptcr & PTCR_PATS; =20 + /* Check if partition table is properly aligned */ + if (patb & MAKE_64BIT_MASK(0, pats + 12)) { + return false; + } + /* Calculate number of entries */ pats =3D 1ull << (pats + 12 - 4); if (pats <=3D lpid) { diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index d761a7d0c3..2a73ba8a1d 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -920,6 +920,7 @@ static target_ulong h_register_process_table(PowerPCCPU= *cpu, target_ulong page_size =3D args[2]; target_ulong table_size =3D args[3]; target_ulong update_lpcr =3D 0; + target_ulong table_byte_size; uint64_t cproc; =20 if (flags & ~FLAGS_MASK) { /* Check no reserved bits are set */ @@ -927,6 +928,14 @@ static target_ulong h_register_process_table(PowerPCCP= U *cpu, } if (flags & FLAG_MODIFY) { if (flags & FLAG_REGISTER) { + /* Check process table alignment */ + table_byte_size =3D 1ULL << (table_size + 12); + if (proc_tbl & (table_byte_size - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: process table not properly aligned: " + "proc_tbl 0x%lx proc_tbl_size 0x%lx\n", + __func__, proc_tbl, table_byte_size); + } if (flags & FLAG_RADIX) { /* Register new RADIX process table = */ if (proc_tbl & 0xfff || proc_tbl >> 60) { return H_P2; diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c index f4985bae78..c8f69b3df9 100644 --- a/target/ppc/mmu-book3s-v3.c +++ b/target/ppc/mmu-book3s-v3.c @@ -28,6 +28,11 @@ bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpi= d, ppc_v3_pate_t *entry) uint64_t patb =3D cpu->env.spr[SPR_PTCR] & PTCR_PATB; uint64_t pats =3D cpu->env.spr[SPR_PTCR] & PTCR_PATS; =20 + /* Check if partition table is properly aligned */ + if (patb & MAKE_64BIT_MASK(0, pats + 12)) { + return false; + } + /* Calculate number of entries */ pats =3D 1ull << (pats + 12 - 4); if (pats <=3D lpid) { diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 21ac958e48..9a8a2e2875 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -383,7 +383,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU = *cpu, { CPUState *cs =3D CPU(cpu); CPUPPCState *env =3D &cpu->env; - uint64_t offset, size, prtbe_addr, prtbe0, base_addr, nls, index, pte; + uint64_t offset, size, prtb, prtbe_addr, prtbe0, base_addr, nls, index= , pte; int fault_cause =3D 0, h_page_size, h_prot; hwaddr h_raddr, pte_addr; int ret; @@ -393,9 +393,18 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU= *cpu, __func__, access_str(access_type), eaddr, mmu_idx, pid); =20 + prtb =3D (pate.dw1 & PATE1_R_PRTB); + size =3D 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); + if (prtb & (size - 1)) { + /* Process Table not properly aligned */ + if (guest_visible) { + ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFI= G); + } + return 1; + } + /* Index Process Table by PID to Find Corresponding Process Table Entr= y */ offset =3D pid * sizeof(struct prtb_entry); - size =3D 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); if (offset >=3D size) { /* offset exceeds size of the process table */ if (guest_visible) { @@ -403,7 +412,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU = *cpu, } return 1; } - prtbe_addr =3D (pate.dw1 & PATE1_R_PRTB) + offset; + prtbe_addr =3D prtb + offset; =20 if (vhyp_flat_addressing(cpu)) { prtbe0 =3D ldq_phys(cs->as, prtbe_addr); @@ -568,7 +577,7 @@ static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vad= dr eaddr, return false; } =20 - /* Get Process Table */ + /* Get Partition Table */ if (cpu->vhyp) { PPCVirtualHypervisorClass *vhc; vhc =3D PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); --=20 2.25.1 From nobody Tue May 21 11:48:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1655757133176736.2574777289645; Mon, 20 Jun 2022 13:32:13 -0700 (PDT) Received: from localhost ([::1]:59600 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3O4C-0003mT-2e for importer@patchew.org; Mon, 20 Jun 2022 16:32:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45146) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3Nzn-00019k-Cp; Mon, 20 Jun 2022 16:27:39 -0400 Received: from [187.72.171.209] (port=41085 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3Nzl-0000Ag-Rh; Mon, 20 Jun 2022 16:27:39 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Mon, 20 Jun 2022 17:27:23 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id EEF80800048; Mon, 20 Jun 2022 17:27:22 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: clg@kaod.org, danielhb413@gmail.com, david@gibson.dropbear.id.au, groug@kaod.org, Leandro Lupori Subject: [PATCH 2/3] target/ppc: Improve Radix xlate level validation Date: Mon, 20 Jun 2022 17:27:03 -0300 Message-Id: <20220620202704.78978-3-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> References: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-OriginalArrivalTime: 20 Jun 2022 20:27:23.0303 (UTC) FILETIME=[260A0370:01D884E4] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1655757134448100003 Content-Type: text/plain; charset="utf-8" Check if the number and size of Radix levels are valid on POWER9/POWER10 CPUs, according to the supported Radix Tree Configurations described in their User Manuals. Signed-off-by: Leandro Lupori --- target/ppc/mmu-radix64.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 9a8a2e2875..2f0bcbfe2e 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -236,13 +236,31 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, MMUAc= cessType access_type, } } =20 +static bool ppc_radix64_is_valid_level(int level, int psize, uint64_t nls) +{ + /* + * Check if this is a valid level, according to POWER9 and POWER10 + * Processor User's Manuals, sections 4.10.4.1 and 5.10.6.1, respectiv= ely: + * Supported Radix Tree Configurations and Resulting Page Sizes. + */ + switch (level) { + case 0: return psize =3D=3D 52 && nls =3D=3D 13; /* Root Page D= ir */ + case 1: return psize =3D=3D 39 && nls =3D=3D 9; + case 2: return psize =3D=3D 30 && nls =3D=3D 9; + case 3: return psize =3D=3D 21 && (nls =3D=3D 9 || nls =3D=3D 5); + default: + qemu_log_mask(LOG_GUEST_ERROR, "invalid radix level: %d\n", level); + return false; + } +} + static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr, - uint64_t *pte_addr, uint64_t *nls, + uint64_t *pte_addr, int *level, uint64_t= *nls, int *psize, uint64_t *pte, int *fault_ca= use) { uint64_t index, pde; =20 - if (*nls < 5) { /* Directory maps less than 2**5 entries */ + if (!ppc_radix64_is_valid_level(*level, *psize, *nls)) { *fault_cause |=3D DSISR_R_BADCONFIG; return 1; } @@ -257,6 +275,7 @@ static int ppc_radix64_next_level(AddressSpace *as, vad= dr eaddr, *pte =3D pde; *psize -=3D *nls; if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */ + ++*level; *nls =3D pde & R_PDE_NLS; index =3D eaddr >> (*psize - *nls); /* Shift */ index &=3D ((1UL << *nls) - 1); /* Mask */ @@ -270,9 +289,10 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vad= dr eaddr, hwaddr *raddr, int *psize, uint64_t *pte, int *fault_cause, hwaddr *pte_addr) { - uint64_t index, pde, rpn , mask; + uint64_t index, pde, rpn, mask; + int level =3D 0; =20 - if (nls < 5) { /* Directory maps less than 2**5 entries */ + if (!ppc_radix64_is_valid_level(level, *psize, nls)) { *fault_cause |=3D DSISR_R_BADCONFIG; return 1; } @@ -283,8 +303,8 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vadd= r eaddr, do { int ret; =20 - ret =3D ppc_radix64_next_level(as, eaddr, pte_addr, &nls, psize, &= pde, - fault_cause); + ret =3D ppc_radix64_next_level(as, eaddr, pte_addr, &level, &nls, = psize, + &pde, fault_cause); if (ret) { return ret; } @@ -456,6 +476,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU = *cpu, } } else { uint64_t rpn, mask; + int level =3D 0; =20 index =3D (eaddr & R_EADDR_MASK) >> (*g_page_size - nls); /* Shift= */ index &=3D ((1UL << nls) - 1); /* Mask = */ @@ -476,7 +497,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU = *cpu, } =20 ret =3D ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK, &= h_raddr, - &nls, g_page_size, &pte, &fault_c= ause); + &level, &nls, g_page_size, &pte, + &fault_cause); if (ret) { /* No valid pte */ if (guest_visible) { --=20 2.25.1 From nobody Tue May 21 11:48:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1655757413639839.028627386861; Mon, 20 Jun 2022 13:36:53 -0700 (PDT) Received: from localhost ([::1]:37860 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3O8i-0000C0-Bj for importer@patchew.org; Mon, 20 Jun 2022 16:36:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45336) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3O0p-0002FI-G3; Mon, 20 Jun 2022 16:28:43 -0400 Received: from [187.72.171.209] (port=63615 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3O0o-0000Iy-1L; Mon, 20 Jun 2022 16:28:43 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Mon, 20 Jun 2022 17:27:23 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id 36E278007AF; Mon, 20 Jun 2022 17:27:23 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: clg@kaod.org, danielhb413@gmail.com, david@gibson.dropbear.id.au, groug@kaod.org, Leandro Lupori Subject: [PATCH 3/3] target/ppc: Check page dir/table base alignment Date: Mon, 20 Jun 2022 17:27:04 -0300 Message-Id: <20220620202704.78978-4-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> References: <20220620202704.78978-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-OriginalArrivalTime: 20 Jun 2022 20:27:23.0568 (UTC) FILETIME=[26327300:01D884E4] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1655757415720100001 Content-Type: text/plain; charset="utf-8" Check if each page dir/table base address is properly aligned and log a guest error if not, as real hardware behave incorrectly in this case. These checks are only performed when DEBUG_MMU is defined, to avoid hurting the performance. Signed-off-by: Leandro Lupori --- target/ppc/mmu-radix64.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 2f0bcbfe2e..80d945a7c3 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -28,6 +28,8 @@ #include "mmu-radix64.h" #include "mmu-book3s-v3.h" =20 +/* #define DEBUG_MMU */ + static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env, vaddr eaddr, uint64_t *lpid, uint64_t = *pid) @@ -277,6 +279,16 @@ static int ppc_radix64_next_level(AddressSpace *as, va= ddr eaddr, if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */ ++*level; *nls =3D pde & R_PDE_NLS; + +#ifdef DEBUG_MMU + if ((pde & R_PDE_NLB) & MAKE_64BIT_MASK(0, *nls + 3)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: misaligned page dir/table base: 0x%"VADDR_PRIx + " page dir size: 0x%"PRIx64" level: %d\n", + __func__, (pde & R_PDE_NLB), BIT(*nls + 3), *level); + } +#endif + index =3D eaddr >> (*psize - *nls); /* Shift */ index &=3D ((1UL << *nls) - 1); /* Mask */ *pte_addr =3D (pde & R_PDE_NLB) + (index * sizeof(pde)); @@ -297,6 +309,15 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vad= dr eaddr, return 1; } =20 +#ifdef DEBUG_MMU + if (base_addr & MAKE_64BIT_MASK(0, nls + 3)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: misaligned page dir base: 0x%"VADDR_PRIx + " page dir size: 0x%"PRIx64"\n", + __func__, base_addr, BIT(nls + 3)); + } +#endif + index =3D eaddr >> (*psize - nls); /* Shift */ index &=3D ((1UL << nls) - 1); /* Mask */ *pte_addr =3D base_addr + (index * sizeof(pde)); --=20 2.25.1