From 5e2bd00949f386b2e0758f2491b0b7253ea8c941 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 7 Mar 2005 19:57:10 -0800 Subject: [IA64] pci.c: PCI root busses need resources Using the generic setup-bus.c code currently fails on HP's Integrity servers because the root busses have their resources set to the whole of ioport space and the whole of iomem space, instead of just the ranges that are routed to that particular bus. This patch uses the resources in the pci_windows to provide the ranges to each PCI root bus. In order to do that, I had to change them from being bus addresses to system addresses. Signed-off-by: Matthew Wilcox Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 134 ++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 63 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 2a0dcf6083d62..33068bd1bba44 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -197,30 +197,6 @@ alloc_pci_controller (int seg) return controller; } -static int __devinit -alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, - unsigned long flags) -{ - struct resource *res; - - res = kmalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - memset(res, 0, sizeof(*res)); - res->name = name; - res->start = start; - res->end = end; - res->flags = flags; - - if (insert_resource(root, res)) { - kfree(res); - return -EBUSY; - } - - return 0; -} - static u64 __devinit add_io_space (struct acpi_resource_address64 *addr) { @@ -273,10 +249,9 @@ struct pci_root_info { char *name; }; -static acpi_status __devinit -add_window (struct acpi_resource *res, void *data) +static __devinit acpi_status add_window(struct acpi_resource *res, void *data) { - struct pci_root_info *info = (struct pci_root_info *) data; + struct pci_root_info *info = data; struct pci_window *window; struct acpi_resource_address64 addr; acpi_status status; @@ -284,45 +259,71 @@ add_window (struct acpi_resource *res, void *data) struct resource *root; status = acpi_resource_to_address64(res, &addr); - if (ACPI_SUCCESS(status)) { - if (!addr.address_length) + if (!ACPI_SUCCESS(status)) + return AE_OK; + + if (!addr.address_length) + return AE_OK; + + if (addr.resource_type == ACPI_MEMORY_RANGE) { + flags = IORESOURCE_MEM; + root = &iomem_resource; + offset = addr.address_translation_offset; + } else if (addr.resource_type == ACPI_IO_RANGE) { + flags = IORESOURCE_IO; + root = &ioport_resource; + offset = add_io_space(&addr); + if (offset == ~0) return AE_OK; - - if (addr.resource_type == ACPI_MEMORY_RANGE) { - flags = IORESOURCE_MEM; - root = &iomem_resource; - offset = addr.address_translation_offset; - } else if (addr.resource_type == ACPI_IO_RANGE) { - flags = IORESOURCE_IO; - root = &ioport_resource; - offset = add_io_space(&addr); - if (offset == ~0) - return AE_OK; - } else - return AE_OK; - - window = &info->controller->window[info->controller->windows++]; - window->resource.flags = flags; - window->resource.start = addr.min_address_range; - window->resource.end = addr.max_address_range; - window->offset = offset; - - if (alloc_resource(info->name, root, addr.min_address_range + offset, - addr.max_address_range + offset, flags)) - printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", - addr.min_address_range + offset, addr.max_address_range + offset, - root->name, info->name); + } else + return AE_OK; + + window = &info->controller->window[info->controller->windows++]; + window->resource.name = info->name; + window->resource.flags = flags; + window->resource.start = addr.min_address_range + offset; + window->resource.end = addr.max_address_range + offset; + window->resource.child = NULL; + window->offset = offset; + + if (insert_resource(root, &window->resource)) { + printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", + window->resource.start, window->resource.end, + root->name, info->name); } return AE_OK; } +static void __devinit +pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) +{ + int i, j; + + j = 0; + for (i = 0; i < ctrl->windows; i++) { + struct resource *res = &ctrl->window[i].resource; + /* HP's firmware has a hack to work around a Windows bug. + * Ignore these tiny memory ranges */ + if ((res->flags & IORESOURCE_MEM) && + (res->end - res->start < 16)) + continue; + if (j >= PCI_BUS_NUM_RESOURCES) { + printk("Ignoring range [%lx-%lx] (%lx)\n", res->start, + res->end, res->flags); + continue; + } + bus->resource[j++] = res; + } +} + struct pci_bus * __devinit -pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) +pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) { struct pci_root_info info; struct pci_controller *controller; unsigned int windows = 0; + struct pci_bus *pbus; char *name; controller = alloc_pci_controller(domain); @@ -331,8 +332,10 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) controller->acpi_handle = device->handle; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); - controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, + &windows); + controller->window = kmalloc(sizeof(*controller->window) * windows, + GFP_KERNEL); if (!controller->window) goto out2; @@ -343,9 +346,14 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) sprintf(name, "PCI Bus %04x:%02x", domain, bus); info.controller = controller; info.name = name; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, + &info); + + pbus = pci_scan_bus(bus, &pci_root_ops, controller); + if (pbus) + pcibios_setup_root_windows(pbus, controller); - return pci_scan_bus(bus, &pci_root_ops, controller); + return pbus; out3: kfree(controller->window); @@ -366,9 +374,9 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_window *window = &controller->window[i]; if (!(window->resource.flags & res->flags)) continue; - if (window->resource.start > res->start - window->offset) + if (window->resource.start > res->start) continue; - if (window->resource.end < res->end - window->offset) + if (window->resource.end < res->end) continue; offset = window->offset; break; @@ -390,9 +398,9 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct pci_window *window = &controller->window[i]; if (!(window->resource.flags & res->flags)) continue; - if (window->resource.start > region->start) + if (window->resource.start - window->offset > region->start) continue; - if (window->resource.end < region->end) + if (window->resource.end - window->offset < region->end) continue; offset = window->offset; break; -- cgit 1.2.3-korg From 8223648fd1f8e9d49649728d427fcbeac591c274 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 7 Mar 2005 22:45:52 -0800 Subject: [IA64-SGI] [PATCH 1/2] - New chipset support for SN platform - add new parameters to a platform-specific SAL call to retrieve addition chipset specific info. - change partition_coherence_id() so that it works on platforms using the new chipset. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 18 ++++++++++----- include/asm-ia64/sn/sn_cpuid.h | 5 +++-- include/asm-ia64/sn/sn_sal.h | 50 +++++++++++++++++++++++++++++++----------- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index a852077940fe0..a78197af95a50 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -76,6 +76,16 @@ char sn_system_serial_number_string[128]; EXPORT_SYMBOL(sn_system_serial_number_string); u64 sn_partition_serial_number; EXPORT_SYMBOL(sn_partition_serial_number); +u8 sn_partition_id; +EXPORT_SYMBOL(sn_partition_id); +u8 sn_system_size; +EXPORT_SYMBOL(sn_system_size); +u8 sn_sharing_domain_size; +EXPORT_SYMBOL(sn_sharing_domain_size); +u8 sn_coherency_id; +EXPORT_SYMBOL(sn_coherency_id); +u8 sn_region_size; +EXPORT_SYMBOL(sn_region_size); short physical_node_map[MAX_PHYSNODE_ID]; @@ -424,15 +434,13 @@ void __init sn_cpu_init(void) int slice; int cnode; int i; - u64 shubtype, nasid_bitmask, nasid_shift; static int wars_have_been_checked; memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_hub_info(0, &shubtype, &nasid_bitmask, &nasid_shift)) + if (ia64_sn_get_sn_info(0, &pda->shub2, &pda->nasid_bitmask, &pda->nasid_shift, + &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, + &sn_coherency_id, &sn_region_size)) BUG(); - pda->shub2 = (u8)shubtype; - pda->nasid_bitmask = (u16)nasid_bitmask; - pda->nasid_shift = (u8)nasid_shift; pda->as_shift = pda->nasid_shift - 2; /* diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h index 749f45042cdcc..685435af170d8 100644 --- a/include/asm-ia64/sn/sn_cpuid.h +++ b/include/asm-ia64/sn/sn_cpuid.h @@ -135,9 +135,10 @@ extern int nasid_slice_to_cpuid(int, int); #define nasid_to_cnodeid(nasid) (physical_node_map[nasid]) /* - * partition_coherence_id - cget the coherence ID of the current partition + * partition_coherence_id - get the coherence ID of the current partition */ -#define partition_coherence_id() (get_nasid() >> 9) +extern u8 sn_coherency_id; +#define partition_coherence_id() (sn_coherency_id) #endif /* _ASM_IA64_SN_SN_CPUID_H */ diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 4ecc05e8ad577..88c31b53dc097 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -18,6 +18,7 @@ #include #include #include +#include // SGI Specific Calls #define SN_SAL_POD_MODE 0x02000001 @@ -34,7 +35,7 @@ #define SN_SAL_PRINT_ERROR 0x02000012 #define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant #define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant -#define SN_SAL_GET_HUB_INFO 0x0200001c +#define SN_SAL_GET_SN_INFO 0x0200001c #define SN_SAL_GET_SAPIC_INFO 0x0200001d #define SN_SAL_CONSOLE_PUTC 0x02000021 #define SN_SAL_CONSOLE_GETC 0x02000022 @@ -935,15 +936,24 @@ ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice) /* * Returns information about the HUB/SHUB. * In: - * arg0 - SN_SAL_GET_HUB_INFO + * arg0 - SN_SAL_GET_SN_INFO * arg1 - 0 (other values reserved for future use) * Out: - * v0 - shub type (0=shub1, 1=shub2) - * v1 - masid mask (ex., 0x7ff for 11 bit nasid) - * v2 - bit position of low nasid bit + * v0 + * [7:0] - shub type (0=shub1, 1=shub2) + * [15:8] - Log2 max number of nodes in entire system (includes + * C-bricks, I-bricks, etc) + * [23:16] - Log2 of nodes per sharing domain + * [31:24] - partition ID + * [39:32] - coherency_id + * [47:40] - regionsize + * v1 + * [15:0] - nasid mask (ex., 0x7ff for 11 bit nasid) + * [23:15] - bit position of low nasid bit */ static inline u64 -ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) +ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift, + u8 *systemsize, u8 *sharing_domain_size, u8 *partid, u8 *coher, u8 *reg) { struct ia64_sal_retval ret_stuff; @@ -951,13 +961,22 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) ret_stuff.v0 = 0; ret_stuff.v1 = 0; ret_stuff.v2 = 0; - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_HUB_INFO, fc, 0, 0, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0); /***** BEGIN HACK - temp til old proms no longer supported ********/ if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) { - if (arg1) *arg1 = 0; - if (arg2) *arg2 = 0x7ff; - if (arg3) *arg3 = 38; + int nasid = get_sapicid() & 0xfff;; +#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL +#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48 + if (shubtype) *shubtype = 0; + if (nasid_bitmask) *nasid_bitmask = 0x7ff; + if (nasid_shift) *nasid_shift = 38; + if (systemsize) *systemsize = 11; + if (sharing_domain_size) *sharing_domain_size = 9; + if (partid) *partid = ia64_sn_sysctl_partition_get(nasid); + if (coher) *coher = nasid >> 9; + if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >> + SH_SHUB_ID_NODES_PER_BIT_SHFT; return 0; } /***** END HACK *******/ @@ -965,9 +984,14 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) if (ret_stuff.status < 0) return ret_stuff.status; - if (arg1) *arg1 = ret_stuff.v0; - if (arg2) *arg2 = ret_stuff.v1; - if (arg3) *arg3 = ret_stuff.v2; + if (shubtype) *shubtype = ret_stuff.v0 & 0xff; + if (systemsize) *systemsize = (ret_stuff.v0 >> 8) & 0xff; + if (sharing_domain_size) *sharing_domain_size = (ret_stuff.v0 >> 16) & 0xff; + if (partid) *partid = (ret_stuff.v0 >> 24) & 0xff; + if (coher) *coher = (ret_stuff.v0 >> 32) & 0xff; + if (reg) *reg = (ret_stuff.v0 >> 40) & 0xff; + if (nasid_bitmask) *nasid_bitmask = (ret_stuff.v1 & 0xffff); + if (nasid_shift) *nasid_shift = (ret_stuff.v1 >> 16) & 0xff; return 0; } -- cgit 1.2.3-korg From 217907ba12bb5dfb7a05d8f0559556abdf1667ee Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 7 Mar 2005 23:02:27 -0800 Subject: [IA64-SGI] [PATCH 2/2] - New chipset support for SN platform - move a number of fields out of the SN pda & into per-cpu data. The pda is ugly & will be deleted. This is a first step. Additional patches will follow. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 12 +++++++----- include/asm-ia64/sn/addrs.h | 7 ++++--- include/asm-ia64/sn/arch.h | 24 ++++++++++++++++++++++++ include/asm-ia64/sn/pda.h | 13 ------------- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index a78197af95a50..f0306b516afba 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -67,9 +67,11 @@ extern void snidle(int); extern unsigned char acpi_kbd_controller_present; unsigned long sn_rtc_cycles_per_second; - EXPORT_SYMBOL(sn_rtc_cycles_per_second); +DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); +EXPORT_PER_CPU_SYMBOL(__sn_hub_info); + partid_t sn_partid = -1; EXPORT_SYMBOL(sn_partid); char sn_system_serial_number_string[128]; @@ -242,7 +244,7 @@ static void __init sn_check_for_wars(void) } else { for_each_online_node(cnode) { if (is_shub_1_1(cnodeid_to_nasid(cnode))) - shub_1_1_found = 1; + sn_hub_info->shub_1_1_found = 1; } } } @@ -437,11 +439,11 @@ void __init sn_cpu_init(void) static int wars_have_been_checked; memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_sn_info(0, &pda->shub2, &pda->nasid_bitmask, &pda->nasid_shift, + if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, &sn_coherency_id, &sn_region_size)) BUG(); - pda->as_shift = pda->nasid_shift - 2; + sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; /* * The boot cpu makes this call again after platform initialization is @@ -490,7 +492,7 @@ void __init sn_cpu_init(void) sn_check_for_wars(); wars_have_been_checked = 1; } - pda->shub_1_1_found = shub_1_1_found; + sn_hub_info->shub_1_1_found = shub_1_1_found; /* * Set up addresses of PIO/MEM write status registers. diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index 3ce60976d474b..c916bd22767a1 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -11,6 +11,7 @@ #include #include +#include #include /* @@ -57,9 +58,9 @@ /* * Define basic shift & mask constants for manipulating NASIDs and AS values. */ -#define NASID_BITMASK (pda->nasid_bitmask) -#define NASID_SHIFT (pda->nasid_shift) -#define AS_SHIFT (pda->as_shift) +#define NASID_BITMASK (sn_hub_info->nasid_bitmask) +#define NASID_SHIFT (sn_hub_info->nasid_shift) +#define AS_SHIFT (sn_hub_info->as_shift) #define AS_BITMASK 0x3UL #define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT) diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h index bfc922a0ab717..7c349f07916a1 100644 --- a/include/asm-ia64/sn/arch.h +++ b/include/asm-ia64/sn/arch.h @@ -12,9 +12,33 @@ #define _ASM_IA64_SN_ARCH_H #include +#include #include #include +/* + * The following defines attributes of the HUB chip. These attributes are + * frequently referenced. They are kept in the per-cpu data areas of each cpu. + * They are kept together in a struct to minimize cache misses. + */ +struct sn_hub_info_s { + u8 shub2; + u8 nasid_shift; + u8 as_shift; + u8 shub_1_1_found; + u16 nasid_bitmask; +}; +DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); +#define sn_hub_info (&__get_cpu_var(__sn_hub_info)) +#define is_shub2() (sn_hub_info->shub2) +#define is_shub1() (sn_hub_info->shub2 == 0) + +/* + * Use this macro to test if shub 1.1 wars should be enabled + */ +#define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found) + + /* * This is the maximum number of nodes that can be part of a kernel. * Effectively, it's the maximum number of compact node ids (cnodeid_t). diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index 6465e8ab2bccd..d18f96f0dc62b 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -37,11 +37,6 @@ typedef struct pda_s { * Support for SN LEDs */ volatile short *led_address; - u16 nasid_bitmask; - u8 shub2; - u8 nasid_shift; - u8 as_shift; - u8 shub_1_1_found; u8 led_state; u8 hb_state; /* supports blinking heartbeat leds */ unsigned int hb_count; @@ -84,12 +79,4 @@ DECLARE_PER_CPU(struct pda_s, pda_percpu); #define pdacpu(cpu) (&per_cpu(pda_percpu, cpu)) -/* - * Use this macro to test if shub 1.1 wars should be enabled - */ -#define enable_shub_wars_1_1() (pda->shub_1_1_found) - -#define is_shub2() (pda->shub2) -#define is_shub1() (pda->shub2 == 0) - #endif /* _ASM_IA64_SN_PDA_H */ -- cgit 1.2.3-korg From 8b46eae95b9d8a182ac434d38eb0c638567f939b Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Mon, 7 Mar 2005 23:04:50 -0800 Subject: [IA64-SGI] Remove unused cpu_bte_if from pda_s Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- include/asm-ia64/sn/pda.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index d18f96f0dc62b..e940d3647c804 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -48,8 +48,6 @@ typedef struct pda_s { unsigned long pio_write_status_val; volatile unsigned long *pio_shub_war_cam_addr; - struct bteinfo_s *cpu_bte_if[BTES_PER_NODE]; /* cpu interface order */ - unsigned long sn_soft_irr[4]; unsigned long sn_in_service_ivecs[4]; short cnodeid_to_nasid_table[MAX_NUMNODES]; -- cgit 1.2.3-korg From 8d7c763253b85b5598e5975a5c88b896fefe2110 Mon Sep 17 00:00:00 2001 From: Bob Montgomery Date: Tue, 8 Mar 2005 00:44:21 -0800 Subject: [IA64] fix bad emulation of unaligned semaphore opcodes The method used to categorize the load/store instructions in arch/ia64/kernel/unaligned.c is masking the entire set of instructions described in Table 4-33 of the 2002 Intel Itanium Volume 3: Instruction Set Reference. It's the set of instructions for opcode 4, mbit 0, x bit 1, described as Semaphore/Get FR/16-Byte Opcode Instructions. Because the IA64_OPCODE_SHIFT and IA64_OPCODE_MASK operations ignore the x bit, this set of instructions (including cmpxchg, xchg, and fetchadd among others) are processed like the corresponding opcode 4, mbit 0, x bit 0 instructions. This means that a cmpxchg.acq with a misaligned pointer will return the old value without setting the new one (rendering spin locks as No-ops) and that the other instructions also appear not to update memory. A cmpxchg.rel will be treated like a ld.s and just retry forever. The correct behavior for this class of instructions is documented in the file as producing failures for user code and kernel oops in kernel mode, but the code as implemented does not behave this way. I have user test code to demonstrate the problem if you would like a copy. The simple fix in this patch has been discussed with Stephane Eranian and David Mosberger. It has the advantage of not requiring the redesign of the opcode discrimination in unaligned.c. Signed-off-by: Bob Montgomery Signed-off-by: Tony Luck --- arch/ia64/kernel/unaligned.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 46dad0d215a3d..43b45b65ee5a9 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1380,6 +1380,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * - ldX.spill * - stX.spill * Reason: RNATs are based on addresses + * - ld16 + * - st16 + * Reason: ld16 and st16 are supposed to occur in a single + * memory op * * synchronization: * - cmpxchg @@ -1401,6 +1405,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) switch (opcode) { case LDS_OP: case LDSA_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case LDS_IMM_OP: case LDSA_IMM_OP: case LDFS_OP: @@ -1425,6 +1433,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) case LDCCLR_OP: case LDCNC_OP: case LDCCLRACQ_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case LD_IMM_OP: case LDA_IMM_OP: case LDBIAS_IMM_OP: @@ -1437,6 +1449,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) case ST_OP: case STREL_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case ST_IMM_OP: case STREL_IMM_OP: ret = emulate_store_int(ifa, u.insn, regs); -- cgit 1.2.3-korg