]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - arch/x86/kernel/aperture_64.c
x86: clean up arch/x86/ia32/mmap32.c
[mirror_ubuntu-jammy-kernel.git] / arch / x86 / kernel / aperture_64.c
CommitLineData
1da177e4
LT
1/*
2 * Firmware replacement code.
3 *
4 * Work around broken BIOSes that don't set an aperture or only set the
5 * aperture in the AGP bridge.
6 * If all fails map the aperture over some low memory. This is cheaper than
7 * doing bounce buffering. The memory is lost. This is done at early boot
8 * because only the bootmem allocator can allocate 32+MB.
9 *
10 * Copyright 2002 Andi Kleen, SuSE Labs.
1da177e4 11 */
1da177e4
LT
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/init.h>
15#include <linux/bootmem.h>
16#include <linux/mmzone.h>
17#include <linux/pci_ids.h>
18#include <linux/pci.h>
19#include <linux/bitops.h>
56dd669a 20#include <linux/ioport.h>
1da177e4
LT
21#include <asm/e820.h>
22#include <asm/io.h>
395624fc 23#include <asm/gart.h>
1da177e4 24#include <asm/pci-direct.h>
ca8642f6 25#include <asm/dma.h>
a32073bf 26#include <asm/k8.h>
1da177e4 27
0440d4c0
JR
28int gart_iommu_aperture;
29int gart_iommu_aperture_disabled __initdata = 0;
30int gart_iommu_aperture_allowed __initdata = 0;
1da177e4
LT
31
32int fallback_aper_order __initdata = 1; /* 64MB */
33int fallback_aper_force __initdata = 0;
34
35int fix_aperture __initdata = 1;
36
56dd669a
AD
37static struct resource gart_resource = {
38 .name = "GART",
39 .flags = IORESOURCE_MEM,
40};
41
42static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
43{
44 gart_resource.start = aper_base;
45 gart_resource.end = aper_base + aper_size - 1;
46 insert_resource(&iomem_resource, &gart_resource);
47}
48
42442ed5
AM
49/* This code runs before the PCI subsystem is initialized, so just
50 access the northbridge directly. */
1da177e4
LT
51
52static u32 __init allocate_aperture(void)
53{
1da177e4
LT
54 u32 aper_size;
55 void *p;
56
57 if (fallback_aper_order > 7)
58 fallback_aper_order = 7;
59 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
60
61 /*
42442ed5 62 * Aperture has to be naturally aligned. This means an 2GB aperture won't
d5d9ca6d 63 * have much chance of finding a place in the lower 4GB of memory.
42442ed5
AM
64 * Unfortunately we cannot move it up because that would make the
65 * IOMMU useless.
1da177e4 66 */
82d1bb72 67 p = __alloc_bootmem_nopanic(aper_size, aper_size, 0);
1da177e4
LT
68 if (!p || __pa(p)+aper_size > 0xffffffff) {
69 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
70 p, aper_size>>10);
71 if (p)
82d1bb72 72 free_bootmem(__pa(p), aper_size);
1da177e4
LT
73 return 0;
74 }
42442ed5 75 printk("Mapping aperture over %d KB of RAM @ %lx\n",
1da177e4 76 aper_size >> 10, __pa(p));
56dd669a 77 insert_aperture_resource((u32)__pa(p), aper_size);
1da177e4
LT
78 return (u32)__pa(p);
79}
80
a32073bf 81static int __init aperture_valid(u64 aper_base, u32 aper_size)
1da177e4
LT
82{
83 if (!aper_base)
84 return 0;
85 if (aper_size < 64*1024*1024) {
a32073bf 86 printk("Aperture too small (%d MB)\n", aper_size>>20);
1da177e4
LT
87 return 0;
88 }
547c5355 89 if (aper_base + aper_size > 0x100000000UL) {
a32073bf 90 printk("Aperture beyond 4GB. Ignoring.\n");
1da177e4
LT
91 return 0;
92 }
eee5a9fa 93 if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
a32073bf 94 printk("Aperture pointing to e820 RAM. Ignoring.\n");
1da177e4
LT
95 return 0;
96 }
97 return 1;
98}
99
42442ed5 100/* Find a PCI capability */
1da177e4
LT
101static __u32 __init find_cap(int num, int slot, int func, int cap)
102{
103 u8 pos;
104 int bytes;
105 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
106 return 0;
107 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
108 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
109 u8 id;
110 pos &= ~3;
111 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
112 if (id == 0xff)
113 break;
114 if (id == cap)
115 return pos;
116 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
117 }
118 return 0;
119}
120
121/* Read a standard AGPv3 bridge header */
122static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
123{
124 u32 apsize;
125 u32 apsizereg;
126 int nbits;
127 u32 aper_low, aper_hi;
128 u64 aper;
129
130 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
131 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
132 if (apsizereg == 0xffffffff) {
133 printk("APSIZE in AGP bridge unreadable\n");
134 return 0;
135 }
136
137 apsize = apsizereg & 0xfff;
138 /* Some BIOS use weird encodings not in the AGPv3 table. */
139 if (apsize & 0xff)
140 apsize |= 0xf00;
141 nbits = hweight16(apsize);
142 *order = 7 - nbits;
143 if ((int)*order < 0) /* < 32MB */
144 *order = 0;
145
146 aper_low = read_pci_config(num,slot,func, 0x10);
147 aper_hi = read_pci_config(num,slot,func,0x14);
148 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
149
150 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
151 aper, 32 << *order, apsizereg);
152
a32073bf 153 if (!aperture_valid(aper, (32*1024*1024) << *order))
1da177e4
LT
154 return 0;
155 return (u32)aper;
156}
157
158/* Look for an AGP bridge. Windows only expects the aperture in the
159 AGP bridge and some BIOS forget to initialize the Northbridge too.
160 Work around this here.
161
162 Do an PCI bus scan by hand because we're running before the PCI
163 subsystem.
164
165 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
166 generically. It's probably overkill to always scan all slots because
167 the AGP bridges should be always an own bus on the HT hierarchy,
168 but do it here for future safety. */
169static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
170{
171 int num, slot, func;
172
173 /* Poor man's PCI discovery */
9c01dda0 174 for (num = 0; num < 256; num++) {
1da177e4
LT
175 for (slot = 0; slot < 32; slot++) {
176 for (func = 0; func < 8; func++) {
177 u32 class, cap;
178 u8 type;
179 class = read_pci_config(num,slot,func,
180 PCI_CLASS_REVISION);
181 if (class == 0xffffffff)
182 break;
183
184 switch (class >> 16) {
185 case PCI_CLASS_BRIDGE_HOST:
186 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
187 /* AGP bridge? */
188 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
189 if (!cap)
190 break;
191 *valid_agp = 1;
192 return read_agp(num,slot,func,cap,order);
193 }
194
195 /* No multi-function device? */
196 type = read_pci_config_byte(num,slot,func,
197 PCI_HEADER_TYPE);
198 if (!(type & 0x80))
199 break;
200 }
201 }
202 }
203 printk("No AGP bridge found\n");
204 return 0;
205}
206
0440d4c0 207void __init gart_iommu_hole_init(void)
1da177e4
LT
208{
209 int fix, num;
50895c5d 210 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
1da177e4
LT
211 u64 aper_base, last_aper_base = 0;
212 int valid_agp = 0;
213
0440d4c0
JR
214 if (gart_iommu_aperture_disabled || !fix_aperture ||
215 !early_pci_allowed())
1da177e4
LT
216 return;
217
753811dc 218 printk(KERN_INFO "Checking aperture...\n");
1da177e4
LT
219
220 fix = 0;
221 for (num = 24; num < 32; num++) {
a32073bf
AK
222 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
223 continue;
1da177e4 224
8d4f6b93 225 iommu_detected = 1;
0440d4c0 226 gart_iommu_aperture = 1;
1da177e4
LT
227
228 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
229 aper_size = (32 * 1024 * 1024) << aper_order;
230 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
231 aper_base <<= 25;
232
233 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
234 aper_base, aper_size>>20);
235
a32073bf 236 if (!aperture_valid(aper_base, aper_size)) {
1da177e4
LT
237 fix = 1;
238 break;
239 }
240
241 if ((last_aper_order && aper_order != last_aper_order) ||
242 (last_aper_base && aper_base != last_aper_base)) {
243 fix = 1;
244 break;
245 }
246 last_aper_order = aper_order;
247 last_aper_base = aper_base;
248 }
249
56dd669a
AD
250 if (!fix && !fallback_aper_force) {
251 if (last_aper_base) {
252 unsigned long n = (32 * 1024 * 1024) << last_aper_order;
253 insert_aperture_resource((u32)last_aper_base, n);
254 }
1da177e4 255 return;
56dd669a 256 }
1da177e4
LT
257
258 if (!fallback_aper_force)
259 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
260
261 if (aper_alloc) {
262 /* Got the aperture from the AGP bridge */
63f02fd7
AK
263 } else if (swiotlb && !valid_agp) {
264 /* Do nothing */
60b08c67 265 } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) ||
1da177e4
LT
266 force_iommu ||
267 valid_agp ||
268 fallback_aper_force) {
269 printk("Your BIOS doesn't leave a aperture memory hole\n");
270 printk("Please enable the IOMMU option in the BIOS setup\n");
42442ed5
AM
271 printk("This costs you %d MB of RAM\n",
272 32 << fallback_aper_order);
1da177e4
LT
273
274 aper_order = fallback_aper_order;
275 aper_alloc = allocate_aperture();
276 if (!aper_alloc) {
277 /* Could disable AGP and IOMMU here, but it's probably
278 not worth it. But the later users cannot deal with
279 bad apertures and turning on the aperture over memory
280 causes very strange problems, so it's better to
281 panic early. */
282 panic("Not enough memory for aperture");
283 }
284 } else {
285 return;
286 }
287
288 /* Fix up the north bridges */
289 for (num = 24; num < 32; num++) {
a32073bf 290 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
1da177e4
LT
291 continue;
292
293 /* Don't enable translation yet. That is done later.
294 Assume this BIOS didn't initialise the GART so
295 just overwrite all previous bits */
296 write_pci_config(0, num, 3, 0x90, aper_order<<1);
297 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
298 }
299}