From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-x230.google.com (mail-wm0-x230.google.com [IPv6:2a00:1450:400c:c09::230]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5A801802A7 for ; Mon, 6 Mar 2017 08:40:58 -0800 (PST) Received: by mail-wm0-x230.google.com with SMTP id n11so68790755wma.1 for ; Mon, 06 Mar 2017 08:40:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Eg6d21wiaATFSdAY+VMMY2OMX862hu+Fq3xo/bWnozE=; b=AF8du+Yp0AMBXOS5naAKo0BVMCcYh2p7hbmUbiap9X7s3WYxT4qq+e+yd8pCN51oz+ lv/Wgkrp6ApJigYMDyVtrwLnrL7cTkIGXm0Tcly2PgFPIqoapO5gEPRnoV5WhXlI99Fd 1E2n/Xj3vLXDvrAQOeF5kUrZZHerffEwu2Wqk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=Eg6d21wiaATFSdAY+VMMY2OMX862hu+Fq3xo/bWnozE=; b=BQ9fbgm1kB+JRbZpVp/CcwUNjJUia+NMzDYE/yNPdxgohpvKe5VdJutNnkc016U2Eo 2iq3GlTGV8Hyt8ZmhdVK2oNY3nfyrRqRk/T6wb4RPuHtCNBUYvr8cf/mQOf9s7O6s8Q5 lYm/CZu1PzNIfL39wC3rJDTJM/iH3WxGBzYcyTvaaIrK9PJeXkYkG8KpsiZfYkqD43F0 bLnXdprnA6q8YxOvnTjY05mV8wkeEeSeFlSh7m7/Ccj7LTpcOQI7AQiQGQv7rbWPSCKe Y7TVIoNLk7bCgItbSK/hpLl1nlz7XxRgX7/N/McabB4t+3Js0/oXieKjgQvI34a+uM73 Mnrw== X-Gm-Message-State: AMke39niygbdRYB4uJNEwcbeOY8ZJXMsn2mbJBbJXtcm3PoKUF+JU5TbxrDyXVr+54lEc64q X-Received: by 10.28.46.213 with SMTP id u204mr11825485wmu.136.1488818449754; Mon, 06 Mar 2017 08:40:49 -0800 (PST) Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id w207sm15427508wmw.29.2017.03.06.08.40.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Mar 2017 08:40:48 -0800 (PST) Date: Mon, 6 Mar 2017 16:40:47 +0000 From: Leif Lindholm To: Ard Biesheuvel Cc: "edk2-devel@lists.01.org" , Laszlo Ersek Message-ID: <20170306164047.GC16034@bivouac.eciton.net> References: <1488450976-16257-1-git-send-email-ard.biesheuvel@linaro.org> <1488450976-16257-4-git-send-email-ard.biesheuvel@linaro.org> <20170306144834.GV16034@bivouac.eciton.net> MIME-Version: 1.0 In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) Subject: Re: [PATCH v2 3/4] ArmPkg/CpuDxe ARM: honour RO/XP attributes in SetMemoryAttributes() X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Mar 2017 16:40:58 -0000 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Mar 06, 2017 at 04:11:50PM +0100, Ard Biesheuvel wrote: > On 6 March 2017 at 15:48, Leif Lindholm wrote: > > On Thu, Mar 02, 2017 at 10:36:15AM +0000, Ard Biesheuvel wrote: > >> Enable the use of strict memory permissions on ARM by processing the > >> EFI_MEMORY_RO and EFI_MEMORY_XP rather than ignoring them. As before, > >> calls to CpuArchProtocol::SetMemoryAttributes that only set RO/XP > >> bits will preserve the cacheability attributes. Permissions attributes > >> are not preserved when setting the memory type only: the way the memory > >> permission attributes are defined does not allows for that, and so this > >> situation does not deviate from other architectures. > >> > >> Contributed-under: TianoCore Contribution Agreement 1.0 > >> Signed-off-by: Ard Biesheuvel > >> --- > >> ArmPkg/Drivers/CpuDxe/Arm/Mmu.c | 151 ++++++++------------ > >> 1 file changed, 62 insertions(+), 89 deletions(-) > >> > >> diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c > >> index 26b637e7658f..6dd749dadf8b 100644 > >> --- a/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c > >> +++ b/ArmPkg/Drivers/CpuDxe/Arm/Mmu.c > >> @@ -374,50 +374,41 @@ UpdatePageEntries ( > >> > >> // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone) > >> // EntryValue: values at bit positions specified by EntryMask > >> - EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK; > >> - EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE; > >> + EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK; > >> + if ((Attributes & EFI_MEMORY_XP) != 0) { > >> + EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN; > >> + } else { > >> + EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE; > >> + } > >> + > >> // Although the PI spec is unclear on this the GCD guarantees that only > >> // one Attribute bit is set at a time, so we can safely use a switch statement > > > > But the switch statement is going away. > > > > The change effectively introduces a guaranteed priority of > > interpretation if the spec is violated. Say something about this order > > being arbitrarily decided due to PI spce guarantee instead? > > > > Indeed. OK, I'll hold back to see what you come up with :) > >> - switch (Attributes) { > >> - case EFI_MEMORY_UC: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> - // map to strongly ordered > >> - EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0 > >> - break; > >> - > >> - case EFI_MEMORY_WC: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> - // map to normal non-cachable > >> - EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0 > >> - break; > >> - > >> - case EFI_MEMORY_WT: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> - // write through with no-allocate > >> - EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0 > >> - break; > >> - > >> - case EFI_MEMORY_WB: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> - // write back (with allocate) > >> - EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1 > >> - break; > >> - > >> - case EFI_MEMORY_WP: > >> - case EFI_MEMORY_XP: > >> - case EFI_MEMORY_UCE: > >> - // cannot be implemented UEFI definition unclear for ARM > >> - // Cause a page fault if these ranges are accessed. > >> - EntryValue = TT_DESCRIPTOR_PAGE_TYPE_FAULT; > >> - DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting page %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes)); > >> - break; > >> + if ((Attributes & EFI_MEMORY_UC) != 0) { > > > > Or should these be "Attributes & Mask" == "ATTRIBUTE"? > > > > I know this is more idiomatic for EDK2, but the mask *is* the > attribute in this case, and so the former implies the latter. If the > mask were OK ... in that case, could you just drop the != 0? > (EFI_MEMORY_WB | EFI_MEMORY_WT | etc > > it would make more sense do to the latter I think > > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> + // map to strongly ordered > >> + EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0 > >> + } else if ((Attributes & EFI_MEMORY_WC) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> + // map to normal non-cachable > >> + EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0 > >> + } else if ((Attributes & EFI_MEMORY_WT) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> + // write through with no-allocate > >> + EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0 > >> + } else if ((Attributes & EFI_MEMORY_WB) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK; > >> + // write back (with allocate) > >> + EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1 > >> + } > >> > >> - default: > >> - return EFI_UNSUPPORTED; > > > > Do we not want a fallback handling for the if-form as well? > > > > No, and that is actually the point of this patch. SetMemoryAttributes > may be called without a memory type argument, in which case it only > modifies permission attributes, and leaves the memory type attributes > only. But should there not be a final "else if (Attributes & CACHE_ATTRIBUTE_MASK)" error path then? / Leif > >> + if ((Attributes & EFI_MEMORY_RO) != 0) { > >> + EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO; > >> + } else { > >> + EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW; > >> } > >> > >> // Obtain page table base > >> @@ -520,53 +511,42 @@ UpdateSectionEntries ( > >> // EntryValue: values at bit positions specified by EntryMask > >> > >> // Make sure we handle a section range that is unmapped > >> - EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK; > >> + EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN_MASK | > >> + TT_DESCRIPTOR_SECTION_AP_MASK; > >> EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION; > >> > >> // Although the PI spec is unclear on this the GCD guarantees that only > >> // one Attribute bit is set at a time, so we can safely use a switch statement > > > > Repeat of above. > > > >> - switch(Attributes) { > >> - case EFI_MEMORY_UC: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> - // map to strongly ordered > >> - EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0 > >> - break; > >> - > >> - case EFI_MEMORY_WC: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> - // map to normal non-cachable > >> - EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0 > >> - break; > >> - > >> - case EFI_MEMORY_WT: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> - // write through with no-allocate > >> - EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0 > >> - break; > >> - > >> - case EFI_MEMORY_WB: > >> - // modify cacheability attributes > >> - EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> - // write back (with allocate) > >> - EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1 > >> - break; > >> - > >> - case EFI_MEMORY_WP: > >> - case EFI_MEMORY_XP: > >> - case EFI_MEMORY_RP: > >> - case EFI_MEMORY_UCE: > >> - // cannot be implemented UEFI definition unclear for ARM > >> - // Cause a page fault if these ranges are accessed. > >> - EntryValue = TT_DESCRIPTOR_SECTION_TYPE_FAULT; > >> - DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting section %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes)); > >> - break; > >> + if ((Attributes & EFI_MEMORY_UC) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> + // map to strongly ordered > >> + EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0 > >> + } else if ((Attributes & EFI_MEMORY_WC) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> + // map to normal non-cachable > >> + EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0 > >> + } else if ((Attributes & EFI_MEMORY_WT) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> + // write through with no-allocate > >> + EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0 > >> + } else if ((Attributes & EFI_MEMORY_WB) != 0) { > >> + // modify cacheability attributes > >> + EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK; > >> + // write back (with allocate) > >> + EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1 > >> + } > > > > (Again, same questions as above.) > > > >> > >> + if ((Attributes & EFI_MEMORY_RO) != 0) { > >> + EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO; > >> + } else { > >> + EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW; > >> + } > >> > >> - default: > >> - return EFI_UNSUPPORTED; > >> + if ((Attributes & EFI_MEMORY_XP) != 0) { > >> + EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK; > >> } > >> > >> // obtain page table base > >> @@ -693,13 +673,6 @@ SetMemoryAttributes ( > >> UINT64 ChunkLength; > >> BOOLEAN FlushTlbs; > >> > >> - // > >> - // Ignore invocations that only modify permission bits > >> - // > >> - if ((Attributes & EFI_MEMORY_CACHETYPE_MASK) == 0) { > >> - return EFI_SUCCESS; > >> - } > >> - > >> FlushTlbs = FALSE; > >> while (Length > 0) { > >> if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) && > >> -- > >> 2.7.4 > >>