aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLianbo Jiang <lijiang@redhat.com>2019-04-22 21:30:06 -0400
committerBorislav Petkov <bp@suse.de>2019-06-20 03:58:07 -0400
commit5da04cc86d1215fd9fe0e5c88ead6e8428a75e56 (patch)
tree6e0d02058d6d5abf71bf78c46af644ed267a4c1e
parentae9e13d621d6795ec1ad6bf10bd2549c6c3feca4 (diff)
x86/mm: Rework ioremap resource mapping determination
On ioremap(), __ioremap_check_mem() does a couple of checks on the supplied memory range to determine how the range should be mapped and in particular what protection flags should be used. Generalize the procedure by introducing IORES_MAP_* flags which control different aspects of the ioremapping and use them in the respective helpers which determine which descriptor flags should be set per range. [ bp: - Rewrite commit message. - Add/improve comments. - Reflow __ioremap_caller()'s args. - s/__ioremap_check_desc/__ioremap_check_encrypted/g; - s/__ioremap_res_check/__ioremap_collect_map_flags/g; - clarify __ioremap_check_ram()'s purpose. ] Signed-off-by: Lianbo Jiang <lijiang@redhat.com> Co-developed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: bhe@redhat.com Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: dyoung@redhat.com Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: kexec@lists.infradead.org Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: x86-ml <x86@kernel.org> Link: https://lkml.kernel.org/r/20190423013007.17838-3-lijiang@redhat.com
-rw-r--r--arch/x86/mm/ioremap.c71
-rw-r--r--include/linux/ioport.h9
2 files changed, 54 insertions, 26 deletions
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 4b6423e7bd21..e500f1df1140 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -28,9 +28,11 @@
28 28
29#include "physaddr.h" 29#include "physaddr.h"
30 30
31struct ioremap_mem_flags { 31/*
32 bool system_ram; 32 * Descriptor controlling ioremap() behavior.
33 bool desc_other; 33 */
34struct ioremap_desc {
35 unsigned int flags;
34}; 36};
35 37
36/* 38/*
@@ -62,13 +64,14 @@ int ioremap_change_attr(unsigned long vaddr, unsigned long size,
62 return err; 64 return err;
63} 65}
64 66
65static bool __ioremap_check_ram(struct resource *res) 67/* Does the range (or a subset of) contain normal RAM? */
68static unsigned int __ioremap_check_ram(struct resource *res)
66{ 69{
67 unsigned long start_pfn, stop_pfn; 70 unsigned long start_pfn, stop_pfn;
68 unsigned long i; 71 unsigned long i;
69 72
70 if ((res->flags & IORESOURCE_SYSTEM_RAM) != IORESOURCE_SYSTEM_RAM) 73 if ((res->flags & IORESOURCE_SYSTEM_RAM) != IORESOURCE_SYSTEM_RAM)
71 return false; 74 return 0;
72 75
73 start_pfn = (res->start + PAGE_SIZE - 1) >> PAGE_SHIFT; 76 start_pfn = (res->start + PAGE_SIZE - 1) >> PAGE_SHIFT;
74 stop_pfn = (res->end + 1) >> PAGE_SHIFT; 77 stop_pfn = (res->end + 1) >> PAGE_SHIFT;
@@ -76,28 +79,44 @@ static bool __ioremap_check_ram(struct resource *res)
76 for (i = 0; i < (stop_pfn - start_pfn); ++i) 79 for (i = 0; i < (stop_pfn - start_pfn); ++i)
77 if (pfn_valid(start_pfn + i) && 80 if (pfn_valid(start_pfn + i) &&
78 !PageReserved(pfn_to_page(start_pfn + i))) 81 !PageReserved(pfn_to_page(start_pfn + i)))
79 return true; 82 return IORES_MAP_SYSTEM_RAM;
80 } 83 }
81 84
82 return false; 85 return 0;
83} 86}
84 87
85static int __ioremap_check_desc_other(struct resource *res) 88/*
89 * In a SEV guest, NONE and RESERVED should not be mapped encrypted because
90 * there the whole memory is already encrypted.
91 */
92static unsigned int __ioremap_check_encrypted(struct resource *res)
86{ 93{
87 return (res->desc != IORES_DESC_NONE); 94 if (!sev_active())
95 return 0;
96
97 switch (res->desc) {
98 case IORES_DESC_NONE:
99 case IORES_DESC_RESERVED:
100 break;
101 default:
102 return IORES_MAP_ENCRYPTED;
103 }
104
105 return 0;
88} 106}
89 107
90static int __ioremap_res_check(struct resource *res, void *arg) 108static int __ioremap_collect_map_flags(struct resource *res, void *arg)
91{ 109{
92 struct ioremap_mem_flags *flags = arg; 110 struct ioremap_desc *desc = arg;
93 111
94 if (!flags->system_ram) 112 if (!(desc->flags & IORES_MAP_SYSTEM_RAM))
95 flags->system_ram = __ioremap_check_ram(res); 113 desc->flags |= __ioremap_check_ram(res);
96 114
97 if (!flags->desc_other) 115 if (!(desc->flags & IORES_MAP_ENCRYPTED))
98 flags->desc_other = __ioremap_check_desc_other(res); 116 desc->flags |= __ioremap_check_encrypted(res);
99 117
100 return flags->system_ram && flags->desc_other; 118 return ((desc->flags & (IORES_MAP_SYSTEM_RAM | IORES_MAP_ENCRYPTED)) ==
119 (IORES_MAP_SYSTEM_RAM | IORES_MAP_ENCRYPTED));
101} 120}
102 121
103/* 122/*
@@ -106,15 +125,15 @@ static int __ioremap_res_check(struct resource *res, void *arg)
106 * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES). 125 * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES).
107 */ 126 */
108static void __ioremap_check_mem(resource_size_t addr, unsigned long size, 127static void __ioremap_check_mem(resource_size_t addr, unsigned long size,
109 struct ioremap_mem_flags *flags) 128 struct ioremap_desc *desc)
110{ 129{
111 u64 start, end; 130 u64 start, end;
112 131
113 start = (u64)addr; 132 start = (u64)addr;
114 end = start + size - 1; 133 end = start + size - 1;
115 memset(flags, 0, sizeof(*flags)); 134 memset(desc, 0, sizeof(struct ioremap_desc));
116 135
117 walk_mem_res(start, end, flags, __ioremap_res_check); 136 walk_mem_res(start, end, desc, __ioremap_collect_map_flags);
118} 137}
119 138
120/* 139/*
@@ -131,15 +150,15 @@ static void __ioremap_check_mem(resource_size_t addr, unsigned long size,
131 * have to convert them into an offset in a page-aligned mapping, but the 150 * have to convert them into an offset in a page-aligned mapping, but the
132 * caller shouldn't need to know that small detail. 151 * caller shouldn't need to know that small detail.
133 */ 152 */
134static void __iomem *__ioremap_caller(resource_size_t phys_addr, 153static void __iomem *
135 unsigned long size, enum page_cache_mode pcm, 154__ioremap_caller(resource_size_t phys_addr, unsigned long size,
136 void *caller, bool encrypted) 155 enum page_cache_mode pcm, void *caller, bool encrypted)
137{ 156{
138 unsigned long offset, vaddr; 157 unsigned long offset, vaddr;
139 resource_size_t last_addr; 158 resource_size_t last_addr;
140 const resource_size_t unaligned_phys_addr = phys_addr; 159 const resource_size_t unaligned_phys_addr = phys_addr;
141 const unsigned long unaligned_size = size; 160 const unsigned long unaligned_size = size;
142 struct ioremap_mem_flags mem_flags; 161 struct ioremap_desc io_desc;
143 struct vm_struct *area; 162 struct vm_struct *area;
144 enum page_cache_mode new_pcm; 163 enum page_cache_mode new_pcm;
145 pgprot_t prot; 164 pgprot_t prot;
@@ -158,12 +177,12 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
158 return NULL; 177 return NULL;
159 } 178 }
160 179
161 __ioremap_check_mem(phys_addr, size, &mem_flags); 180 __ioremap_check_mem(phys_addr, size, &io_desc);
162 181
163 /* 182 /*
164 * Don't allow anybody to remap normal RAM that we're using.. 183 * Don't allow anybody to remap normal RAM that we're using..
165 */ 184 */
166 if (mem_flags.system_ram) { 185 if (io_desc.flags & IORES_MAP_SYSTEM_RAM) {
167 WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", 186 WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n",
168 &phys_addr, &last_addr); 187 &phys_addr, &last_addr);
169 return NULL; 188 return NULL;
@@ -201,7 +220,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
201 * resulting mapping. 220 * resulting mapping.
202 */ 221 */
203 prot = PAGE_KERNEL_IO; 222 prot = PAGE_KERNEL_IO;
204 if ((sev_active() && mem_flags.desc_other) || encrypted) 223 if ((io_desc.flags & IORES_MAP_ENCRYPTED) || encrypted)
205 prot = pgprot_encrypted(prot); 224 prot = pgprot_encrypted(prot);
206 225
207 switch (pcm) { 226 switch (pcm) {
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 6ed59de48bd5..5db386cfc2d4 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -12,6 +12,7 @@
12#ifndef __ASSEMBLY__ 12#ifndef __ASSEMBLY__
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/bits.h>
15/* 16/*
16 * Resources are tree-like, allowing 17 * Resources are tree-like, allowing
17 * nesting etc.. 18 * nesting etc..
@@ -136,6 +137,14 @@ enum {
136 IORES_DESC_RESERVED = 8, 137 IORES_DESC_RESERVED = 8,
137}; 138};
138 139
140/*
141 * Flags controlling ioremap() behavior.
142 */
143enum {
144 IORES_MAP_SYSTEM_RAM = BIT(0),
145 IORES_MAP_ENCRYPTED = BIT(1),
146};
147
139/* helpers to define resources */ 148/* helpers to define resources */
140#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \ 149#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \
141 { \ 150 { \