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