]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - arch/x86_64/kernel/aperture.c
[PATCH] x86_64: Use the e820 hole to map the IOMMU/AGP aperture
[linux-3.10.git] / arch / x86_64 / kernel / aperture.c
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.
11  * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $
12  */
13 #include <linux/config.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/init.h>
17 #include <linux/bootmem.h>
18 #include <linux/mmzone.h>
19 #include <linux/pci_ids.h>
20 #include <linux/pci.h>
21 #include <linux/bitops.h>
22 #include <asm/e820.h>
23 #include <asm/io.h>
24 #include <asm/proto.h>
25 #include <asm/pci-direct.h>
26
27 int iommu_aperture;
28 int iommu_aperture_disabled __initdata = 0;
29 int iommu_aperture_allowed __initdata = 0;
30
31 int fallback_aper_order __initdata = 1; /* 64MB */
32 int fallback_aper_force __initdata = 0; 
33
34 int fix_aperture __initdata = 1;
35
36 #define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
37
38 static struct resource aper_res = {
39         .name = "Aperture",
40         .flags = IORESOURCE_MEM,
41 };
42
43 static u32 __init allocate_aperture(void) 
44 {
45 #ifdef CONFIG_DISCONTIGMEM
46         pg_data_t *nd0 = NODE_DATA(0);
47 #else
48         pg_data_t *nd0 = &contig_page_data;
49 #endif  
50         u32 aper_size;
51         void *p; 
52
53         if (fallback_aper_order > 7) 
54                 fallback_aper_order = 7; 
55         aper_size = (32 * 1024 * 1024) << fallback_aper_order; 
56
57         /* 
58          * Aperture has to be naturally aligned. This means an 2GB
59          * aperture won't have much chances to find a place in the
60          * lower 4GB of memory.  Unfortunately we cannot move it up
61          * because that would make the IOMMU useless.
62          */
63
64         /* First try to find some free unused space */
65         if (!allocate_resource(&iomem_resource, &aper_res,
66                                aper_size,
67                                0, 0xffffffff,
68                                aper_size,
69                                NULL, NULL)) {
70                 printk(KERN_INFO "Putting aperture at %lx-%lx\n",
71                        aper_res.start, aper_res.end);
72                 return aper_res.start;
73         }
74
75         /* No free space found. Go on to waste some memory... */
76         p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0); 
77         if (!p || __pa(p)+aper_size > 0xffffffff) {
78                 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
79                        p, aper_size>>10);
80                 if (p)
81                         free_bootmem_node(nd0, (unsigned long)p, aper_size); 
82                 return 0;
83         }
84         printk("Mapping aperture over %d KB of precious RAM @ %lx\n",
85                aper_size >> 10, __pa(p)); 
86         return (u32)__pa(p); 
87 }
88
89 static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size) 
90
91         if (!aper_base) 
92                 return 0;
93         if (aper_size < 64*1024*1024) { 
94                 printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20); 
95                 return 0;
96         }
97         if (aper_base + aper_size >= 0xffffffff) { 
98                 printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
99                 return 0; 
100         }
101         if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {  
102                 printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
103                 return 0; 
104         } 
105         /* Don't check the resource here because the aperture is usually
106            in an e820 reserved area, and we allocated these earlier. */
107         return 1;
108
109
110 /*
111  * Find a PCI capability.
112  * This code runs before the PCI subsystem is initialized, so just
113  * access the northbridge directly.
114  */
115 static __u32 __init find_cap(int num, int slot, int func, int cap) 
116
117         u8 pos;
118         int bytes;
119         if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
120                 return 0;
121         pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
122         for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { 
123                 u8 id;
124                 pos &= ~3; 
125                 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
126                 if (id == 0xff)
127                         break;
128                 if (id == cap) 
129                         return pos; 
130                 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT); 
131         } 
132         return 0;
133
134
135 /* Read a standard AGPv3 bridge header */
136 static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
137
138         u32 apsize;
139         u32 apsizereg;
140         int nbits;
141         u32 aper_low, aper_hi;
142         u64 aper;
143
144         printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
145         apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
146         if (apsizereg == 0xffffffff) {
147                 printk("APSIZE in AGP bridge unreadable\n");
148                 return 0;
149         }
150
151         apsize = apsizereg & 0xfff;
152         /* Some BIOS use weird encodings not in the AGPv3 table. */
153         if (apsize & 0xff) 
154                 apsize |= 0xf00; 
155         nbits = hweight16(apsize);
156         *order = 7 - nbits;
157         if ((int)*order < 0) /* < 32MB */
158                 *order = 0;
159         
160         aper_low = read_pci_config(num,slot,func, 0x10);
161         aper_hi = read_pci_config(num,slot,func,0x14);
162         aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
163
164         printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 
165                aper, 32 << *order, apsizereg);
166
167         if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
168             return 0;
169         return (u32)aper; 
170
171
172 /* Look for an AGP bridge. Windows only expects the aperture in the
173    AGP bridge and some BIOS forget to initialize the Northbridge too.
174    Work around this here. 
175
176    Do an PCI bus scan by hand because we're running before the PCI
177    subsystem. 
178
179    All K8 AGP bridges are AGPv3 compliant, so we can do this scan
180    generically. It's probably overkill to always scan all slots because
181    the AGP bridges should be always an own bus on the HT hierarchy, 
182    but do it here for future safety. */
183 static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
184 {
185         int num, slot, func;
186
187         /* Poor man's PCI discovery */
188         for (num = 0; num < 32; num++) { 
189                 for (slot = 0; slot < 32; slot++) { 
190                         for (func = 0; func < 8; func++) { 
191                                 u32 class, cap;
192                                 u8 type;
193                                 class = read_pci_config(num,slot,func,
194                                                         PCI_CLASS_REVISION);
195                                 if (class == 0xffffffff)
196                                         break; 
197                                 
198                                 switch (class >> 16) { 
199                                 case PCI_CLASS_BRIDGE_HOST:
200                                 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
201                                         /* AGP bridge? */
202                                         cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
203                                         if (!cap)
204                                                 break;
205                                         *valid_agp = 1; 
206                                         return read_agp(num,slot,func,cap,order);
207                                 } 
208                                 
209                                 /* No multi-function device? */
210                                 type = read_pci_config_byte(num,slot,func,
211                                                                PCI_HEADER_TYPE);
212                                 if (!(type & 0x80))
213                                         break;
214                         } 
215                 } 
216         }
217         printk("No AGP bridge found\n"); 
218         return 0;
219 }
220
221 void __init iommu_hole_init(void) 
222
223         int fix, num; 
224         u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0;
225         u64 aper_base, last_aper_base = 0;
226         int valid_agp = 0;
227
228         if (iommu_aperture_disabled || !fix_aperture)
229                 return;
230
231         printk("Checking aperture...\n"); 
232
233         fix = 0;
234         for (num = 24; num < 32; num++) {               
235                 char name[30];
236                 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
237                         continue;       
238
239                 iommu_aperture = 1; 
240
241                 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 
242                 aper_size = (32 * 1024 * 1024) << aper_order; 
243                 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
244                 aper_base <<= 25; 
245
246                 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, 
247                        aper_base, aper_size>>20);
248                 
249                 sprintf(name, "northbridge cpu %d", num-24); 
250
251                 if (!aperture_valid(name, aper_base, aper_size)) { 
252                         fix = 1; 
253                         break; 
254                 }
255
256                 if ((last_aper_order && aper_order != last_aper_order) ||
257                     (last_aper_base && aper_base != last_aper_base)) {
258                         fix = 1;
259                         break;
260                 }
261                 last_aper_order = aper_order;
262                 last_aper_base = aper_base;
263         } 
264
265         if (!fix && !fallback_aper_force) 
266                 return; 
267
268         if (!fallback_aper_force)
269                 aper_alloc = search_agp_bridge(&aper_order, &valid_agp); 
270                 
271         if (aper_alloc) { 
272                 /* Got the aperture from the AGP bridge */
273         } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
274                    force_iommu ||
275                    valid_agp ||
276                    fallback_aper_force) { 
277                 printk("Your BIOS doesn't leave a aperture memory hole\n");
278                 printk("Please enable the IOMMU option in the BIOS setup\n");
279
280                 aper_order = fallback_aper_order;
281                 aper_alloc = allocate_aperture();
282                 if (!aper_alloc) { 
283                         /* Could disable AGP and IOMMU here, but it's probably
284                            not worth it. But the later users cannot deal with
285                            bad apertures and turning on the aperture over memory
286                            causes very strange problems, so it's better to 
287                            panic early. */
288                         panic("Not enough memory for aperture");
289                 }
290         } else { 
291                 return; 
292         } 
293
294         /* Fix up the north bridges */
295         for (num = 24; num < 32; num++) {               
296                 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
297                         continue;       
298
299                 /* Don't enable translation yet. That is done later. 
300                    Assume this BIOS didn't initialise the GART so 
301                    just overwrite all previous bits */ 
302                 write_pci_config(0, num, 3, 0x90, aper_order<<1); 
303                 write_pci_config(0, num, 3, 0x94, aper_alloc>>25); 
304         } 
305