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