diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-12 11:33:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-12 11:33:53 -0400 |
commit | 26cda988ba1e3e843a0680fe98661a22fa430a60 (patch) | |
tree | 692e76e9bc9b11ed34bad88f892adc0184c2e5ff /arch | |
parent | 1df5c10a5b40d1ad747e3de3caf28764153c5c8e (diff) | |
parent | 2d909d08db7655a53f3afb31c7627c5c8c87142a (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/ppc64-2.6
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ppc64/kernel/iSeries_pci.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/maple_pci.c | 56 | ||||
-rw-r--r-- | arch/ppc64/kernel/pSeries_setup.c | 8 | ||||
-rw-r--r-- | arch/ppc64/kernel/pSeries_smp.c | 13 | ||||
-rw-r--r-- | arch/ppc64/kernel/pci.c | 425 | ||||
-rw-r--r-- | arch/ppc64/kernel/pmac_pci.c | 60 | ||||
-rw-r--r-- | arch/ppc64/kernel/pmac_setup.c | 13 | ||||
-rw-r--r-- | arch/ppc64/kernel/process.c | 34 | ||||
-rw-r--r-- | arch/ppc64/kernel/ptrace.c | 28 | ||||
-rw-r--r-- | arch/ppc64/kernel/ptrace32.c | 34 | ||||
-rw-r--r-- | arch/ppc64/kernel/ras.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/setup.c | 16 | ||||
-rw-r--r-- | arch/ppc64/kernel/signal.c | 9 | ||||
-rw-r--r-- | arch/ppc64/kernel/signal32.c | 8 | ||||
-rw-r--r-- | arch/ppc64/kernel/xics.c | 44 | ||||
-rw-r--r-- | arch/ppc64/mm/fault.c | 31 | ||||
-rw-r--r-- | arch/ppc64/xmon/privinst.h | 1 | ||||
-rw-r--r-- | arch/ppc64/xmon/xmon.c | 20 |
18 files changed, 587 insertions, 217 deletions
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c index 356e4fd9a94f..fbc273c32bcc 100644 --- a/arch/ppc64/kernel/iSeries_pci.c +++ b/arch/ppc64/kernel/iSeries_pci.c | |||
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void) | |||
252 | phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | 252 | phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); |
253 | if (phb == NULL) | 253 | if (phb == NULL) |
254 | return -ENOMEM; | 254 | return -ENOMEM; |
255 | pci_setup_pci_controller(phb); | 255 | pci_setup_pci_controller(phb); |
256 | 256 | ||
257 | phb->pci_mem_offset = phb->local_number = bus; | 257 | phb->pci_mem_offset = phb->local_number = bus; |
258 | phb->first_busno = bus; | 258 | phb->first_busno = bus; |
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c index 5a8b4d8c2dd6..1d297e0edfc0 100644 --- a/arch/ppc64/kernel/maple_pci.c +++ b/arch/ppc64/kernel/maple_pci.c | |||
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose) | |||
283 | * the reg address cell, we shall fix that by killing struct | 283 | * the reg address cell, we shall fix that by killing struct |
284 | * reg_property and using some accessor functions instead | 284 | * reg_property and using some accessor functions instead |
285 | */ | 285 | */ |
286 | hose->first_busno = 0xf0; | 286 | hose->first_busno = 0xf0; |
287 | hose->last_busno = 0xff; | 287 | hose->last_busno = 0xff; |
288 | hose->ops = &u3_agp_pci_ops; | 288 | hose->ops = &u3_agp_pci_ops; |
289 | hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); | 289 | hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); |
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev) | |||
315 | char* disp_name; | 315 | char* disp_name; |
316 | int *bus_range; | 316 | int *bus_range; |
317 | int primary = 1; | 317 | int primary = 1; |
318 | struct property *of_prop; | 318 | struct property *of_prop; |
319 | 319 | ||
320 | DBG("Adding PCI host bridge %s\n", dev->full_name); | 320 | DBG("Adding PCI host bridge %s\n", dev->full_name); |
321 | 321 | ||
322 | bus_range = (int *) get_property(dev, "bus-range", &len); | 322 | bus_range = (int *) get_property(dev, "bus-range", &len); |
323 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 323 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
324 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | 324 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", |
325 | dev->full_name); | 325 | dev->full_name); |
326 | } | 326 | } |
327 | 327 | ||
328 | hose = alloc_bootmem(sizeof(struct pci_controller)); | 328 | hose = alloc_bootmem(sizeof(struct pci_controller)); |
329 | if (hose == NULL) | 329 | if (hose == NULL) |
330 | return -ENOMEM; | 330 | return -ENOMEM; |
331 | pci_setup_pci_controller(hose); | 331 | pci_setup_pci_controller(hose); |
332 | 332 | ||
333 | hose->arch_data = dev; | 333 | hose->arch_data = dev; |
334 | hose->first_busno = bus_range ? bus_range[0] : 0; | 334 | hose->first_busno = bus_range ? bus_range[0] : 0; |
335 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 335 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
336 | 336 | ||
337 | of_prop = alloc_bootmem(sizeof(struct property) + | 337 | of_prop = alloc_bootmem(sizeof(struct property) + |
338 | sizeof(hose->global_number)); | 338 | sizeof(hose->global_number)); |
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev) | |||
346 | } | 346 | } |
347 | 347 | ||
348 | disp_name = NULL; | 348 | disp_name = NULL; |
349 | if (device_is_compatible(dev, "u3-agp")) { | 349 | if (device_is_compatible(dev, "u3-agp")) { |
350 | setup_u3_agp(hose); | 350 | setup_u3_agp(hose); |
351 | disp_name = "U3-AGP"; | 351 | disp_name = "U3-AGP"; |
352 | primary = 0; | 352 | primary = 0; |
353 | } else if (device_is_compatible(dev, "u3-ht")) { | 353 | } else if (device_is_compatible(dev, "u3-ht")) { |
354 | setup_u3_ht(hose); | 354 | setup_u3_ht(hose); |
355 | disp_name = "U3-HT"; | 355 | disp_name = "U3-HT"; |
356 | primary = 1; | 356 | primary = 1; |
357 | } | 357 | } |
358 | printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", | 358 | printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", |
359 | disp_name, hose->first_busno, hose->last_busno); | 359 | disp_name, hose->first_busno, hose->last_busno); |
360 | 360 | ||
361 | /* Interpret the "ranges" property */ | 361 | /* Interpret the "ranges" property */ |
362 | /* This also maps the I/O region and sets isa_io/mem_base */ | 362 | /* This also maps the I/O region and sets isa_io/mem_base */ |
363 | pci_process_bridge_OF_ranges(hose, dev); | 363 | pci_process_bridge_OF_ranges(hose, dev); |
364 | pci_setup_phb_io(hose, primary); | 364 | pci_setup_phb_io(hose, primary); |
365 | 365 | ||
366 | /* Fixup "bus-range" OF property */ | 366 | /* Fixup "bus-range" OF property */ |
367 | fixup_bus_range(dev); | 367 | fixup_bus_range(dev); |
368 | 368 | ||
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c index 9490b6c5b173..bfadccc7b8be 100644 --- a/arch/ppc64/kernel/pSeries_setup.c +++ b/arch/ppc64/kernel/pSeries_setup.c | |||
@@ -590,6 +590,13 @@ static int pseries_shared_idle(void) | |||
590 | return 0; | 590 | return 0; |
591 | } | 591 | } |
592 | 592 | ||
593 | static int pSeries_pci_probe_mode(struct pci_bus *bus) | ||
594 | { | ||
595 | if (systemcfg->platform & PLATFORM_LPAR) | ||
596 | return PCI_PROBE_DEVTREE; | ||
597 | return PCI_PROBE_NORMAL; | ||
598 | } | ||
599 | |||
593 | struct machdep_calls __initdata pSeries_md = { | 600 | struct machdep_calls __initdata pSeries_md = { |
594 | .probe = pSeries_probe, | 601 | .probe = pSeries_probe, |
595 | .setup_arch = pSeries_setup_arch, | 602 | .setup_arch = pSeries_setup_arch, |
@@ -597,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = { | |||
597 | .get_cpuinfo = pSeries_get_cpuinfo, | 604 | .get_cpuinfo = pSeries_get_cpuinfo, |
598 | .log_error = pSeries_log_error, | 605 | .log_error = pSeries_log_error, |
599 | .pcibios_fixup = pSeries_final_fixup, | 606 | .pcibios_fixup = pSeries_final_fixup, |
607 | .pci_probe_mode = pSeries_pci_probe_mode, | ||
600 | .irq_bus_setup = pSeries_irq_bus_setup, | 608 | .irq_bus_setup = pSeries_irq_bus_setup, |
601 | .restart = rtas_restart, | 609 | .restart = rtas_restart, |
602 | .power_off = rtas_power_off, | 610 | .power_off = rtas_power_off, |
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index 79c7f3223665..d2c7e2c4733b 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c | |||
@@ -272,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
272 | unsigned long start_here = __pa((u32)*((unsigned long *) | 272 | unsigned long start_here = __pa((u32)*((unsigned long *) |
273 | pSeries_secondary_smp_init)); | 273 | pSeries_secondary_smp_init)); |
274 | unsigned int pcpu; | 274 | unsigned int pcpu; |
275 | int start_cpu; | ||
275 | 276 | ||
276 | if (cpu_isset(lcpu, of_spin_map)) | 277 | if (cpu_isset(lcpu, of_spin_map)) |
277 | /* Already started by OF and sitting in spin loop */ | 278 | /* Already started by OF and sitting in spin loop */ |
@@ -282,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
282 | /* Fixup atomic count: it exited inside IRQ handler. */ | 283 | /* Fixup atomic count: it exited inside IRQ handler. */ |
283 | paca[lcpu].__current->thread_info->preempt_count = 0; | 284 | paca[lcpu].__current->thread_info->preempt_count = 0; |
284 | 285 | ||
285 | status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL, | 286 | /* |
286 | pcpu, start_here, lcpu); | 287 | * If the RTAS start-cpu token does not exist then presume the |
288 | * cpu is already spinning. | ||
289 | */ | ||
290 | start_cpu = rtas_token("start-cpu"); | ||
291 | if (start_cpu == RTAS_UNKNOWN_SERVICE) | ||
292 | return 1; | ||
293 | |||
294 | status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu); | ||
287 | if (status != 0) { | 295 | if (status != 0) { |
288 | printk(KERN_ERR "start-cpu failed: %i\n", status); | 296 | printk(KERN_ERR "start-cpu failed: %i\n", status); |
289 | return 0; | 297 | return 0; |
290 | } | 298 | } |
299 | |||
291 | return 1; | 300 | return 1; |
292 | } | 301 | } |
293 | 302 | ||
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 8447dcc2c2b3..861138ad092c 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -51,6 +51,10 @@ unsigned long io_page_mask; | |||
51 | 51 | ||
52 | EXPORT_SYMBOL(io_page_mask); | 52 | EXPORT_SYMBOL(io_page_mask); |
53 | 53 | ||
54 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
55 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | ||
56 | static void do_bus_setup(struct pci_bus *bus); | ||
57 | #endif | ||
54 | 58 | ||
55 | unsigned int pcibios_assign_all_busses(void) | 59 | unsigned int pcibios_assign_all_busses(void) |
56 | { | 60 | { |
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void) | |||
225 | } | 229 | } |
226 | #endif | 230 | #endif |
227 | 231 | ||
232 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
233 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) | ||
234 | { | ||
235 | u32 *prop; | ||
236 | int len; | ||
237 | |||
238 | prop = (u32 *) get_property(np, name, &len); | ||
239 | if (prop && len >= 4) | ||
240 | return *prop; | ||
241 | return def; | ||
242 | } | ||
243 | |||
244 | static unsigned int pci_parse_of_flags(u32 addr0) | ||
245 | { | ||
246 | unsigned int flags = 0; | ||
247 | |||
248 | if (addr0 & 0x02000000) { | ||
249 | flags |= IORESOURCE_MEM; | ||
250 | if (addr0 & 0x40000000) | ||
251 | flags |= IORESOURCE_PREFETCH; | ||
252 | } else if (addr0 & 0x01000000) | ||
253 | flags |= IORESOURCE_IO; | ||
254 | return flags; | ||
255 | } | ||
256 | |||
257 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||
258 | |||
259 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | ||
260 | { | ||
261 | u64 base, size; | ||
262 | unsigned int flags; | ||
263 | struct resource *res; | ||
264 | u32 *addrs, i; | ||
265 | int proplen; | ||
266 | |||
267 | addrs = (u32 *) get_property(node, "assigned-addresses", &proplen); | ||
268 | if (!addrs) | ||
269 | return; | ||
270 | for (; proplen >= 20; proplen -= 20, addrs += 5) { | ||
271 | flags = pci_parse_of_flags(addrs[0]); | ||
272 | if (!flags) | ||
273 | continue; | ||
274 | base = GET_64BIT(addrs, 1); | ||
275 | size = GET_64BIT(addrs, 3); | ||
276 | if (!size) | ||
277 | continue; | ||
278 | i = addrs[0] & 0xff; | ||
279 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | ||
280 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | ||
281 | } else if (i == dev->rom_base_reg) { | ||
282 | res = &dev->resource[PCI_ROM_RESOURCE]; | ||
283 | flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; | ||
284 | } else { | ||
285 | printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); | ||
286 | continue; | ||
287 | } | ||
288 | res->start = base; | ||
289 | res->end = base + size - 1; | ||
290 | res->flags = flags; | ||
291 | res->name = pci_name(dev); | ||
292 | fixup_resource(res, dev); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static struct pci_dev *of_create_pci_dev(struct device_node *node, | ||
297 | struct pci_bus *bus, int devfn) | ||
298 | { | ||
299 | struct pci_dev *dev; | ||
300 | const char *type; | ||
301 | |||
302 | dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | ||
303 | if (!dev) | ||
304 | return NULL; | ||
305 | type = get_property(node, "device_type", NULL); | ||
306 | if (type == NULL) | ||
307 | type = ""; | ||
308 | |||
309 | memset(dev, 0, sizeof(struct pci_dev)); | ||
310 | dev->bus = bus; | ||
311 | dev->sysdata = node; | ||
312 | dev->dev.parent = bus->bridge; | ||
313 | dev->dev.bus = &pci_bus_type; | ||
314 | dev->devfn = devfn; | ||
315 | dev->multifunction = 0; /* maybe a lie? */ | ||
316 | |||
317 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); | ||
318 | dev->device = get_int_prop(node, "device-id", 0xffff); | ||
319 | dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); | ||
320 | dev->subsystem_device = get_int_prop(node, "subsystem-id", 0); | ||
321 | |||
322 | dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/ | ||
323 | |||
324 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
325 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
326 | dev->class = get_int_prop(node, "class-code", 0); | ||
327 | |||
328 | dev->current_state = 4; /* unknown power state */ | ||
329 | |||
330 | if (!strcmp(type, "pci")) { | ||
331 | /* a PCI-PCI bridge */ | ||
332 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
333 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
334 | } else if (!strcmp(type, "cardbus")) { | ||
335 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
336 | } else { | ||
337 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
338 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
339 | dev->irq = NO_IRQ; | ||
340 | if (node->n_intrs > 0) { | ||
341 | dev->irq = node->intrs[0].line; | ||
342 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, | ||
343 | dev->irq); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | pci_parse_of_addrs(node, dev); | ||
348 | |||
349 | pci_device_add(dev, bus); | ||
350 | |||
351 | /* XXX pci_scan_msi_device(dev); */ | ||
352 | |||
353 | return dev; | ||
354 | } | ||
355 | |||
356 | static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev); | ||
357 | |||
358 | static void __devinit of_scan_bus(struct device_node *node, | ||
359 | struct pci_bus *bus) | ||
360 | { | ||
361 | struct device_node *child = NULL; | ||
362 | u32 *reg; | ||
363 | int reglen, devfn; | ||
364 | struct pci_dev *dev; | ||
365 | |||
366 | while ((child = of_get_next_child(node, child)) != NULL) { | ||
367 | reg = (u32 *) get_property(child, "reg", ®len); | ||
368 | if (reg == NULL || reglen < 20) | ||
369 | continue; | ||
370 | devfn = (reg[0] >> 8) & 0xff; | ||
371 | /* create a new pci_dev for this device */ | ||
372 | dev = of_create_pci_dev(child, bus, devfn); | ||
373 | if (!dev) | ||
374 | continue; | ||
375 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
376 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
377 | of_scan_pci_bridge(child, dev); | ||
378 | } | ||
379 | |||
380 | do_bus_setup(bus); | ||
381 | } | ||
382 | |||
383 | static void __devinit of_scan_pci_bridge(struct device_node *node, | ||
384 | struct pci_dev *dev) | ||
385 | { | ||
386 | struct pci_bus *bus; | ||
387 | u32 *busrange, *ranges; | ||
388 | int len, i, mode; | ||
389 | struct resource *res; | ||
390 | unsigned int flags; | ||
391 | u64 size; | ||
392 | |||
393 | /* parse bus-range property */ | ||
394 | busrange = (u32 *) get_property(node, "bus-range", &len); | ||
395 | if (busrange == NULL || len != 8) { | ||
396 | printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n", | ||
397 | node->full_name); | ||
398 | return; | ||
399 | } | ||
400 | ranges = (u32 *) get_property(node, "ranges", &len); | ||
401 | if (ranges == NULL) { | ||
402 | printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n", | ||
403 | node->full_name); | ||
404 | return; | ||
405 | } | ||
406 | |||
407 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | ||
408 | if (!bus) { | ||
409 | printk(KERN_ERR "Failed to create pci bus for %s\n", | ||
410 | node->full_name); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | bus->primary = dev->bus->number; | ||
415 | bus->subordinate = busrange[1]; | ||
416 | bus->bridge_ctl = 0; | ||
417 | bus->sysdata = node; | ||
418 | |||
419 | /* parse ranges property */ | ||
420 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | ||
421 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | ||
422 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | ||
423 | res->flags = 0; | ||
424 | bus->resource[i] = res; | ||
425 | ++res; | ||
426 | } | ||
427 | i = 1; | ||
428 | for (; len >= 32; len -= 32, ranges += 8) { | ||
429 | flags = pci_parse_of_flags(ranges[0]); | ||
430 | size = GET_64BIT(ranges, 6); | ||
431 | if (flags == 0 || size == 0) | ||
432 | continue; | ||
433 | if (flags & IORESOURCE_IO) { | ||
434 | res = bus->resource[0]; | ||
435 | if (res->flags) { | ||
436 | printk(KERN_ERR "PCI: ignoring extra I/O range" | ||
437 | " for bridge %s\n", node->full_name); | ||
438 | continue; | ||
439 | } | ||
440 | } else { | ||
441 | if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { | ||
442 | printk(KERN_ERR "PCI: too many memory ranges" | ||
443 | " for bridge %s\n", node->full_name); | ||
444 | continue; | ||
445 | } | ||
446 | res = bus->resource[i]; | ||
447 | ++i; | ||
448 | } | ||
449 | res->start = GET_64BIT(ranges, 1); | ||
450 | res->end = res->start + size - 1; | ||
451 | res->flags = flags; | ||
452 | fixup_resource(res, dev); | ||
453 | } | ||
454 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | ||
455 | bus->number); | ||
456 | |||
457 | mode = PCI_PROBE_NORMAL; | ||
458 | if (ppc_md.pci_probe_mode) | ||
459 | mode = ppc_md.pci_probe_mode(bus); | ||
460 | if (mode == PCI_PROBE_DEVTREE) | ||
461 | of_scan_bus(node, bus); | ||
462 | else if (mode == PCI_PROBE_NORMAL) | ||
463 | pci_scan_child_bus(bus); | ||
464 | } | ||
465 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
466 | |||
467 | static void __devinit scan_phb(struct pci_controller *hose) | ||
468 | { | ||
469 | struct pci_bus *bus; | ||
470 | struct device_node *node = hose->arch_data; | ||
471 | int i, mode; | ||
472 | struct resource *res; | ||
473 | |||
474 | bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); | ||
475 | if (bus == NULL) { | ||
476 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | ||
477 | hose->global_number); | ||
478 | return; | ||
479 | } | ||
480 | bus->secondary = hose->first_busno; | ||
481 | hose->bus = bus; | ||
482 | |||
483 | bus->resource[0] = res = &hose->io_resource; | ||
484 | if (res->flags && request_resource(&ioport_resource, res)) | ||
485 | printk(KERN_ERR "Failed to request PCI IO region " | ||
486 | "on PCI domain %04x\n", hose->global_number); | ||
487 | |||
488 | for (i = 0; i < 3; ++i) { | ||
489 | res = &hose->mem_resources[i]; | ||
490 | bus->resource[i+1] = res; | ||
491 | if (res->flags && request_resource(&iomem_resource, res)) | ||
492 | printk(KERN_ERR "Failed to request PCI memory region " | ||
493 | "on PCI domain %04x\n", hose->global_number); | ||
494 | } | ||
495 | |||
496 | mode = PCI_PROBE_NORMAL; | ||
497 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
498 | if (ppc_md.pci_probe_mode) | ||
499 | mode = ppc_md.pci_probe_mode(bus); | ||
500 | if (mode == PCI_PROBE_DEVTREE) { | ||
501 | bus->subordinate = hose->last_busno; | ||
502 | of_scan_bus(node, bus); | ||
503 | } | ||
504 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
505 | if (mode == PCI_PROBE_NORMAL) | ||
506 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
507 | pci_bus_add_devices(bus); | ||
508 | } | ||
509 | |||
228 | static int __init pcibios_init(void) | 510 | static int __init pcibios_init(void) |
229 | { | 511 | { |
230 | struct pci_controller *hose, *tmp; | 512 | struct pci_controller *hose, *tmp; |
231 | struct pci_bus *bus; | ||
232 | 513 | ||
233 | /* For now, override phys_mem_access_prot. If we need it, | 514 | /* For now, override phys_mem_access_prot. If we need it, |
234 | * later, we may move that initialization to each ppc_md | 515 | * later, we may move that initialization to each ppc_md |
@@ -242,13 +523,8 @@ static int __init pcibios_init(void) | |||
242 | printk("PCI: Probing PCI hardware\n"); | 523 | printk("PCI: Probing PCI hardware\n"); |
243 | 524 | ||
244 | /* Scan all of the recorded PCI controllers. */ | 525 | /* Scan all of the recorded PCI controllers. */ |
245 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 526 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
246 | hose->last_busno = 0xff; | 527 | scan_phb(hose); |
247 | bus = pci_scan_bus(hose->first_busno, hose->ops, | ||
248 | hose->arch_data); | ||
249 | hose->bus = bus; | ||
250 | hose->last_busno = bus->subordinate; | ||
251 | } | ||
252 | 528 | ||
253 | #ifndef CONFIG_PPC_ISERIES | 529 | #ifndef CONFIG_PPC_ISERIES |
254 | if (pci_probe_only) | 530 | if (pci_probe_only) |
@@ -820,120 +1096,89 @@ void phbs_remap_io(void) | |||
820 | /* | 1096 | /* |
821 | * ppc64 can have multifunction devices that do not respond to function 0. | 1097 | * ppc64 can have multifunction devices that do not respond to function 0. |
822 | * In this case we must scan all functions. | 1098 | * In this case we must scan all functions. |
1099 | * XXX this can go now, we use the OF device tree in all the | ||
1100 | * cases that caused problems. -- paulus | ||
823 | */ | 1101 | */ |
824 | int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) | 1102 | int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) |
825 | { | 1103 | { |
826 | struct device_node *busdn, *dn; | ||
827 | |||
828 | if (bus->self) | ||
829 | busdn = pci_device_to_OF_node(bus->self); | ||
830 | else | ||
831 | busdn = bus->sysdata; /* must be a phb */ | ||
832 | |||
833 | if (busdn == NULL) | ||
834 | return 0; | ||
835 | |||
836 | /* | ||
837 | * Check to see if there is any of the 8 functions are in the | ||
838 | * device tree. If they are then we need to scan all the | ||
839 | * functions of this slot. | ||
840 | */ | ||
841 | for (dn = busdn->child; dn; dn = dn->sibling) { | ||
842 | struct pci_dn *pdn = dn->data; | ||
843 | if (pdn && (pdn->devfn >> 3) == (devfn >> 3)) | ||
844 | return 1; | ||
845 | } | ||
846 | |||
847 | return 0; | 1104 | return 0; |
848 | } | 1105 | } |
849 | 1106 | ||
1107 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||
1108 | { | ||
1109 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
1110 | unsigned long start, end, mask, offset; | ||
1111 | |||
1112 | if (res->flags & IORESOURCE_IO) { | ||
1113 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
1114 | |||
1115 | start = res->start += offset; | ||
1116 | end = res->end += offset; | ||
1117 | |||
1118 | /* Need to allow IO access to pages that are in the | ||
1119 | ISA range */ | ||
1120 | if (start < MAX_ISA_PORT) { | ||
1121 | if (end > MAX_ISA_PORT) | ||
1122 | end = MAX_ISA_PORT; | ||
1123 | |||
1124 | start >>= PAGE_SHIFT; | ||
1125 | end >>= PAGE_SHIFT; | ||
1126 | |||
1127 | /* get the range of pages for the map */ | ||
1128 | mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); | ||
1129 | io_page_mask |= mask; | ||
1130 | } | ||
1131 | } else if (res->flags & IORESOURCE_MEM) { | ||
1132 | res->start += hose->pci_mem_offset; | ||
1133 | res->end += hose->pci_mem_offset; | ||
1134 | } | ||
1135 | } | ||
850 | 1136 | ||
851 | void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | 1137 | void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, |
852 | struct pci_bus *bus) | 1138 | struct pci_bus *bus) |
853 | { | 1139 | { |
854 | /* Update device resources. */ | 1140 | /* Update device resources. */ |
855 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
856 | int i; | 1141 | int i; |
857 | 1142 | ||
858 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | 1143 | for (i = 0; i < PCI_NUM_RESOURCES; i++) |
859 | if (dev->resource[i].flags & IORESOURCE_IO) { | 1144 | if (dev->resource[i].flags) |
860 | unsigned long offset = (unsigned long)hose->io_base_virt | 1145 | fixup_resource(&dev->resource[i], dev); |
861 | - pci_io_base; | ||
862 | unsigned long start, end, mask; | ||
863 | |||
864 | start = dev->resource[i].start += offset; | ||
865 | end = dev->resource[i].end += offset; | ||
866 | |||
867 | /* Need to allow IO access to pages that are in the | ||
868 | ISA range */ | ||
869 | if (start < MAX_ISA_PORT) { | ||
870 | if (end > MAX_ISA_PORT) | ||
871 | end = MAX_ISA_PORT; | ||
872 | |||
873 | start >>= PAGE_SHIFT; | ||
874 | end >>= PAGE_SHIFT; | ||
875 | |||
876 | /* get the range of pages for the map */ | ||
877 | mask = ((1 << (end+1))-1) ^ ((1 << start)-1); | ||
878 | io_page_mask |= mask; | ||
879 | } | ||
880 | } | ||
881 | else if (dev->resource[i].flags & IORESOURCE_MEM) { | ||
882 | dev->resource[i].start += hose->pci_mem_offset; | ||
883 | dev->resource[i].end += hose->pci_mem_offset; | ||
884 | } | ||
885 | } | ||
886 | } | 1146 | } |
887 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 1147 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
888 | 1148 | ||
889 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 1149 | static void __devinit do_bus_setup(struct pci_bus *bus) |
890 | { | 1150 | { |
891 | struct pci_controller *hose = pci_bus_to_host(bus); | 1151 | struct pci_dev *dev; |
892 | struct pci_dev *dev = bus->self; | ||
893 | struct resource *res; | ||
894 | int i; | ||
895 | 1152 | ||
896 | if (!dev) { | 1153 | ppc_md.iommu_bus_setup(bus); |
897 | /* Root bus. */ | ||
898 | 1154 | ||
899 | hose->bus = bus; | 1155 | list_for_each_entry(dev, &bus->devices, bus_list) |
900 | bus->resource[0] = res = &hose->io_resource; | 1156 | ppc_md.iommu_dev_setup(dev); |
901 | 1157 | ||
902 | if (res->flags && request_resource(&ioport_resource, res)) | 1158 | if (ppc_md.irq_bus_setup) |
903 | printk(KERN_ERR "Failed to request IO on " | 1159 | ppc_md.irq_bus_setup(bus); |
904 | "PCI domain %d\n", pci_domain_nr(bus)); | 1160 | } |
905 | 1161 | ||
906 | for (i = 0; i < 3; ++i) { | 1162 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) |
907 | res = &hose->mem_resources[i]; | 1163 | { |
908 | bus->resource[i+1] = res; | 1164 | struct pci_dev *dev = bus->self; |
909 | if (res->flags && request_resource(&iomem_resource, res)) | 1165 | |
910 | printk(KERN_ERR "Failed to request MEM on " | 1166 | if (dev && pci_probe_only && |
911 | "PCI domain %d\n", | 1167 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
912 | pci_domain_nr(bus)); | ||
913 | } | ||
914 | } else if (pci_probe_only && | ||
915 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
916 | /* This is a subordinate bridge */ | 1168 | /* This is a subordinate bridge */ |
917 | 1169 | ||
918 | pci_read_bridge_bases(bus); | 1170 | pci_read_bridge_bases(bus); |
919 | pcibios_fixup_device_resources(dev, bus); | 1171 | pcibios_fixup_device_resources(dev, bus); |
920 | } | 1172 | } |
921 | 1173 | ||
922 | ppc_md.iommu_bus_setup(bus); | 1174 | do_bus_setup(bus); |
923 | |||
924 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
925 | ppc_md.iommu_dev_setup(dev); | ||
926 | |||
927 | if (ppc_md.irq_bus_setup) | ||
928 | ppc_md.irq_bus_setup(bus); | ||
929 | 1175 | ||
930 | if (!pci_probe_only) | 1176 | if (!pci_probe_only) |
931 | return; | 1177 | return; |
932 | 1178 | ||
933 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1179 | list_for_each_entry(dev, &bus->devices, bus_list) |
934 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | 1180 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) |
935 | pcibios_fixup_device_resources(dev, bus); | 1181 | pcibios_fixup_device_resources(dev, bus); |
936 | } | ||
937 | } | 1182 | } |
938 | EXPORT_SYMBOL(pcibios_fixup_bus); | 1183 | EXPORT_SYMBOL(pcibios_fixup_bus); |
939 | 1184 | ||
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c index d37bff2d7d40..dc40a0cad0b4 100644 --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c | |||
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose) | |||
388 | * the reg address cell, we shall fix that by killing struct | 388 | * the reg address cell, we shall fix that by killing struct |
389 | * reg_property and using some accessor functions instead | 389 | * reg_property and using some accessor functions instead |
390 | */ | 390 | */ |
391 | hose->first_busno = 0xf0; | 391 | hose->first_busno = 0xf0; |
392 | hose->last_busno = 0xff; | 392 | hose->last_busno = 0xff; |
393 | has_uninorth = 1; | 393 | has_uninorth = 1; |
394 | hose->ops = ¯isc_pci_ops; | 394 | hose->ops = ¯isc_pci_ops; |
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
473 | continue; | 473 | continue; |
474 | } | 474 | } |
475 | cur++; | 475 | cur++; |
476 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", | 476 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", |
477 | cur-1, res->start - 1, cur, res->end + 1); | 477 | cur-1, res->start - 1, cur, res->end + 1); |
478 | hose->mem_resources[cur].name = np->full_name; | 478 | hose->mem_resources[cur].name = np->full_name; |
479 | hose->mem_resources[cur].flags = IORESOURCE_MEM; | 479 | hose->mem_resources[cur].flags = IORESOURCE_MEM; |
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev) | |||
603 | char* disp_name; | 603 | char* disp_name; |
604 | int *bus_range; | 604 | int *bus_range; |
605 | int primary = 1; | 605 | int primary = 1; |
606 | struct property *of_prop; | 606 | struct property *of_prop; |
607 | 607 | ||
608 | DBG("Adding PCI host bridge %s\n", dev->full_name); | 608 | DBG("Adding PCI host bridge %s\n", dev->full_name); |
609 | 609 | ||
610 | bus_range = (int *) get_property(dev, "bus-range", &len); | 610 | bus_range = (int *) get_property(dev, "bus-range", &len); |
611 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 611 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
612 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | 612 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", |
613 | dev->full_name); | 613 | dev->full_name); |
614 | } | 614 | } |
615 | 615 | ||
616 | hose = alloc_bootmem(sizeof(struct pci_controller)); | 616 | hose = alloc_bootmem(sizeof(struct pci_controller)); |
617 | if (hose == NULL) | 617 | if (hose == NULL) |
618 | return -ENOMEM; | 618 | return -ENOMEM; |
619 | pci_setup_pci_controller(hose); | 619 | pci_setup_pci_controller(hose); |
620 | 620 | ||
621 | hose->arch_data = dev; | 621 | hose->arch_data = dev; |
622 | hose->first_busno = bus_range ? bus_range[0] : 0; | 622 | hose->first_busno = bus_range ? bus_range[0] : 0; |
623 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 623 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
624 | 624 | ||
625 | of_prop = alloc_bootmem(sizeof(struct property) + | 625 | of_prop = alloc_bootmem(sizeof(struct property) + |
626 | sizeof(hose->global_number)); | 626 | sizeof(hose->global_number)); |
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev) | |||
634 | } | 634 | } |
635 | 635 | ||
636 | disp_name = NULL; | 636 | disp_name = NULL; |
637 | if (device_is_compatible(dev, "u3-agp")) { | 637 | if (device_is_compatible(dev, "u3-agp")) { |
638 | setup_u3_agp(hose); | 638 | setup_u3_agp(hose); |
639 | disp_name = "U3-AGP"; | 639 | disp_name = "U3-AGP"; |
640 | primary = 0; | 640 | primary = 0; |
641 | } else if (device_is_compatible(dev, "u3-ht")) { | 641 | } else if (device_is_compatible(dev, "u3-ht")) { |
642 | setup_u3_ht(hose); | 642 | setup_u3_ht(hose); |
643 | disp_name = "U3-HT"; | 643 | disp_name = "U3-HT"; |
644 | primary = 1; | 644 | primary = 1; |
645 | } | 645 | } |
646 | printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", | 646 | printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", |
647 | disp_name, hose->first_busno, hose->last_busno); | 647 | disp_name, hose->first_busno, hose->last_busno); |
648 | 648 | ||
649 | /* Interpret the "ranges" property */ | 649 | /* Interpret the "ranges" property */ |
650 | /* This also maps the I/O region and sets isa_io/mem_base */ | 650 | /* This also maps the I/O region and sets isa_io/mem_base */ |
651 | pmac_process_bridge_OF_ranges(hose, dev, primary); | 651 | pmac_process_bridge_OF_ranges(hose, dev, primary); |
652 | 652 | ||
653 | /* Fixup "bus-range" OF property */ | 653 | /* Fixup "bus-range" OF property */ |
654 | fixup_bus_range(dev); | 654 | fixup_bus_range(dev); |
655 | 655 | ||
656 | return 0; | 656 | return 0; |
657 | } | 657 | } |
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index e7f695dcd8c8..325426c7bed0 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c | |||
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform) | |||
477 | return 1; | 477 | return 1; |
478 | } | 478 | } |
479 | 479 | ||
480 | static int pmac_probe_mode(struct pci_bus *bus) | ||
481 | { | ||
482 | struct device_node *node = bus->sysdata; | ||
483 | |||
484 | /* We need to use normal PCI probing for the AGP bus, | ||
485 | since the device for the AGP bridge isn't in the tree. */ | ||
486 | if (bus->self == NULL && device_is_compatible(node, "u3-agp")) | ||
487 | return PCI_PROBE_NORMAL; | ||
488 | |||
489 | return PCI_PROBE_DEVTREE; | ||
490 | } | ||
491 | |||
480 | struct machdep_calls __initdata pmac_md = { | 492 | struct machdep_calls __initdata pmac_md = { |
481 | #ifdef CONFIG_HOTPLUG_CPU | 493 | #ifdef CONFIG_HOTPLUG_CPU |
482 | .cpu_die = generic_mach_cpu_die, | 494 | .cpu_die = generic_mach_cpu_die, |
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = { | |||
488 | .init_IRQ = pmac_init_IRQ, | 500 | .init_IRQ = pmac_init_IRQ, |
489 | .get_irq = mpic_get_irq, | 501 | .get_irq = mpic_get_irq, |
490 | .pcibios_fixup = pmac_pcibios_fixup, | 502 | .pcibios_fixup = pmac_pcibios_fixup, |
503 | .pci_probe_mode = pmac_probe_mode, | ||
491 | .restart = pmac_restart, | 504 | .restart = pmac_restart, |
492 | .power_off = pmac_power_off, | 505 | .power_off = pmac_power_off, |
493 | .halt = pmac_halt, | 506 | .halt = pmac_halt, |
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 7a7e027653ad..887005358eb1 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <asm/sections.h> | 54 | #include <asm/sections.h> |
55 | #include <asm/tlbflush.h> | 55 | #include <asm/tlbflush.h> |
56 | #include <asm/time.h> | 56 | #include <asm/time.h> |
57 | #include <asm/plpar_wrappers.h> | ||
57 | 58 | ||
58 | #ifndef CONFIG_SMP | 59 | #ifndef CONFIG_SMP |
59 | struct task_struct *last_task_used_math = NULL; | 60 | struct task_struct *last_task_used_math = NULL; |
@@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) | |||
163 | 164 | ||
164 | #endif /* CONFIG_ALTIVEC */ | 165 | #endif /* CONFIG_ALTIVEC */ |
165 | 166 | ||
167 | static void set_dabr_spr(unsigned long val) | ||
168 | { | ||
169 | mtspr(SPRN_DABR, val); | ||
170 | } | ||
171 | |||
172 | int set_dabr(unsigned long dabr) | ||
173 | { | ||
174 | int ret = 0; | ||
175 | |||
176 | if (firmware_has_feature(FW_FEATURE_XDABR)) { | ||
177 | /* We want to catch accesses from kernel and userspace */ | ||
178 | unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER; | ||
179 | ret = plpar_set_xdabr(dabr, flags); | ||
180 | } else if (firmware_has_feature(FW_FEATURE_DABR)) { | ||
181 | ret = plpar_set_dabr(dabr); | ||
182 | } else { | ||
183 | set_dabr_spr(dabr); | ||
184 | } | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
166 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | 189 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); |
190 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
167 | 191 | ||
168 | struct task_struct *__switch_to(struct task_struct *prev, | 192 | struct task_struct *__switch_to(struct task_struct *prev, |
169 | struct task_struct *new) | 193 | struct task_struct *new) |
@@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
198 | new->thread.regs->msr |= MSR_VEC; | 222 | new->thread.regs->msr |= MSR_VEC; |
199 | #endif /* CONFIG_ALTIVEC */ | 223 | #endif /* CONFIG_ALTIVEC */ |
200 | 224 | ||
225 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { | ||
226 | set_dabr(new->thread.dabr); | ||
227 | __get_cpu_var(current_dabr) = new->thread.dabr; | ||
228 | } | ||
229 | |||
201 | flush_tlb_pending(); | 230 | flush_tlb_pending(); |
202 | 231 | ||
203 | new_thread = &new->thread; | 232 | new_thread = &new->thread; |
@@ -334,6 +363,11 @@ void flush_thread(void) | |||
334 | last_task_used_altivec = NULL; | 363 | last_task_used_altivec = NULL; |
335 | #endif /* CONFIG_ALTIVEC */ | 364 | #endif /* CONFIG_ALTIVEC */ |
336 | #endif /* CONFIG_SMP */ | 365 | #endif /* CONFIG_SMP */ |
366 | |||
367 | if (current->thread.dabr) { | ||
368 | current->thread.dabr = 0; | ||
369 | set_dabr(0); | ||
370 | } | ||
337 | } | 371 | } |
338 | 372 | ||
339 | void | 373 | void |
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index 2993f108d96d..85ed3188a91d 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * this archive for more details. | 17 | * this archive for more details. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/config.h> | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
206 | break; | 207 | break; |
207 | } | 208 | } |
208 | 209 | ||
210 | case PTRACE_GET_DEBUGREG: { | ||
211 | ret = -EINVAL; | ||
212 | /* We only support one DABR and no IABRS at the moment */ | ||
213 | if (addr > 0) | ||
214 | break; | ||
215 | ret = put_user(child->thread.dabr, | ||
216 | (unsigned long __user *)data); | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | case PTRACE_SET_DEBUGREG: | ||
221 | ret = ptrace_set_debugreg(child, addr, data); | ||
222 | |||
209 | case PTRACE_DETACH: | 223 | case PTRACE_DETACH: |
210 | ret = ptrace_detach(child, data); | 224 | ret = ptrace_detach(child, data); |
211 | break; | 225 | break; |
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
274 | break; | 288 | break; |
275 | } | 289 | } |
276 | 290 | ||
291 | #ifdef CONFIG_ALTIVEC | ||
292 | case PTRACE_GETVRREGS: | ||
293 | /* Get the child altivec register state. */ | ||
294 | flush_altivec_to_thread(child); | ||
295 | ret = get_vrregs((unsigned long __user *)data, child); | ||
296 | break; | ||
297 | |||
298 | case PTRACE_SETVRREGS: | ||
299 | /* Set the child altivec register state. */ | ||
300 | flush_altivec_to_thread(child); | ||
301 | ret = set_vrregs(child, (unsigned long __user *)data); | ||
302 | break; | ||
303 | #endif | ||
304 | |||
277 | default: | 305 | default: |
278 | ret = ptrace_request(child, request, addr, data); | 306 | ret = ptrace_request(child, request, addr, data); |
279 | break; | 307 | break; |
diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index 16436426c7e2..fb8c22d6084a 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * this archive for more details. | 17 | * this archive for more details. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/config.h> | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) | |||
337 | break; | 338 | break; |
338 | } | 339 | } |
339 | 340 | ||
341 | case PTRACE_GET_DEBUGREG: { | ||
342 | ret = -EINVAL; | ||
343 | /* We only support one DABR and no IABRS at the moment */ | ||
344 | if (addr > 0) | ||
345 | break; | ||
346 | ret = put_user(child->thread.dabr, (u32 __user *)data); | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | case PTRACE_SET_DEBUGREG: | ||
351 | ret = ptrace_set_debugreg(child, addr, data); | ||
352 | break; | ||
353 | |||
340 | case PTRACE_DETACH: | 354 | case PTRACE_DETACH: |
341 | ret = ptrace_detach(child, data); | 355 | ret = ptrace_detach(child, data); |
342 | break; | 356 | break; |
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) | |||
405 | break; | 419 | break; |
406 | } | 420 | } |
407 | 421 | ||
408 | case PTRACE_GETEVENTMSG: | 422 | case PTRACE_GETEVENTMSG: |
409 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | 423 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); |
410 | break; | 424 | break; |
425 | |||
426 | #ifdef CONFIG_ALTIVEC | ||
427 | case PTRACE_GETVRREGS: | ||
428 | /* Get the child altivec register state. */ | ||
429 | flush_altivec_to_thread(child); | ||
430 | ret = get_vrregs((unsigned long __user *)data, child); | ||
431 | break; | ||
432 | |||
433 | case PTRACE_SETVRREGS: | ||
434 | /* Set the child altivec register state. */ | ||
435 | flush_altivec_to_thread(child); | ||
436 | ret = set_vrregs(child, (unsigned long __user *)data); | ||
437 | break; | ||
438 | #endif | ||
411 | 439 | ||
412 | default: | 440 | default: |
413 | ret = ptrace_request(child, request, addr, data); | 441 | ret = ptrace_request(child, request, addr, data); |
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c index 3c00f7bfc1b5..41b97dc9cc0a 100644 --- a/arch/ppc64/kernel/ras.c +++ b/arch/ppc64/kernel/ras.c | |||
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX] | |||
59 | /* This is true if we are using the firmware NMI handler (typically LPAR) */ | 59 | /* This is true if we are using the firmware NMI handler (typically LPAR) */ |
60 | extern int fwnmi_active; | 60 | extern int fwnmi_active; |
61 | 61 | ||
62 | extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr); | ||
63 | |||
64 | static int ras_get_sensor_state_token; | 62 | static int ras_get_sensor_state_token; |
65 | static int ras_check_exception_token; | 63 | static int ras_check_exception_token; |
66 | 64 | ||
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index bfa8791c9807..5ac48bd64891 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c | |||
@@ -1064,8 +1064,6 @@ void __init setup_arch(char **cmdline_p) | |||
1064 | #define PPC64_LINUX_FUNCTION 0x0f000000 | 1064 | #define PPC64_LINUX_FUNCTION 0x0f000000 |
1065 | #define PPC64_IPL_MESSAGE 0xc0000000 | 1065 | #define PPC64_IPL_MESSAGE 0xc0000000 |
1066 | #define PPC64_TERM_MESSAGE 0xb0000000 | 1066 | #define PPC64_TERM_MESSAGE 0xb0000000 |
1067 | #define PPC64_ATTN_MESSAGE 0xa0000000 | ||
1068 | #define PPC64_DUMP_MESSAGE 0xd0000000 | ||
1069 | 1067 | ||
1070 | static void ppc64_do_msg(unsigned int src, const char *msg) | 1068 | static void ppc64_do_msg(unsigned int src, const char *msg) |
1071 | { | 1069 | { |
@@ -1093,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg) | |||
1093 | printk("[terminate]%04x %s\n", src, msg); | 1091 | printk("[terminate]%04x %s\n", src, msg); |
1094 | } | 1092 | } |
1095 | 1093 | ||
1096 | /* Print something that needs attention (device error, etc) */ | ||
1097 | void ppc64_attention_msg(unsigned int src, const char *msg) | ||
1098 | { | ||
1099 | ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg); | ||
1100 | printk("[attention]%04x %s\n", src, msg); | ||
1101 | } | ||
1102 | |||
1103 | /* Print a dump progress message. */ | ||
1104 | void ppc64_dump_msg(unsigned int src, const char *msg) | ||
1105 | { | ||
1106 | ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg); | ||
1107 | printk("[dump]%04x %s\n", src, msg); | ||
1108 | } | ||
1109 | |||
1110 | /* This should only be called on processor 0 during calibrate decr */ | 1094 | /* This should only be called on processor 0 during calibrate decr */ |
1111 | void __init setup_default_decr(void) | 1095 | void __init setup_default_decr(void) |
1112 | { | 1096 | { |
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c index 49a79a55c32d..347112cca3c0 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/ppc64/kernel/signal.c | |||
@@ -550,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
550 | /* Whee! Actually deliver the signal. */ | 550 | /* Whee! Actually deliver the signal. */ |
551 | if (TRAP(regs) == 0x0C00) | 551 | if (TRAP(regs) == 0x0C00) |
552 | syscall_restart(regs, &ka); | 552 | syscall_restart(regs, &ka); |
553 | |||
554 | /* | ||
555 | * Reenable the DABR before delivering the signal to | ||
556 | * user space. The DABR will have been cleared if it | ||
557 | * triggered inside the kernel. | ||
558 | */ | ||
559 | if (current->thread.dabr) | ||
560 | set_dabr(current->thread.dabr); | ||
561 | |||
553 | return handle_signal(signr, &ka, &info, oldset, regs); | 562 | return handle_signal(signr, &ka, &info, oldset, regs); |
554 | } | 563 | } |
555 | 564 | ||
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index 46f4d6cc7fc9..a8b7a5a56bb4 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c | |||
@@ -970,6 +970,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) | |||
970 | newsp = regs->gpr[1]; | 970 | newsp = regs->gpr[1]; |
971 | newsp &= ~0xfUL; | 971 | newsp &= ~0xfUL; |
972 | 972 | ||
973 | /* | ||
974 | * Reenable the DABR before delivering the signal to | ||
975 | * user space. The DABR will have been cleared if it | ||
976 | * triggered inside the kernel. | ||
977 | */ | ||
978 | if (current->thread.dabr) | ||
979 | set_dabr(current->thread.dabr); | ||
980 | |||
973 | /* Whee! Actually deliver the signal. */ | 981 | /* Whee! Actually deliver the signal. */ |
974 | if (ka.sa.sa_flags & SA_SIGINFO) | 982 | if (ka.sa.sa_flags & SA_SIGINFO) |
975 | ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); | 983 | ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); |
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index d9dc6f28d050..daf93885dcfa 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c | |||
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq); | |||
38 | static void xics_end_irq(unsigned int irq); | 38 | static void xics_end_irq(unsigned int irq); |
39 | static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); | 39 | static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); |
40 | 40 | ||
41 | struct hw_interrupt_type xics_pic = { | 41 | static struct hw_interrupt_type xics_pic = { |
42 | .typename = " XICS ", | 42 | .typename = " XICS ", |
43 | .startup = xics_startup, | 43 | .startup = xics_startup, |
44 | .enable = xics_enable_irq, | 44 | .enable = xics_enable_irq, |
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = { | |||
48 | .set_affinity = xics_set_affinity | 48 | .set_affinity = xics_set_affinity |
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct hw_interrupt_type xics_8259_pic = { | 51 | static struct hw_interrupt_type xics_8259_pic = { |
52 | .typename = " XICS/8259", | 52 | .typename = " XICS/8259", |
53 | .ack = xics_mask_and_ack_irq, | 53 | .ack = xics_mask_and_ack_irq, |
54 | }; | 54 | }; |
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS]; | |||
89 | static int xics_irq_8259_cascade = 0; | 89 | static int xics_irq_8259_cascade = 0; |
90 | static int xics_irq_8259_cascade_real = 0; | 90 | static int xics_irq_8259_cascade_real = 0; |
91 | static unsigned int default_server = 0xFF; | 91 | static unsigned int default_server = 0xFF; |
92 | /* also referenced in smp.c... */ | 92 | static unsigned int default_distrib_server = 0; |
93 | unsigned int default_distrib_server = 0; | 93 | static unsigned int interrupt_server_size = 8; |
94 | unsigned int interrupt_server_size = 8; | ||
95 | 94 | ||
96 | /* | 95 | /* |
97 | * XICS only has a single IPI, so encode the messages per CPU | 96 | * XICS only has a single IPI, so encode the messages per CPU |
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8; | |||
99 | struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; | 98 | struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; |
100 | 99 | ||
101 | /* RTAS service tokens */ | 100 | /* RTAS service tokens */ |
102 | int ibm_get_xive; | 101 | static int ibm_get_xive; |
103 | int ibm_set_xive; | 102 | static int ibm_set_xive; |
104 | int ibm_int_on; | 103 | static int ibm_int_on; |
105 | int ibm_int_off; | 104 | static int ibm_int_off; |
106 | 105 | ||
107 | typedef struct { | 106 | typedef struct { |
108 | int (*xirr_info_get)(int cpu); | 107 | int (*xirr_info_get)(int cpu); |
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq) | |||
284 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 283 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
285 | DEFAULT_PRIORITY); | 284 | DEFAULT_PRIORITY); |
286 | if (call_status != 0) { | 285 | if (call_status != 0) { |
287 | printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive " | 286 | printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive " |
288 | "returned %x\n", irq, call_status); | 287 | "returned %d\n", irq, call_status); |
288 | printk("set_xive %x, server %x\n", ibm_set_xive, server); | ||
289 | return; | 289 | return; |
290 | } | 290 | } |
291 | 291 | ||
292 | /* Now unmask the interrupt (often a no-op) */ | 292 | /* Now unmask the interrupt (often a no-op) */ |
293 | call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); | 293 | call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); |
294 | if (call_status != 0) { | 294 | if (call_status != 0) { |
295 | printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on " | 295 | printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on " |
296 | "returned %x\n", irq, call_status); | 296 | "returned %d\n", irq, call_status); |
297 | return; | 297 | return; |
298 | } | 298 | } |
299 | } | 299 | } |
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq) | |||
308 | 308 | ||
309 | call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); | 309 | call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); |
310 | if (call_status != 0) { | 310 | if (call_status != 0) { |
311 | printk(KERN_ERR "xics_disable_real_irq: irq=%d: " | 311 | printk(KERN_ERR "xics_disable_real_irq: irq=%u: " |
312 | "ibm_int_off returned %x\n", irq, call_status); | 312 | "ibm_int_off returned %d\n", irq, call_status); |
313 | return; | 313 | return; |
314 | } | 314 | } |
315 | 315 | ||
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq) | |||
317 | /* Have to set XIVE to 0xff to be able to remove a slot */ | 317 | /* Have to set XIVE to 0xff to be able to remove a slot */ |
318 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); | 318 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); |
319 | if (call_status != 0) { | 319 | if (call_status != 0) { |
320 | printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)" | 320 | printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)" |
321 | " returned %x\n", irq, call_status); | 321 | " returned %d\n", irq, call_status); |
322 | return; | 322 | return; |
323 | } | 323 | } |
324 | } | 324 | } |
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs) | |||
380 | if (irq == NO_IRQ) | 380 | if (irq == NO_IRQ) |
381 | irq = real_irq_to_virt_slowpath(vec); | 381 | irq = real_irq_to_virt_slowpath(vec); |
382 | if (irq == NO_IRQ) { | 382 | if (irq == NO_IRQ) { |
383 | printk(KERN_ERR "Interrupt %d (real) is invalid," | 383 | printk(KERN_ERR "Interrupt %u (real) is invalid," |
384 | " disabling it.\n", vec); | 384 | " disabling it.\n", vec); |
385 | xics_disable_real_irq(vec); | 385 | xics_disable_real_irq(vec); |
386 | } else | 386 | } else |
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
622 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); | 622 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); |
623 | 623 | ||
624 | if (status) { | 624 | if (status) { |
625 | printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive " | 625 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive " |
626 | "returns %d\n", irq, status); | 626 | "returns %d\n", irq, status); |
627 | return; | 627 | return; |
628 | } | 628 | } |
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
641 | irq, newmask, xics_status[1]); | 641 | irq, newmask, xics_status[1]); |
642 | 642 | ||
643 | if (status) { | 643 | if (status) { |
644 | printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive " | 644 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " |
645 | "returns %d\n", irq, status); | 645 | "returns %d\n", irq, status); |
646 | return; | 646 | return; |
647 | } | 647 | } |
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void) | |||
720 | 720 | ||
721 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); | 721 | status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); |
722 | if (status) { | 722 | if (status) { |
723 | printk(KERN_ERR "migrate_irqs_away: irq=%d " | 723 | printk(KERN_ERR "migrate_irqs_away: irq=%u " |
724 | "ibm,get-xive returns %d\n", | 724 | "ibm,get-xive returns %d\n", |
725 | virq, status); | 725 | virq, status); |
726 | goto unlock; | 726 | goto unlock; |
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void) | |||
734 | if (xics_status[0] != get_hard_smp_processor_id(cpu)) | 734 | if (xics_status[0] != get_hard_smp_processor_id(cpu)) |
735 | goto unlock; | 735 | goto unlock; |
736 | 736 | ||
737 | printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n", | 737 | printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n", |
738 | virq, cpu); | 738 | virq, cpu); |
739 | 739 | ||
740 | /* Reset affinity to all cpus */ | 740 | /* Reset affinity to all cpus */ |
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 772f0714a5b7..7fbc68bbb739 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c | |||
@@ -77,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs) | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | static void do_dabr(struct pt_regs *regs, unsigned long error_code) | ||
81 | { | ||
82 | siginfo_t info; | ||
83 | |||
84 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
85 | 11, SIGSEGV) == NOTIFY_STOP) | ||
86 | return; | ||
87 | |||
88 | if (debugger_dabr_match(regs)) | ||
89 | return; | ||
90 | |||
91 | /* Clear the DABR */ | ||
92 | set_dabr(0); | ||
93 | |||
94 | /* Deliver the signal to userspace */ | ||
95 | info.si_signo = SIGTRAP; | ||
96 | info.si_errno = 0; | ||
97 | info.si_code = TRAP_HWBKPT; | ||
98 | info.si_addr = (void __user *)regs->nip; | ||
99 | force_sig_info(SIGTRAP, &info, current); | ||
100 | } | ||
101 | |||
80 | /* | 102 | /* |
81 | * The error_code parameter is | 103 | * The error_code parameter is |
82 | * - DSISR for a non-SLB data access fault, | 104 | * - DSISR for a non-SLB data access fault, |
@@ -111,12 +133,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
111 | if (!user_mode(regs) && (address >= TASK_SIZE)) | 133 | if (!user_mode(regs) && (address >= TASK_SIZE)) |
112 | return SIGSEGV; | 134 | return SIGSEGV; |
113 | 135 | ||
114 | if (error_code & DSISR_DABRMATCH) { | 136 | if (error_code & DSISR_DABRMATCH) { |
115 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | 137 | do_dabr(regs, error_code); |
116 | 11, SIGSEGV) == NOTIFY_STOP) | 138 | return 0; |
117 | return 0; | ||
118 | if (debugger_dabr_match(regs)) | ||
119 | return 0; | ||
120 | } | 139 | } |
121 | 140 | ||
122 | if (in_atomic() || mm == NULL) { | 141 | if (in_atomic() || mm == NULL) { |
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h index 183c3e400258..02eb40dac0b3 100644 --- a/arch/ppc64/xmon/privinst.h +++ b/arch/ppc64/xmon/privinst.h | |||
@@ -46,7 +46,6 @@ GSETSPR(287, pvr) | |||
46 | GSETSPR(1008, hid0) | 46 | GSETSPR(1008, hid0) |
47 | GSETSPR(1009, hid1) | 47 | GSETSPR(1009, hid1) |
48 | GSETSPR(1010, iabr) | 48 | GSETSPR(1010, iabr) |
49 | GSETSPR(1013, dabr) | ||
50 | GSETSPR(1023, pir) | 49 | GSETSPR(1023, pir) |
51 | 50 | ||
52 | static inline void store_inst(void *p) | 51 | static inline void store_inst(void *p) |
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index 45908b10acd3..74e63a886a69 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c | |||
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs) | |||
586 | { | 586 | { |
587 | if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) | 587 | if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) |
588 | return 0; | 588 | return 0; |
589 | if (dabr.enabled == 0) | ||
590 | return 0; | ||
589 | xmon_core(regs, 0); | 591 | xmon_core(regs, 0); |
590 | return 1; | 592 | return 1; |
591 | } | 593 | } |
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs) | |||
628 | return 0; | 630 | return 0; |
629 | } | 631 | } |
630 | 632 | ||
631 | /* On systems with a hypervisor, we can't set the DABR | ||
632 | (data address breakpoint register) directly. */ | ||
633 | static void set_controlled_dabr(unsigned long val) | ||
634 | { | ||
635 | #ifdef CONFIG_PPC_PSERIES | ||
636 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | ||
637 | int rc = plpar_hcall_norets(H_SET_DABR, val); | ||
638 | if (rc != H_Success) | ||
639 | xmon_printf("Warning: setting DABR failed (%d)\n", rc); | ||
640 | } else | ||
641 | #endif | ||
642 | set_dabr(val); | ||
643 | } | ||
644 | |||
645 | static struct bpt *at_breakpoint(unsigned long pc) | 633 | static struct bpt *at_breakpoint(unsigned long pc) |
646 | { | 634 | { |
647 | int i; | 635 | int i; |
@@ -728,7 +716,7 @@ static void insert_bpts(void) | |||
728 | static void insert_cpu_bpts(void) | 716 | static void insert_cpu_bpts(void) |
729 | { | 717 | { |
730 | if (dabr.enabled) | 718 | if (dabr.enabled) |
731 | set_controlled_dabr(dabr.address | (dabr.enabled & 7)); | 719 | set_dabr(dabr.address | (dabr.enabled & 7)); |
732 | if (iabr && cpu_has_feature(CPU_FTR_IABR)) | 720 | if (iabr && cpu_has_feature(CPU_FTR_IABR)) |
733 | set_iabr(iabr->address | 721 | set_iabr(iabr->address |
734 | | (iabr->enabled & (BP_IABR|BP_IABR_TE))); | 722 | | (iabr->enabled & (BP_IABR|BP_IABR_TE))); |
@@ -756,7 +744,7 @@ static void remove_bpts(void) | |||
756 | 744 | ||
757 | static void remove_cpu_bpts(void) | 745 | static void remove_cpu_bpts(void) |
758 | { | 746 | { |
759 | set_controlled_dabr(0); | 747 | set_dabr(0); |
760 | if (cpu_has_feature(CPU_FTR_IABR)) | 748 | if (cpu_has_feature(CPU_FTR_IABR)) |
761 | set_iabr(0); | 749 | set_iabr(0); |
762 | } | 750 | } |