summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-08-17 14:37:55 +0100
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-08-17 14:37:55 +0100
commit327b6b08d6ab3bf5488120ba02ed2fe06b09efe6 (patch)
tree592b0ebc2f5f18dac0bdc0fd6ba87d2c8b07b232 /arch
parentc973b112c76c9d8fd042991128f218a738cc8d0a (diff)
parent2ad56496627630ebc99f06af5f81ca23e17e014e (diff)
downloadblackbird-op-linux-327b6b08d6ab3bf5488120ba02ed2fe06b09efe6.tar.gz
blackbird-op-linux-327b6b08d6ab3bf5488120ba02ed2fe06b09efe6.zip
Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/entry-armv.S7
-rw-r--r--arch/arm/lib/bitops.h4
-rw-r--r--arch/arm/mach-s3c2410/usb-simtec.c18
-rw-r--r--arch/arm/mm/mm-armv.c17
-rw-r--r--arch/arm/mm/proc-v6.S22
-rw-r--r--arch/ia64/kernel/domain.c2
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ppc64/kernel/LparData.c79
-rw-r--r--arch/ppc64/kernel/Makefile5
-rw-r--r--arch/ppc64/kernel/head.S6
-rw-r--r--arch/ppc64/kernel/lparmap.c31
-rw-r--r--arch/ppc64/kernel/prom_init.c2
-rw-r--r--arch/sparc64/solaris/socket.c193
-rw-r--r--arch/x86_64/kernel/smpboot.c2
14 files changed, 211 insertions, 179 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 39a6c1b0b9a3..7152bfbee581 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -533,6 +533,13 @@ ENTRY(__switch_to)
ldr r3, [r2, #TI_TP_VALUE]
stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
ldr r6, [r2, #TI_CPU_DOMAIN]!
+#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_MPCORE
+ clrex
+#else
+ strex r3, r4, [ip] @ Clear exclusive monitor
+#endif
+#endif
#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
mra r4, r5, acc0
stmia ip, {r4, r5}
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index 2036ff15bda9..64a988c1ad44 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,4 +1,6 @@
-#if __LINUX_ARM_ARCH__ >= 6
+#include <linux/config.h>
+
+#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE)
.macro bitop, instr
mov r2, #1
and r3, r0, #7 @ Get bit offset
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 7f2b61362976..f021fd82be52 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/usb-simtec.c
*
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://www.simtec.co.uk/products/EB2410ITX/
@@ -14,6 +14,8 @@
* Modifications:
* 14-Sep-2004 BJD Created
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
+ * 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc
+ * 09-Aug-2005 BJD Ports powered only if both are enabled
*/
#define DEBUG
@@ -47,13 +49,19 @@
* designed boards.
*/
+static unsigned int power_state[2];
+
static void
usb_simtec_powercontrol(int port, int to)
{
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
- if (port == 1)
- s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
+ power_state[port] = to;
+
+ if (power_state[0] && power_state[1])
+ s3c2410_gpio_setpin(S3C2410_GPB4, 0);
+ else
+ s3c2410_gpio_setpin(S3C2410_GPB4, 1);
}
static irqreturn_t
@@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
pr_debug("usb_simtec: over-current irq (oc detected)\n");
- s3c2410_report_oc(info, 3);
+ s3c2410_usb_report_oc(info, 3);
} else {
pr_debug("usb_simtec: over-current irq (oc cleared)\n");
- s3c2410_report_oc(info, 0);
+ s3c2410_usb_report_oc(info, 0);
}
return IRQ_HANDLED;
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index e33fe4229d05..3c655c54e231 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -383,6 +383,7 @@ static void __init build_mem_type_table(void)
{
struct cachepolicy *cp;
unsigned int cr = get_cr();
+ unsigned int user_pgprot;
int cpu_arch = cpu_architecture();
int i;
@@ -408,6 +409,9 @@ static void __init build_mem_type_table(void)
}
}
+ cp = &cache_policies[cachepolicy];
+ user_pgprot = cp->pte;
+
/*
* ARMv6 and above have extended page tables.
*/
@@ -426,11 +430,18 @@ static void __init build_mem_type_table(void)
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+ /*
+ * Mark the device area as "shared device"
+ */
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
- }
- cp = &cache_policies[cachepolicy];
+ /*
+ * User pages need to be mapped with the ASID
+ * (iow, non-global)
+ */
+ user_pgprot |= L_PTE_ASID;
+ }
if (cpu_arch >= CPU_ARCH_ARMv5) {
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
@@ -448,7 +459,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
- v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte;
+ v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 352db98ee269..3429ddcf65d1 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm)
mcr p15, 0, r1, c13, c0, 1 @ set context ID
mov pc, lr
-#define nG (1 << 11)
-#define APX (1 << 9)
-#define AP1 (1 << 5)
-#define AP0 (1 << 4)
-#define XN (1 << 0)
-
/*
* cpu_v6_set_pte(ptep, pte)
*
@@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm)
ENTRY(cpu_v6_set_pte)
str r1, [r0], #-2048 @ linux version
- bic r2, r1, #0x00000ff0
+ bic r2, r1, #0x000007f0
bic r2, r2, #0x00000003
- orr r2, r2, #AP0 | 2
+ orr r2, r2, #PTE_EXT_AP0 | 2
tst r1, #L_PTE_WRITE
tstne r1, #L_PTE_DIRTY
- orreq r2, r2, #APX
+ orreq r2, r2, #PTE_EXT_APX
tst r1, #L_PTE_USER
- orrne r2, r2, #AP1 | nG
- tstne r2, #APX
- bicne r2, r2, #APX | AP0
+ orrne r2, r2, #PTE_EXT_AP1
+ tstne r2, #PTE_EXT_APX
+ bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
tst r1, #L_PTE_YOUNG
- biceq r2, r2, #APX | AP1 | AP0
+ biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
@ tst r1, #L_PTE_EXEC
-@ orreq r2, r2, #XN
+@ orreq r2, r2, #PTE_EXT_XN
tst r1, #L_PTE_PRESENT
moveq r2, #0
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
index d65e87b6394f..bbb8efe126b7 100644
--- a/arch/ia64/kernel/domain.c
+++ b/arch/ia64/kernel/domain.c
@@ -341,7 +341,7 @@ next_sg:
#endif
/* Attach the domains */
- for_each_online_cpu(i) {
+ for_each_cpu_mask(i, *cpu_map) {
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
sd = &per_cpu(cpu_domains, i);
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 66e840609808..051e050359e4 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -179,7 +179,7 @@ static int can_do_pal_halt = 1;
static int __init nohalt_setup(char * str)
{
- pal_halt = 0;
+ pal_halt = can_do_pal_halt = 0;
return 1;
}
__setup("nohalt", nohalt_setup);
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 76cfd1449d52..1c11031c838e 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -32,32 +32,12 @@
/* The HvReleaseData is the root of the information shared between
* the hypervisor and Linux.
*/
-
-/*
- * WARNING - magic here
- *
- * Ok, this is a horrid hack below, but marginally better than the
- * alternatives. What we really want is just to initialize
- * hvReleaseData in C as in the #if 0 section here. However, gcc
- * refuses to believe that (u32)&x is a constant expression, so will
- * not allow the xMsNucDataOffset field to be properly initialized.
- * So, we declare hvReleaseData in inline asm instead. We use inline
- * asm, rather than a .S file, because the assembler won't generate
- * the necessary relocation for the LparMap either, unless that symbol
- * is declared in the same source file. Finally, we put the asm in a
- * dummy, attribute-used function, instead of at file scope, because
- * file scope asms don't allow contraints. We want to use the "i"
- * constraints to put sizeof() and offsetof() expressions in there,
- * because including asm/offsets.h in C code then stringifying causes
- * all manner of warnings.
- */
-#if 0
struct HvReleaseData hvReleaseData = {
.xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
.xSize = sizeof(struct HvReleaseData),
.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
.xSlicNacaAddr = &naca, /* 64-bit Naca address */
- .xMsNucDataOffset = (u32)((unsigned long)&xLparMap - KERNELBASE),
+ .xMsNucDataOffset = LPARMAP_PHYS,
.xFlags = HVREL_TAGSINACTIVE /* tags inactive */
/* 64 bit */
/* shared processors */
@@ -70,63 +50,6 @@ struct HvReleaseData hvReleaseData = {
0xa7, 0x40, 0xf2, 0x4b,
0xf4, 0x4b, 0xf6, 0xf4 },
};
-#endif
-
-
-extern struct HvReleaseData hvReleaseData;
-
-static void __attribute_used__ hvReleaseData_wrapper(void)
-{
- /* This doesn't appear to need any alignment (even 4 byte) */
- asm volatile (
- " lparMapPhys = xLparMap - %3\n"
- " .data\n"
- " .globl hvReleaseData\n"
- "hvReleaseData:\n"
- " .long 0xc8a5d9c4\n" /* xDesc */
- /* "HvRD" in ebcdic */
- " .short %0\n" /* xSize */
- " .short %1\n" /* xVpdAreasPtrOffset */
- " .llong naca\n" /* xSlicNacaAddr */
- " .long lparMapPhys\n" /* xMsNucDataOffset */
- " .long 0\n" /* xRsvd1 */
- " .short %2\n" /* xFlags */
- " .short 4\n" /* xVrmIndex - v5r2m0 */
- " .short 3\n" /* xMinSupportedPlicVrmIndex - v5r1m0 */
- " .short 3\n" /* xMinCompatablePlicVrmIndex - v5r1m0 */
- " .long 0xd38995a4\n" /* xVrmName */
- " .long 0xa740f24b\n" /* "Linux 2.4.64" ebcdic */
- " .long 0xf44bf6f4\n"
- " . = hvReleaseData + %0\n"
- " .previous\n"
- : : "i"(sizeof(hvReleaseData)),
- "i"(offsetof(struct naca_struct, xItVpdAreas)),
- "i"(HVREL_TAGSINACTIVE /* tags inactive, 64 bit, */
- /* shared processors, HMT allowed */
- | 6), /* TEMP: This allows non-GA drivers */
- "i"(KERNELBASE)
- );
-}
-
-struct LparMap __attribute__((aligned (16))) xLparMap = {
- .xNumberEsids = HvEsidsToMap,
- .xNumberRanges = HvRangesToMap,
- .xSegmentTableOffs = STAB0_PAGE,
-
- .xEsids = {
- { .xKernelEsid = GET_ESID(KERNELBASE),
- .xKernelVsid = KERNEL_VSID(KERNELBASE), },
- { .xKernelEsid = GET_ESID(VMALLOCBASE),
- .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
- },
-
- .xRanges = {
- { .xPages = HvPagesToMap,
- .xOffset = 0,
- .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
- },
- },
-};
extern void system_reset_iSeries(void);
extern void machine_check_iSeries(void);
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index d9b2660ef221..2ecccb6b4f8c 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -73,3 +73,8 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_KPROBES) += kprobes.o
CFLAGS_ioctl32.o += -Ifs/
+
+ifeq ($(CONFIG_PPC_ISERIES),y)
+arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s
+AFLAGS_head.o += -Iarch/ppc64/kernel
+endif
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 784f56d4684c..accaa052d31f 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -38,6 +38,7 @@
#include <asm/cputable.h>
#include <asm/setup.h>
#include <asm/hvcall.h>
+#include <asm/iSeries/LparMap.h>
#ifdef CONFIG_PPC_ISERIES
#define DO_SOFT_DISABLE
@@ -679,6 +680,11 @@ hardware_interrupt_iSeries_masked:
.globl fwnmi_data_area
fwnmi_data_area:
+#ifdef CONFIG_PPC_ISERIES
+ . = LPARMAP_PHYS
+#include "lparmap.s"
+#endif /* CONFIG_PPC_ISERIES */
+
/*
* Vectors for the FWNMI option. Share common code.
*/
diff --git a/arch/ppc64/kernel/lparmap.c b/arch/ppc64/kernel/lparmap.c
new file mode 100644
index 000000000000..b81de286df5e
--- /dev/null
+++ b/arch/ppc64/kernel/lparmap.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005 Stephen Rothwell IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/iSeries/LparMap.h>
+
+const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
+ .xNumberEsids = HvEsidsToMap,
+ .xNumberRanges = HvRangesToMap,
+ .xSegmentTableOffs = STAB0_PAGE,
+
+ .xEsids = {
+ { .xKernelEsid = GET_ESID(KERNELBASE),
+ .xKernelVsid = KERNEL_VSID(KERNELBASE), },
+ { .xKernelEsid = GET_ESID(VMALLOCBASE),
+ .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
+ },
+
+ .xRanges = {
+ { .xPages = HvPagesToMap,
+ .xOffset = 0,
+ .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
+ },
+ },
+};
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index e248a7950aeb..dbbe6c79d8da 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1803,7 +1803,7 @@ static void __init fixup_device_tree(void)
if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
== PROM_ERROR)
return;
- if (u3_rev != 0x35)
+ if (u3_rev != 0x35 && u3_rev != 0x37)
return;
/* does it need fixup ? */
if (prom_getproplen(i2c, "interrupts") > 0)
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index 06740582717e..d3a66ea74a7f 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -16,6 +16,7 @@
#include <linux/net.h>
#include <linux/compat.h>
#include <net/compat.h>
+#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/string.h>
@@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
- struct iovec iov[UIO_FASTIOV];
+ struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20];
unsigned char *ctl_buf = ctl;
- struct msghdr kern_msg;
- int err, total_len;
+ struct msghdr msg_sys;
+ int err, ctl_len, iov_size, total_len;
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
- return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
- err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
- if (err < 0)
+ err = -EFAULT;
+ if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+ goto out;
+
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
goto out;
+
+ /* do not move before msg_sys is valid */
+ err = -EMSGSIZE;
+ if (msg_sys.msg_iovlen > UIO_MAXIOV)
+ goto out_put;
+
+ /* Check whether to allocate the iovec area*/
+ err = -ENOMEM;
+ iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+ if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+ iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+ if (!iov)
+ goto out_put;
+ }
+
+ err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+ if (err < 0)
+ goto out_freeiov;
total_len = err;
- if(kern_msg.msg_controllen) {
- struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control;
+ err = -ENOBUFS;
+ if (msg_sys.msg_controllen > INT_MAX)
+ goto out_freeiov;
+
+ ctl_len = msg_sys.msg_controllen;
+ if (ctl_len) {
+ struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
unsigned long *kcmsg;
compat_size_t cmlen;
- if (kern_msg.msg_controllen <= sizeof(compat_size_t))
- return -EINVAL;
+ err = -EINVAL;
+ if (ctl_len <= sizeof(compat_size_t))
+ goto out_freeiov;
- if(kern_msg.msg_controllen > sizeof(ctl)) {
+ if (ctl_len > sizeof(ctl)) {
err = -ENOBUFS;
- ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
- if(!ctl_buf)
+ ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
+ if (!ctl_buf)
goto out_freeiov;
}
__get_user(cmlen, &ucmsg->cmsg_len);
kcmsg = (unsigned long *) ctl_buf;
*kcmsg++ = (unsigned long)cmlen;
err = -EFAULT;
- if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
- kern_msg.msg_controllen - sizeof(compat_size_t)))
+ if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
+ ctl_len - sizeof(compat_size_t)))
goto out_freectl;
- kern_msg.msg_control = ctl_buf;
+ msg_sys.msg_control = ctl_buf;
}
- kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags);
+ msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
- lock_kernel();
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- if (sock->file->f_flags & O_NONBLOCK)
- kern_msg.msg_flags |= MSG_DONTWAIT;
- err = sock_sendmsg(sock, &kern_msg, total_len);
- sockfd_put(sock);
- }
- unlock_kernel();
+ if (sock->file->f_flags & O_NONBLOCK)
+ msg_sys.msg_flags |= MSG_DONTWAIT;
+ err = sock_sendmsg(sock, &msg_sys, total_len);
out_freectl:
- /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
- if(ctl_buf != ctl)
- kfree(ctl_buf);
+ if (ctl_buf != ctl)
+ sock_kfree_s(sock->sk, ctl_buf, ctl_len);
out_freeiov:
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
-out:
+ if (iov != iovstack)
+ sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+ sockfd_put(sock);
+out:
return err;
}
asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct msghdr kern_msg;
- char addr[MAX_SOCK_ADDR];
struct socket *sock;
+ struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack;
+ struct msghdr msg_sys;
+ unsigned long cmsg_ptr;
+ int err, iov_size, total_len, len;
+
+ /* kernel mode address */
+ char addr[MAX_SOCK_ADDR];
+
+ /* user mode address pointers */
struct sockaddr __user *uaddr;
int __user *uaddr_len;
- unsigned long cmsg_ptr;
- int err, total_len, len = 0;
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
- uaddr = kern_msg.msg_name;
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
+ goto out;
+
+ err = -EMSGSIZE;
+ if (msg_sys.msg_iovlen > UIO_MAXIOV)
+ goto out_put;
+
+ /* Check whether to allocate the iovec area*/
+ err = -ENOMEM;
+ iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+ if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+ iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+ if (!iov)
+ goto out_put;
+ }
+
+ /*
+ * Save the user-mode address (verify_iovec will change the
+ * kernel msghdr to use the kernel address space)
+ */
+
+ uaddr = (void __user *) msg_sys.msg_name;
uaddr_len = &user_msg->msg_namelen;
- err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
+ err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
if (err < 0)
- goto out;
+ goto out_freeiov;
total_len = err;
- cmsg_ptr = (unsigned long) kern_msg.msg_control;
- kern_msg.msg_flags = 0;
+ cmsg_ptr = (unsigned long) msg_sys.msg_control;
+ msg_sys.msg_flags = MSG_CMSG_COMPAT;
- lock_kernel();
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- if (sock->file->f_flags & O_NONBLOCK)
- user_flags |= MSG_DONTWAIT;
- err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
- if(err >= 0)
- len = err;
- sockfd_put(sock);
- }
- unlock_kernel();
-
- if(uaddr != NULL && err >= 0)
- err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
- if(err >= 0) {
- err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags);
- if(!err) {
- /* XXX Convert cmsg back into userspace 32-bit format... */
- err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
- &user_msg->msg_controllen);
- }
+ if (sock->file->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
+
+ err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
+ if(err < 0)
+ goto out_freeiov;
+
+ len = err;
+
+ if (uaddr != NULL) {
+ err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+ if (err < 0)
+ goto out_freeiov;
}
+ err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags);
+ if (err)
+ goto out_freeiov;
+ err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
+ &user_msg->msg_controllen);
+ if (err)
+ goto out_freeiov;
+ err = len;
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
+out_freeiov:
+ if (iov != iovstack)
+ sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+ sockfd_put(sock);
out:
- if(err < 0)
- return err;
- return len;
+ return err;
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 6e4807d64d46..b15761ff4101 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -334,7 +334,7 @@ static void __cpuinit tsc_sync_wait(void)
{
if (notscsync || !cpu_has_tsc)
return;
- sync_tsc(boot_cpu_id);
+ sync_tsc(0);
}
static __init int notscsync_setup(char *s)
OpenPOWER on IntegriCloud