diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ppc64/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/pSeries_iommu.c | 169 | ||||
-rw-r--r-- | arch/ppc64/kernel/pci.c | 9 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom_init.c | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 39 | ||||
-rw-r--r-- | arch/sparc64/kernel/ptrace.c | 7 | ||||
-rw-r--r-- | arch/sparc64/kernel/una_asm.S | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/unaligned.c | 64 | ||||
-rw-r--r-- | arch/x86_64/Kconfig | 2 |
9 files changed, 180 insertions, 117 deletions
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index 17d2c1eac3b8..521c2a5a2862 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile | |||
@@ -107,7 +107,7 @@ install: vmlinux | |||
107 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ | 107 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ |
108 | 108 | ||
109 | defaultimage-$(CONFIG_PPC_PSERIES) := zImage | 109 | defaultimage-$(CONFIG_PPC_PSERIES) := zImage |
110 | defaultimage-$(CONFIG_PPC_PMAC) := vmlinux | 110 | defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode |
111 | defaultimage-$(CONFIG_PPC_MAPLE) := zImage | 111 | defaultimage-$(CONFIG_PPC_MAPLE) := zImage |
112 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux | 112 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux |
113 | KBUILD_IMAGE := $(defaultimage-y) | 113 | KBUILD_IMAGE := $(defaultimage-y) |
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index f0fd7fbd6531..8c6313e7e145 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c | |||
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; | 265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; |
266 | 266 | ||
267 | /* Test if we are going over 2GB of DMA space */ | 267 | /* Test if we are going over 2GB of DMA space */ |
268 | if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31)) | 268 | if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { |
269 | udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | ||
269 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | 270 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); |
271 | } | ||
270 | 272 | ||
271 | phb->dma_window_base_cur += phb->dma_window_size; | 273 | phb->dma_window_base_cur += phb->dma_window_size; |
272 | 274 | ||
@@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
310 | 312 | ||
311 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 313 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) |
312 | { | 314 | { |
313 | struct device_node *dn, *pdn; | 315 | struct device_node *dn; |
314 | struct pci_dn *pci; | ||
315 | struct iommu_table *tbl; | 316 | struct iommu_table *tbl; |
317 | struct device_node *isa_dn, *isa_dn_orig; | ||
318 | struct device_node *tmp; | ||
319 | struct pci_dn *pci; | ||
320 | int children; | ||
316 | 321 | ||
317 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | 322 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); |
318 | 323 | ||
319 | /* For each (root) bus, we carve up the available DMA space in 256MB | 324 | dn = pci_bus_to_OF_node(bus); |
320 | * pieces. Since each piece is used by one (sub) bus/device, that would | 325 | pci = PCI_DN(dn); |
321 | * give a maximum of 7 devices per PHB. In most cases, this is plenty. | 326 | |
322 | * | 327 | if (bus->self) { |
323 | * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS | 328 | /* This is not a root bus, any setup will be done for the |
324 | * bridges below the PHB to allocate the sectioned tables to, so instead | 329 | * device-side of the bridge in iommu_dev_setup_pSeries(). |
325 | * we allocate a 1GB table at the PHB level. | 330 | */ |
331 | return; | ||
332 | } | ||
333 | |||
334 | /* Check if the ISA bus on the system is under | ||
335 | * this PHB. | ||
326 | */ | 336 | */ |
337 | isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa"); | ||
327 | 338 | ||
328 | dn = pci_bus_to_OF_node(bus); | 339 | while (isa_dn && isa_dn != dn) |
329 | pci = dn->data; | 340 | isa_dn = isa_dn->parent; |
330 | 341 | ||
331 | if (!bus->self) { | 342 | if (isa_dn_orig) |
332 | /* Root bus */ | 343 | of_node_put(isa_dn_orig); |
333 | if (is_python(dn)) { | ||
334 | unsigned int *iohole; | ||
335 | |||
336 | DBG("Python root bus %s\n", bus->name); | ||
337 | |||
338 | iohole = (unsigned int *)get_property(dn, "io-hole", 0); | ||
339 | |||
340 | if (iohole) { | ||
341 | /* On first bus we need to leave room for the | ||
342 | * ISA address space. Just skip the first 256MB | ||
343 | * alltogether. This leaves 768MB for the window. | ||
344 | */ | ||
345 | DBG("PHB has io-hole, reserving 256MB\n"); | ||
346 | pci->phb->dma_window_size = 3 << 28; | ||
347 | pci->phb->dma_window_base_cur = 1 << 28; | ||
348 | } else { | ||
349 | /* 1GB window by default */ | ||
350 | pci->phb->dma_window_size = 1 << 30; | ||
351 | pci->phb->dma_window_base_cur = 0; | ||
352 | } | ||
353 | |||
354 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
355 | |||
356 | iommu_table_setparms(pci->phb, dn, tbl); | ||
357 | pci->iommu_table = iommu_init_table(tbl); | ||
358 | } else { | ||
359 | /* Do a 128MB table at root. This is used for the IDE | ||
360 | * controller on some SMP-mode POWER4 machines. It | ||
361 | * doesn't hurt to allocate it on other machines | ||
362 | * -- it'll just be unused since new tables are | ||
363 | * allocated on the EADS level. | ||
364 | * | ||
365 | * Allocate at offset 128MB to avoid having to deal | ||
366 | * with ISA holes; 128MB table for IDE is plenty. | ||
367 | */ | ||
368 | pci->phb->dma_window_size = 1 << 27; | ||
369 | pci->phb->dma_window_base_cur = 1 << 27; | ||
370 | |||
371 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
372 | |||
373 | iommu_table_setparms(pci->phb, dn, tbl); | ||
374 | pci->iommu_table = iommu_init_table(tbl); | ||
375 | |||
376 | /* All child buses have 256MB tables */ | ||
377 | pci->phb->dma_window_size = 1 << 28; | ||
378 | } | ||
379 | } else { | ||
380 | pdn = pci_bus_to_OF_node(bus->parent); | ||
381 | 344 | ||
382 | if (!bus->parent->self && !is_python(pdn)) { | 345 | /* Count number of direct PCI children of the PHB. |
383 | struct iommu_table *tbl; | 346 | * All PCI device nodes have class-code property, so it's |
384 | /* First child and not python means this is the EADS | 347 | * an easy way to find them. |
385 | * level. Allocate new table for this slot with 256MB | 348 | */ |
386 | * window. | 349 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) |
387 | */ | 350 | if (get_property(tmp, "class-code", NULL)) |
351 | children++; | ||
388 | 352 | ||
389 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 353 | DBG("Children: %d\n", children); |
390 | 354 | ||
391 | iommu_table_setparms(pci->phb, dn, tbl); | 355 | /* Calculate amount of DMA window per slot. Each window must be |
356 | * a power of two (due to pci_alloc_consistent requirements). | ||
357 | * | ||
358 | * Keep 256MB aside for PHBs with ISA. | ||
359 | */ | ||
392 | 360 | ||
393 | pci->iommu_table = iommu_init_table(tbl); | 361 | if (!isa_dn) { |
394 | } else { | 362 | /* No ISA/IDE - just set window size and return */ |
395 | /* Lower than first child or under python, use parent table */ | 363 | pci->phb->dma_window_size = 0x80000000ul; /* To be divided */ |
396 | pci->iommu_table = PCI_DN(pdn)->iommu_table; | 364 | |
397 | } | 365 | while (pci->phb->dma_window_size * children > 0x80000000ul) |
366 | pci->phb->dma_window_size >>= 1; | ||
367 | DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
368 | pci->phb->dma_window_base_cur = 0; | ||
369 | |||
370 | return; | ||
398 | } | 371 | } |
372 | |||
373 | /* If we have ISA, then we probably have an IDE | ||
374 | * controller too. Allocate a 128MB table but | ||
375 | * skip the first 128MB to avoid stepping on ISA | ||
376 | * space. | ||
377 | */ | ||
378 | pci->phb->dma_window_size = 0x8000000ul; | ||
379 | pci->phb->dma_window_base_cur = 0x8000000ul; | ||
380 | |||
381 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
382 | |||
383 | iommu_table_setparms(pci->phb, dn, tbl); | ||
384 | pci->iommu_table = iommu_init_table(tbl); | ||
385 | |||
386 | /* Divide the rest (1.75GB) among the children */ | ||
387 | pci->phb->dma_window_size = 0x80000000ul; | ||
388 | while (pci->phb->dma_window_size * children > 0x70000000ul) | ||
389 | pci->phb->dma_window_size >>= 1; | ||
390 | |||
391 | DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
392 | |||
399 | } | 393 | } |
400 | 394 | ||
401 | 395 | ||
@@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
446 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 440 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) |
447 | { | 441 | { |
448 | struct device_node *dn, *mydn; | 442 | struct device_node *dn, *mydn; |
443 | struct iommu_table *tbl; | ||
449 | 444 | ||
450 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); | 445 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); |
451 | /* Now copy the iommu_table ptr from the bus device down to the | 446 | |
452 | * pci device_node. This means get_iommu_table() won't need to search | ||
453 | * up the device tree to find it. | ||
454 | */ | ||
455 | mydn = dn = pci_device_to_OF_node(dev); | 447 | mydn = dn = pci_device_to_OF_node(dev); |
456 | 448 | ||
449 | /* If we're the direct child of a root bus, then we need to allocate | ||
450 | * an iommu table ourselves. The bus setup code should have setup | ||
451 | * the window sizes already. | ||
452 | */ | ||
453 | if (!dev->bus->self) { | ||
454 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | ||
455 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
456 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | ||
457 | PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); | ||
458 | |||
459 | return; | ||
460 | } | ||
461 | |||
462 | /* If this device is further down the bus tree, search upwards until | ||
463 | * an already allocated iommu table is found and use that. | ||
464 | */ | ||
465 | |||
457 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) | 466 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) |
458 | dn = dn->parent; | 467 | dn = dn->parent; |
459 | 468 | ||
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 861138ad092c..ff4be1da69d5 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -246,11 +246,14 @@ static unsigned int pci_parse_of_flags(u32 addr0) | |||
246 | unsigned int flags = 0; | 246 | unsigned int flags = 0; |
247 | 247 | ||
248 | if (addr0 & 0x02000000) { | 248 | if (addr0 & 0x02000000) { |
249 | flags |= IORESOURCE_MEM; | 249 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; |
250 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
251 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | ||
250 | if (addr0 & 0x40000000) | 252 | if (addr0 & 0x40000000) |
251 | flags |= IORESOURCE_PREFETCH; | 253 | flags |= IORESOURCE_PREFETCH |
254 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | ||
252 | } else if (addr0 & 0x01000000) | 255 | } else if (addr0 & 0x01000000) |
253 | flags |= IORESOURCE_IO; | 256 | flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; |
254 | return flags; | 257 | return flags; |
255 | } | 258 | } |
256 | 259 | ||
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 9979919cdf92..f252670874a4 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -1711,6 +1711,7 @@ static void __init flatten_device_tree(void) | |||
1711 | unsigned long offset = reloc_offset(); | 1711 | unsigned long offset = reloc_offset(); |
1712 | unsigned long mem_start, mem_end, room; | 1712 | unsigned long mem_start, mem_end, room; |
1713 | struct boot_param_header *hdr; | 1713 | struct boot_param_header *hdr; |
1714 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1714 | char *namep; | 1715 | char *namep; |
1715 | u64 *rsvmap; | 1716 | u64 *rsvmap; |
1716 | 1717 | ||
@@ -1765,6 +1766,7 @@ static void __init flatten_device_tree(void) | |||
1765 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); | 1766 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); |
1766 | 1767 | ||
1767 | /* Finish header */ | 1768 | /* Finish header */ |
1769 | hdr->boot_cpuid_phys = _prom->cpu; | ||
1768 | hdr->magic = OF_DT_HEADER; | 1770 | hdr->magic = OF_DT_HEADER; |
1769 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); | 1771 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); |
1770 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); | 1772 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); |
@@ -1854,7 +1856,6 @@ static void __init prom_find_boot_cpu(void) | |||
1854 | 1856 | ||
1855 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); | 1857 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); |
1856 | 1858 | ||
1857 | prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0); | ||
1858 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | 1859 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); |
1859 | _prom->cpu = getprop_rval; | 1860 | _prom->cpu = getprop_rval; |
1860 | 1861 | ||
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 3e0badb820c5..b48349527853 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -42,19 +42,15 @@ | |||
42 | * executing (see inherit_locked_prom_mappings() rant). | 42 | * executing (see inherit_locked_prom_mappings() rant). |
43 | */ | 43 | */ |
44 | sparc64_vpte_nucleus: | 44 | sparc64_vpte_nucleus: |
45 | /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ | 45 | /* Note that kvmap below has verified that the address is |
46 | mov 0xf, %g5 | 46 | * in the range MODULES_VADDR --> VMALLOC_END already. So |
47 | sllx %g5, 28, %g5 | 47 | * here we need only check if it is an OBP address or not. |
48 | 48 | */ | |
49 | /* Is addr >= LOW_OBP_ADDRESS? */ | 49 | sethi %hi(LOW_OBP_ADDRESS), %g5 |
50 | cmp %g4, %g5 | 50 | cmp %g4, %g5 |
51 | blu,pn %xcc, sparc64_vpte_patchme1 | 51 | blu,pn %xcc, sparc64_vpte_patchme1 |
52 | mov 0x1, %g5 | 52 | mov 0x1, %g5 |
53 | |||
54 | /* Load 0x100000000, which is HI_OBP_ADDRESS. */ | ||
55 | sllx %g5, 32, %g5 | 53 | sllx %g5, 32, %g5 |
56 | |||
57 | /* Is addr < HI_OBP_ADDRESS? */ | ||
58 | cmp %g4, %g5 | 54 | cmp %g4, %g5 |
59 | blu,pn %xcc, obp_iaddr_patch | 55 | blu,pn %xcc, obp_iaddr_patch |
60 | nop | 56 | nop |
@@ -156,26 +152,29 @@ obp_daddr_patch: | |||
156 | * rather, use information saved during inherit_prom_mappings() using 8k | 152 | * rather, use information saved during inherit_prom_mappings() using 8k |
157 | * pagesize. | 153 | * pagesize. |
158 | */ | 154 | */ |
155 | .align 32 | ||
159 | kvmap: | 156 | kvmap: |
160 | /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ | 157 | sethi %hi(MODULES_VADDR), %g5 |
161 | mov 0xf, %g5 | 158 | cmp %g4, %g5 |
162 | sllx %g5, 28, %g5 | 159 | blu,pn %xcc, longpath |
160 | mov (VMALLOC_END >> 24), %g5 | ||
161 | sllx %g5, 24, %g5 | ||
162 | cmp %g4, %g5 | ||
163 | bgeu,pn %xcc, longpath | ||
164 | nop | ||
163 | 165 | ||
164 | /* Is addr >= LOW_OBP_ADDRESS? */ | 166 | kvmap_check_obp: |
167 | sethi %hi(LOW_OBP_ADDRESS), %g5 | ||
165 | cmp %g4, %g5 | 168 | cmp %g4, %g5 |
166 | blu,pn %xcc, vmalloc_addr | 169 | blu,pn %xcc, kvmap_vmalloc_addr |
167 | mov 0x1, %g5 | 170 | mov 0x1, %g5 |
168 | |||
169 | /* Load 0x100000000, which is HI_OBP_ADDRESS. */ | ||
170 | sllx %g5, 32, %g5 | 171 | sllx %g5, 32, %g5 |
171 | |||
172 | /* Is addr < HI_OBP_ADDRESS? */ | ||
173 | cmp %g4, %g5 | 172 | cmp %g4, %g5 |
174 | blu,pn %xcc, obp_daddr_patch | 173 | blu,pn %xcc, obp_daddr_patch |
175 | nop | 174 | nop |
176 | 175 | ||
177 | vmalloc_addr: | 176 | kvmap_vmalloc_addr: |
178 | /* If we get here, a vmalloc addr accessed, load kernel VPTE. */ | 177 | /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ |
179 | ldxa [%g3 + %g6] ASI_N, %g5 | 178 | ldxa [%g3 + %g6] ASI_N, %g5 |
180 | brgez,pn %g5, longpath | 179 | brgez,pn %g5, longpath |
181 | nop | 180 | nop |
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 23ad839d113f..5efbff90d668 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/psrcompat.h> | 30 | #include <asm/psrcompat.h> |
31 | #include <asm/visasm.h> | 31 | #include <asm/visasm.h> |
32 | #include <asm/spitfire.h> | 32 | #include <asm/spitfire.h> |
33 | #include <asm/page.h> | ||
33 | 34 | ||
34 | /* Returning from ptrace is a bit tricky because the syscall return | 35 | /* Returning from ptrace is a bit tricky because the syscall return |
35 | * low level code assumes any value returned which is negative and | 36 | * low level code assumes any value returned which is negative and |
@@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | |||
128 | * is mapped to in the user's address space, we can skip the | 129 | * is mapped to in the user's address space, we can skip the |
129 | * D-cache flush. | 130 | * D-cache flush. |
130 | */ | 131 | */ |
131 | if ((uaddr ^ kaddr) & (1UL << 13)) { | 132 | if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { |
132 | unsigned long start = __pa(kaddr); | 133 | unsigned long start = __pa(kaddr); |
133 | unsigned long end = start + len; | 134 | unsigned long end = start + len; |
134 | 135 | ||
135 | if (tlb_type == spitfire) { | 136 | if (tlb_type == spitfire) { |
136 | for (; start < end; start += 32) | 137 | for (; start < end; start += 32) |
137 | spitfire_put_dcache_tag(va & 0x3fe0, 0x0); | 138 | spitfire_put_dcache_tag(start & 0x3fe0, 0x0); |
138 | } else { | 139 | } else { |
139 | for (; start < end; start += 32) | 140 | for (; start < end; start += 32) |
140 | __asm__ __volatile__( | 141 | __asm__ __volatile__( |
141 | "stxa %%g0, [%0] %1\n\t" | 142 | "stxa %%g0, [%0] %1\n\t" |
142 | "membar #Sync" | 143 | "membar #Sync" |
143 | : /* no outputs */ | 144 | : /* no outputs */ |
144 | : "r" (va), | 145 | : "r" (start), |
145 | "i" (ASI_DCACHE_INVALIDATE)); | 146 | "i" (ASI_DCACHE_INVALIDATE)); |
146 | } | 147 | } |
147 | } | 148 | } |
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S index cbb40585253c..da48400bcc95 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc64/kernel/una_asm.S | |||
@@ -17,7 +17,7 @@ kernel_unaligned_trap_fault: | |||
17 | __do_int_store: | 17 | __do_int_store: |
18 | rd %asi, %o4 | 18 | rd %asi, %o4 |
19 | wr %o3, 0, %asi | 19 | wr %o3, 0, %asi |
20 | ldx [%o2], %g3 | 20 | mov %o2, %g3 |
21 | cmp %o1, 2 | 21 | cmp %o1, 2 |
22 | be,pn %icc, 2f | 22 | be,pn %icc, 2f |
23 | cmp %o1, 4 | 23 | cmp %o1, 4 |
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index da9739f0d437..42718f6a7d36 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c | |||
@@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size, | |||
184 | unsigned long *saddr, int is_signed, int asi); | 184 | unsigned long *saddr, int is_signed, int asi); |
185 | 185 | ||
186 | extern void __do_int_store(unsigned long *dst_addr, int size, | 186 | extern void __do_int_store(unsigned long *dst_addr, int size, |
187 | unsigned long *src_val, int asi); | 187 | unsigned long src_val, int asi); |
188 | 188 | ||
189 | static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, | 189 | static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, |
190 | struct pt_regs *regs, int asi) | 190 | struct pt_regs *regs, int asi, int orig_asi) |
191 | { | 191 | { |
192 | unsigned long zero = 0; | 192 | unsigned long zero = 0; |
193 | unsigned long *src_val = &zero; | 193 | unsigned long *src_val_p = &zero; |
194 | unsigned long src_val; | ||
194 | 195 | ||
195 | if (size == 16) { | 196 | if (size == 16) { |
196 | size = 8; | 197 | size = 8; |
@@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, | |||
198 | (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | | 199 | (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | |
199 | (unsigned)fetch_reg(reg_num + 1, regs); | 200 | (unsigned)fetch_reg(reg_num + 1, regs); |
200 | } else if (reg_num) { | 201 | } else if (reg_num) { |
201 | src_val = fetch_reg_addr(reg_num, regs); | 202 | src_val_p = fetch_reg_addr(reg_num, regs); |
203 | } | ||
204 | src_val = *src_val_p; | ||
205 | if (unlikely(asi != orig_asi)) { | ||
206 | switch (size) { | ||
207 | case 2: | ||
208 | src_val = swab16(src_val); | ||
209 | break; | ||
210 | case 4: | ||
211 | src_val = swab32(src_val); | ||
212 | break; | ||
213 | case 8: | ||
214 | src_val = swab64(src_val); | ||
215 | break; | ||
216 | case 16: | ||
217 | default: | ||
218 | BUG(); | ||
219 | break; | ||
220 | }; | ||
202 | } | 221 | } |
203 | __do_int_store(dst_addr, size, src_val, asi); | 222 | __do_int_store(dst_addr, size, src_val, asi); |
204 | } | 223 | } |
@@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u | |||
276 | kernel_mna_trap_fault(); | 295 | kernel_mna_trap_fault(); |
277 | } else { | 296 | } else { |
278 | unsigned long addr; | 297 | unsigned long addr; |
298 | int orig_asi, asi; | ||
279 | 299 | ||
280 | addr = compute_effective_address(regs, insn, | 300 | addr = compute_effective_address(regs, insn, |
281 | ((insn >> 25) & 0x1f)); | 301 | ((insn >> 25) & 0x1f)); |
@@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u | |||
285 | regs->tpc, dirstrings[dir], addr, size, | 305 | regs->tpc, dirstrings[dir], addr, size, |
286 | regs->u_regs[UREG_RETPC]); | 306 | regs->u_regs[UREG_RETPC]); |
287 | #endif | 307 | #endif |
308 | orig_asi = asi = decode_asi(insn, regs); | ||
309 | switch (asi) { | ||
310 | case ASI_NL: | ||
311 | case ASI_AIUPL: | ||
312 | case ASI_AIUSL: | ||
313 | case ASI_PL: | ||
314 | case ASI_SL: | ||
315 | case ASI_PNFL: | ||
316 | case ASI_SNFL: | ||
317 | asi &= ~0x08; | ||
318 | break; | ||
319 | }; | ||
288 | switch (dir) { | 320 | switch (dir) { |
289 | case load: | 321 | case load: |
290 | do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), | 322 | do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), |
291 | size, (unsigned long *) addr, | 323 | size, (unsigned long *) addr, |
292 | decode_signedness(insn), | 324 | decode_signedness(insn), asi); |
293 | decode_asi(insn, regs)); | 325 | if (unlikely(asi != orig_asi)) { |
326 | unsigned long val_in = *(unsigned long *) addr; | ||
327 | switch (size) { | ||
328 | case 2: | ||
329 | val_in = swab16(val_in); | ||
330 | break; | ||
331 | case 4: | ||
332 | val_in = swab32(val_in); | ||
333 | break; | ||
334 | case 8: | ||
335 | val_in = swab64(val_in); | ||
336 | break; | ||
337 | case 16: | ||
338 | default: | ||
339 | BUG(); | ||
340 | break; | ||
341 | }; | ||
342 | *(unsigned long *) addr = val_in; | ||
343 | } | ||
294 | break; | 344 | break; |
295 | 345 | ||
296 | case store: | 346 | case store: |
297 | do_int_store(((insn>>25)&0x1f), size, | 347 | do_int_store(((insn>>25)&0x1f), size, |
298 | (unsigned long *) addr, regs, | 348 | (unsigned long *) addr, regs, |
299 | decode_asi(insn, regs)); | 349 | asi, orig_asi); |
300 | break; | 350 | break; |
301 | 351 | ||
302 | default: | 352 | default: |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 0969d570f3b5..21afa69a086d 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -308,7 +308,7 @@ config HPET_TIMER | |||
308 | present. The HPET provides a stable time base on SMP | 308 | present. The HPET provides a stable time base on SMP |
309 | systems, unlike the TSC, but it is more expensive to access, | 309 | systems, unlike the TSC, but it is more expensive to access, |
310 | as it is off-chip. You can find the HPET spec at | 310 | as it is off-chip. You can find the HPET spec at |
311 | <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>. | 311 | <http://www.intel.com/hardwaredesign/hpetspec.htm>. |
312 | 312 | ||
313 | config X86_PM_TIMER | 313 | config X86_PM_TIMER |
314 | bool "PM timer" | 314 | bool "PM timer" |