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