diff options
Diffstat (limited to 'arch/x86/kernel')
28 files changed, 2900 insertions, 1162 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index c9be69fedb70..5098585f87ce 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -10,7 +10,7 @@ ifdef CONFIG_FTRACE | |||
| 10 | # Do not profile debug and lowlevel utilities | 10 | # Do not profile debug and lowlevel utilities |
| 11 | CFLAGS_REMOVE_tsc.o = -pg | 11 | CFLAGS_REMOVE_tsc.o = -pg |
| 12 | CFLAGS_REMOVE_rtc.o = -pg | 12 | CFLAGS_REMOVE_rtc.o = -pg |
| 13 | CFLAGS_REMOVE_paravirt.o = -pg | 13 | CFLAGS_REMOVE_paravirt-spinlocks.o = -pg |
| 14 | endif | 14 | endif |
| 15 | 15 | ||
| 16 | # | 16 | # |
| @@ -51,7 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o | |||
| 51 | obj-$(CONFIG_MCA) += mca_32.o | 51 | obj-$(CONFIG_MCA) += mca_32.o |
| 52 | obj-$(CONFIG_X86_MSR) += msr.o | 52 | obj-$(CONFIG_X86_MSR) += msr.o |
| 53 | obj-$(CONFIG_X86_CPUID) += cpuid.o | 53 | obj-$(CONFIG_X86_CPUID) += cpuid.o |
| 54 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
| 55 | obj-$(CONFIG_PCI) += early-quirks.o | 54 | obj-$(CONFIG_PCI) += early-quirks.o |
| 56 | apm-y := apm_32.o | 55 | apm-y := apm_32.o |
| 57 | obj-$(CONFIG_APM) += apm.o | 56 | obj-$(CONFIG_APM) += apm.o |
| @@ -90,7 +89,7 @@ obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o | |||
| 90 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o | 89 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o |
| 91 | obj-$(CONFIG_KVM_GUEST) += kvm.o | 90 | obj-$(CONFIG_KVM_GUEST) += kvm.o |
| 92 | obj-$(CONFIG_KVM_CLOCK) += kvmclock.o | 91 | obj-$(CONFIG_KVM_CLOCK) += kvmclock.o |
| 93 | obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o | 92 | obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o paravirt-spinlocks.o |
| 94 | obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o | 93 | obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o |
| 95 | 94 | ||
| 96 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o | 95 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o |
| @@ -100,6 +99,11 @@ scx200-y += scx200_32.o | |||
| 100 | 99 | ||
| 101 | obj-$(CONFIG_OLPC) += olpc.o | 100 | obj-$(CONFIG_OLPC) += olpc.o |
| 102 | 101 | ||
| 102 | microcode-y := microcode_core.o | ||
| 103 | microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o | ||
| 104 | microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o | ||
| 105 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
| 106 | |||
| 103 | ### | 107 | ### |
| 104 | # 64 bit specific files | 108 | # 64 bit specific files |
| 105 | ifeq ($(CONFIG_X86_64),y) | 109 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c2ac1b4515a0..eb875cdc7367 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -1418,8 +1418,16 @@ static int __init force_acpi_ht(const struct dmi_system_id *d) | |||
| 1418 | */ | 1418 | */ |
| 1419 | static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) | 1419 | static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) |
| 1420 | { | 1420 | { |
| 1421 | pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", d->ident); | 1421 | /* |
| 1422 | acpi_skip_timer_override = 1; | 1422 | * The ati_ixp4x0_rev() early PCI quirk should have set |
| 1423 | * the acpi_skip_timer_override flag already: | ||
| 1424 | */ | ||
| 1425 | if (!acpi_skip_timer_override) { | ||
| 1426 | WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); | ||
| 1427 | pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", | ||
| 1428 | d->ident); | ||
| 1429 | acpi_skip_timer_override = 1; | ||
| 1430 | } | ||
| 1423 | return 0; | 1431 | return 0; |
| 1424 | } | 1432 | } |
| 1425 | 1433 | ||
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 148fcfe22f17..4cd8083c58be 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
| @@ -723,9 +723,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
| 723 | init_iommu_from_acpi(iommu, h); | 723 | init_iommu_from_acpi(iommu, h); |
| 724 | init_iommu_devices(iommu); | 724 | init_iommu_devices(iommu); |
| 725 | 725 | ||
| 726 | pci_enable_device(iommu->dev); | 726 | return pci_enable_device(iommu->dev); |
| 727 | |||
| 728 | return 0; | ||
| 729 | } | 727 | } |
| 730 | 728 | ||
| 731 | /* | 729 | /* |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7581b62df184..fb789dd9e691 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -1121,16 +1121,5 @@ void __cpuinit cpu_init(void) | |||
| 1121 | xsave_init(); | 1121 | xsave_init(); |
| 1122 | } | 1122 | } |
| 1123 | 1123 | ||
| 1124 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 1125 | void __cpuinit cpu_uninit(void) | ||
| 1126 | { | ||
| 1127 | int cpu = raw_smp_processor_id(); | ||
| 1128 | cpu_clear(cpu, cpu_initialized); | ||
| 1129 | |||
| 1130 | /* lazy TLB state */ | ||
| 1131 | per_cpu(cpu_tlbstate, cpu).state = 0; | ||
| 1132 | per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; | ||
| 1133 | } | ||
| 1134 | #endif | ||
| 1135 | 1124 | ||
| 1136 | #endif | 1125 | #endif |
diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index a47798b59f07..395acb12b0d1 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c | |||
| @@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = { | |||
| 66 | .ds = __USER_DS, | 66 | .ds = __USER_DS, |
| 67 | .fs = __KERNEL_PERCPU, | 67 | .fs = __KERNEL_PERCPU, |
| 68 | 68 | ||
| 69 | .__cr3 = __pa(swapper_pg_dir) | 69 | .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir) |
| 70 | } | 70 | } |
| 71 | }; | 71 | }; |
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 24bb5faf5efa..733c4f8d42ea 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c | |||
| @@ -95,6 +95,52 @@ static void __init nvidia_bugs(int num, int slot, int func) | |||
| 95 | 95 | ||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static u32 ati_ixp4x0_rev(int num, int slot, int func) | ||
| 99 | { | ||
| 100 | u32 d; | ||
| 101 | u8 b; | ||
| 102 | |||
| 103 | b = read_pci_config_byte(num, slot, func, 0xac); | ||
| 104 | b &= ~(1<<5); | ||
| 105 | write_pci_config_byte(num, slot, func, 0xac, b); | ||
| 106 | |||
| 107 | d = read_pci_config(num, slot, func, 0x70); | ||
| 108 | d |= 1<<8; | ||
| 109 | write_pci_config(num, slot, func, 0x70, d); | ||
| 110 | |||
| 111 | d = read_pci_config(num, slot, func, 0x8); | ||
| 112 | d &= 0xff; | ||
| 113 | return d; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void __init ati_bugs(int num, int slot, int func) | ||
| 117 | { | ||
| 118 | #if defined(CONFIG_ACPI) && defined (CONFIG_X86_IO_APIC) | ||
| 119 | u32 d; | ||
| 120 | u8 b; | ||
| 121 | |||
| 122 | if (acpi_use_timer_override) | ||
| 123 | return; | ||
| 124 | |||
| 125 | d = ati_ixp4x0_rev(num, slot, func); | ||
| 126 | if (d < 0x82) | ||
| 127 | acpi_skip_timer_override = 1; | ||
| 128 | else { | ||
| 129 | /* check for IRQ0 interrupt swap */ | ||
| 130 | outb(0x72, 0xcd6); b = inb(0xcd7); | ||
| 131 | if (!(b & 0x2)) | ||
| 132 | acpi_skip_timer_override = 1; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (acpi_skip_timer_override) { | ||
| 136 | printk(KERN_INFO "SB4X0 revision 0x%x\n", d); | ||
| 137 | printk(KERN_INFO "Ignoring ACPI timer override.\n"); | ||
| 138 | printk(KERN_INFO "If you got timer trouble " | ||
| 139 | "try acpi_use_timer_override\n"); | ||
| 140 | } | ||
| 141 | #endif | ||
| 142 | } | ||
| 143 | |||
| 98 | #ifdef CONFIG_DMAR | 144 | #ifdef CONFIG_DMAR |
| 99 | static void __init intel_g33_dmar(int num, int slot, int func) | 145 | static void __init intel_g33_dmar(int num, int slot, int func) |
| 100 | { | 146 | { |
| @@ -128,6 +174,8 @@ static struct chipset early_qrk[] __initdata = { | |||
| 128 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, | 174 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, |
| 129 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, | 175 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, |
| 130 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, | 176 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, |
| 177 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, | ||
| 178 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, | ||
| 131 | #ifdef CONFIG_DMAR | 179 | #ifdef CONFIG_DMAR |
| 132 | { PCI_VENDOR_ID_INTEL, 0x29c0, | 180 | { PCI_VENDOR_ID_INTEL, 0x29c0, |
| 133 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar }, | 181 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar }, |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index ff9e7350da54..34ad997d3834 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
| @@ -3,11 +3,19 @@ | |||
| 3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
| 4 | #include <linux/string.h> | 4 | #include <linux/string.h> |
| 5 | #include <linux/screen_info.h> | 5 | #include <linux/screen_info.h> |
| 6 | #include <linux/usb/ch9.h> | ||
| 7 | #include <linux/pci_regs.h> | ||
| 8 | #include <linux/pci_ids.h> | ||
| 9 | #include <linux/errno.h> | ||
| 6 | #include <asm/io.h> | 10 | #include <asm/io.h> |
| 7 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
| 8 | #include <asm/fcntl.h> | 12 | #include <asm/fcntl.h> |
| 9 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
| 10 | #include <xen/hvc-console.h> | 14 | #include <xen/hvc-console.h> |
| 15 | #include <asm/pci-direct.h> | ||
| 16 | #include <asm/pgtable.h> | ||
| 17 | #include <asm/fixmap.h> | ||
| 18 | #include <linux/usb/ehci_def.h> | ||
| 11 | 19 | ||
| 12 | /* Simple VGA output */ | 20 | /* Simple VGA output */ |
| 13 | #define VGABASE (__ISA_IO_base + 0xb8000) | 21 | #define VGABASE (__ISA_IO_base + 0xb8000) |
| @@ -78,6 +86,7 @@ static int early_serial_base = 0x3f8; /* ttyS0 */ | |||
| 78 | static int early_serial_putc(unsigned char ch) | 86 | static int early_serial_putc(unsigned char ch) |
| 79 | { | 87 | { |
| 80 | unsigned timeout = 0xffff; | 88 | unsigned timeout = 0xffff; |
| 89 | |||
| 81 | while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) | 90 | while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) |
| 82 | cpu_relax(); | 91 | cpu_relax(); |
| 83 | outb(ch, early_serial_base + TXR); | 92 | outb(ch, early_serial_base + TXR); |
| @@ -111,7 +120,7 @@ static __init void early_serial_init(char *s) | |||
| 111 | if (!strncmp(s, "0x", 2)) { | 120 | if (!strncmp(s, "0x", 2)) { |
| 112 | early_serial_base = simple_strtoul(s, &e, 16); | 121 | early_serial_base = simple_strtoul(s, &e, 16); |
| 113 | } else { | 122 | } else { |
| 114 | static int bases[] = { 0x3f8, 0x2f8 }; | 123 | static const int __initconst bases[] = { 0x3f8, 0x2f8 }; |
| 115 | 124 | ||
| 116 | if (!strncmp(s, "ttyS", 4)) | 125 | if (!strncmp(s, "ttyS", 4)) |
| 117 | s += 4; | 126 | s += 4; |
| @@ -151,6 +160,721 @@ static struct console early_serial_console = { | |||
| 151 | .index = -1, | 160 | .index = -1, |
| 152 | }; | 161 | }; |
| 153 | 162 | ||
| 163 | #ifdef CONFIG_EARLY_PRINTK_DBGP | ||
| 164 | |||
| 165 | static struct ehci_caps __iomem *ehci_caps; | ||
| 166 | static struct ehci_regs __iomem *ehci_regs; | ||
| 167 | static struct ehci_dbg_port __iomem *ehci_debug; | ||
| 168 | static unsigned int dbgp_endpoint_out; | ||
| 169 | |||
| 170 | struct ehci_dev { | ||
| 171 | u32 bus; | ||
| 172 | u32 slot; | ||
| 173 | u32 func; | ||
| 174 | }; | ||
| 175 | |||
| 176 | static struct ehci_dev ehci_dev; | ||
| 177 | |||
| 178 | #define USB_DEBUG_DEVNUM 127 | ||
| 179 | |||
| 180 | #define DBGP_DATA_TOGGLE 0x8800 | ||
| 181 | |||
| 182 | static inline u32 dbgp_pid_update(u32 x, u32 tok) | ||
| 183 | { | ||
| 184 | return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); | ||
| 185 | } | ||
| 186 | |||
| 187 | static inline u32 dbgp_len_update(u32 x, u32 len) | ||
| 188 | { | ||
| 189 | return (x & ~0x0f) | (len & 0x0f); | ||
| 190 | } | ||
| 191 | |||
| 192 | /* | ||
| 193 | * USB Packet IDs (PIDs) | ||
| 194 | */ | ||
| 195 | |||
| 196 | /* token */ | ||
| 197 | #define USB_PID_OUT 0xe1 | ||
| 198 | #define USB_PID_IN 0x69 | ||
| 199 | #define USB_PID_SOF 0xa5 | ||
| 200 | #define USB_PID_SETUP 0x2d | ||
| 201 | /* handshake */ | ||
| 202 | #define USB_PID_ACK 0xd2 | ||
| 203 | #define USB_PID_NAK 0x5a | ||
| 204 | #define USB_PID_STALL 0x1e | ||
| 205 | #define USB_PID_NYET 0x96 | ||
| 206 | /* data */ | ||
| 207 | #define USB_PID_DATA0 0xc3 | ||
| 208 | #define USB_PID_DATA1 0x4b | ||
| 209 | #define USB_PID_DATA2 0x87 | ||
| 210 | #define USB_PID_MDATA 0x0f | ||
| 211 | /* Special */ | ||
| 212 | #define USB_PID_PREAMBLE 0x3c | ||
| 213 | #define USB_PID_ERR 0x3c | ||
| 214 | #define USB_PID_SPLIT 0x78 | ||
| 215 | #define USB_PID_PING 0xb4 | ||
| 216 | #define USB_PID_UNDEF_0 0xf0 | ||
| 217 | |||
| 218 | #define USB_PID_DATA_TOGGLE 0x88 | ||
| 219 | #define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE) | ||
| 220 | |||
| 221 | #define PCI_CAP_ID_EHCI_DEBUG 0xa | ||
| 222 | |||
| 223 | #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ | ||
| 224 | #define HUB_SHORT_RESET_TIME 10 | ||
| 225 | #define HUB_LONG_RESET_TIME 200 | ||
| 226 | #define HUB_RESET_TIMEOUT 500 | ||
| 227 | |||
| 228 | #define DBGP_MAX_PACKET 8 | ||
| 229 | |||
| 230 | static int dbgp_wait_until_complete(void) | ||
| 231 | { | ||
| 232 | u32 ctrl; | ||
| 233 | int loop = 0x100000; | ||
| 234 | |||
| 235 | do { | ||
| 236 | ctrl = readl(&ehci_debug->control); | ||
| 237 | /* Stop when the transaction is finished */ | ||
| 238 | if (ctrl & DBGP_DONE) | ||
| 239 | break; | ||
| 240 | } while (--loop > 0); | ||
| 241 | |||
| 242 | if (!loop) | ||
| 243 | return -1; | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Now that we have observed the completed transaction, | ||
| 247 | * clear the done bit. | ||
| 248 | */ | ||
| 249 | writel(ctrl | DBGP_DONE, &ehci_debug->control); | ||
| 250 | return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl); | ||
| 251 | } | ||
| 252 | |||
| 253 | static void dbgp_mdelay(int ms) | ||
| 254 | { | ||
| 255 | int i; | ||
| 256 | |||
| 257 | while (ms--) { | ||
| 258 | for (i = 0; i < 1000; i++) | ||
| 259 | outb(0x1, 0x80); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | static void dbgp_breath(void) | ||
| 264 | { | ||
| 265 | /* Sleep to give the debug port a chance to breathe */ | ||
| 266 | } | ||
| 267 | |||
| 268 | static int dbgp_wait_until_done(unsigned ctrl) | ||
| 269 | { | ||
| 270 | u32 pids, lpid; | ||
| 271 | int ret; | ||
| 272 | int loop = 3; | ||
| 273 | |||
| 274 | retry: | ||
| 275 | writel(ctrl | DBGP_GO, &ehci_debug->control); | ||
| 276 | ret = dbgp_wait_until_complete(); | ||
| 277 | pids = readl(&ehci_debug->pids); | ||
| 278 | lpid = DBGP_PID_GET(pids); | ||
| 279 | |||
| 280 | if (ret < 0) | ||
| 281 | return ret; | ||
| 282 | |||
| 283 | /* | ||
| 284 | * If the port is getting full or it has dropped data | ||
| 285 | * start pacing ourselves, not necessary but it's friendly. | ||
| 286 | */ | ||
| 287 | if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET)) | ||
| 288 | dbgp_breath(); | ||
| 289 | |||
| 290 | /* If I get a NACK reissue the transmission */ | ||
| 291 | if (lpid == USB_PID_NAK) { | ||
| 292 | if (--loop > 0) | ||
| 293 | goto retry; | ||
| 294 | } | ||
| 295 | |||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | |||
| 299 | static void dbgp_set_data(const void *buf, int size) | ||
| 300 | { | ||
| 301 | const unsigned char *bytes = buf; | ||
| 302 | u32 lo, hi; | ||
| 303 | int i; | ||
| 304 | |||
| 305 | lo = hi = 0; | ||
| 306 | for (i = 0; i < 4 && i < size; i++) | ||
| 307 | lo |= bytes[i] << (8*i); | ||
| 308 | for (; i < 8 && i < size; i++) | ||
| 309 | hi |= bytes[i] << (8*(i - 4)); | ||
| 310 | writel(lo, &ehci_debug->data03); | ||
| 311 | writel(hi, &ehci_debug->data47); | ||
| 312 | } | ||
| 313 | |||
| 314 | static void dbgp_get_data(void *buf, int size) | ||
| 315 | { | ||
| 316 | unsigned char *bytes = buf; | ||
| 317 | u32 lo, hi; | ||
| 318 | int i; | ||
| 319 | |||
| 320 | lo = readl(&ehci_debug->data03); | ||
| 321 | hi = readl(&ehci_debug->data47); | ||
| 322 | for (i = 0; i < 4 && i < size; i++) | ||
| 323 | bytes[i] = (lo >> (8*i)) & 0xff; | ||
| 324 | for (; i < 8 && i < size; i++) | ||
| 325 | bytes[i] = (hi >> (8*(i - 4))) & 0xff; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, | ||
| 329 | const char *bytes, int size) | ||
| 330 | { | ||
| 331 | u32 pids, addr, ctrl; | ||
| 332 | int ret; | ||
| 333 | |||
| 334 | if (size > DBGP_MAX_PACKET) | ||
| 335 | return -1; | ||
| 336 | |||
| 337 | addr = DBGP_EPADDR(devnum, endpoint); | ||
| 338 | |||
| 339 | pids = readl(&ehci_debug->pids); | ||
| 340 | pids = dbgp_pid_update(pids, USB_PID_OUT); | ||
| 341 | |||
| 342 | ctrl = readl(&ehci_debug->control); | ||
| 343 | ctrl = dbgp_len_update(ctrl, size); | ||
| 344 | ctrl |= DBGP_OUT; | ||
| 345 | ctrl |= DBGP_GO; | ||
| 346 | |||
| 347 | dbgp_set_data(bytes, size); | ||
| 348 | writel(addr, &ehci_debug->address); | ||
| 349 | writel(pids, &ehci_debug->pids); | ||
| 350 | |||
| 351 | ret = dbgp_wait_until_done(ctrl); | ||
| 352 | if (ret < 0) | ||
| 353 | return ret; | ||
| 354 | |||
| 355 | return ret; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, | ||
| 359 | int size) | ||
| 360 | { | ||
| 361 | u32 pids, addr, ctrl; | ||
| 362 | int ret; | ||
| 363 | |||
| 364 | if (size > DBGP_MAX_PACKET) | ||
| 365 | return -1; | ||
| 366 | |||
| 367 | addr = DBGP_EPADDR(devnum, endpoint); | ||
| 368 | |||
| 369 | pids = readl(&ehci_debug->pids); | ||
| 370 | pids = dbgp_pid_update(pids, USB_PID_IN); | ||
| 371 | |||
| 372 | ctrl = readl(&ehci_debug->control); | ||
| 373 | ctrl = dbgp_len_update(ctrl, size); | ||
| 374 | ctrl &= ~DBGP_OUT; | ||
| 375 | ctrl |= DBGP_GO; | ||
| 376 | |||
| 377 | writel(addr, &ehci_debug->address); | ||
| 378 | writel(pids, &ehci_debug->pids); | ||
| 379 | ret = dbgp_wait_until_done(ctrl); | ||
| 380 | if (ret < 0) | ||
| 381 | return ret; | ||
| 382 | |||
| 383 | if (size > ret) | ||
| 384 | size = ret; | ||
| 385 | dbgp_get_data(data, size); | ||
| 386 | return ret; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int dbgp_control_msg(unsigned devnum, int requesttype, int request, | ||
| 390 | int value, int index, void *data, int size) | ||
| 391 | { | ||
| 392 | u32 pids, addr, ctrl; | ||
| 393 | struct usb_ctrlrequest req; | ||
| 394 | int read; | ||
| 395 | int ret; | ||
| 396 | |||
| 397 | read = (requesttype & USB_DIR_IN) != 0; | ||
| 398 | if (size > (read ? DBGP_MAX_PACKET:0)) | ||
| 399 | return -1; | ||
| 400 | |||
| 401 | /* Compute the control message */ | ||
| 402 | req.bRequestType = requesttype; | ||
| 403 | req.bRequest = request; | ||
| 404 | req.wValue = cpu_to_le16(value); | ||
| 405 | req.wIndex = cpu_to_le16(index); | ||
| 406 | req.wLength = cpu_to_le16(size); | ||
| 407 | |||
| 408 | pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); | ||
| 409 | addr = DBGP_EPADDR(devnum, 0); | ||
| 410 | |||
| 411 | ctrl = readl(&ehci_debug->control); | ||
| 412 | ctrl = dbgp_len_update(ctrl, sizeof(req)); | ||
| 413 | ctrl |= DBGP_OUT; | ||
| 414 | ctrl |= DBGP_GO; | ||
| 415 | |||
| 416 | /* Send the setup message */ | ||
| 417 | dbgp_set_data(&req, sizeof(req)); | ||
| 418 | writel(addr, &ehci_debug->address); | ||
| 419 | writel(pids, &ehci_debug->pids); | ||
| 420 | ret = dbgp_wait_until_done(ctrl); | ||
| 421 | if (ret < 0) | ||
| 422 | return ret; | ||
| 423 | |||
| 424 | /* Read the result */ | ||
| 425 | return dbgp_bulk_read(devnum, 0, data, size); | ||
| 426 | } | ||
| 427 | |||
| 428 | |||
| 429 | /* Find a PCI capability */ | ||
| 430 | static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) | ||
| 431 | { | ||
| 432 | u8 pos; | ||
| 433 | int bytes; | ||
| 434 | |||
| 435 | if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & | ||
| 436 | PCI_STATUS_CAP_LIST)) | ||
| 437 | return 0; | ||
| 438 | |||
| 439 | pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); | ||
| 440 | for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { | ||
| 441 | u8 id; | ||
| 442 | |||
| 443 | pos &= ~3; | ||
| 444 | id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); | ||
| 445 | if (id == 0xff) | ||
| 446 | break; | ||
| 447 | if (id == cap) | ||
| 448 | return pos; | ||
| 449 | |||
| 450 | pos = read_pci_config_byte(num, slot, func, | ||
| 451 | pos+PCI_CAP_LIST_NEXT); | ||
| 452 | } | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func) | ||
| 457 | { | ||
| 458 | u32 class; | ||
| 459 | |||
| 460 | class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); | ||
| 461 | if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI) | ||
| 462 | return 0; | ||
| 463 | |||
| 464 | return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG); | ||
| 465 | } | ||
| 466 | |||
| 467 | static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc) | ||
| 468 | { | ||
| 469 | u32 bus, slot, func; | ||
| 470 | |||
| 471 | for (bus = 0; bus < 256; bus++) { | ||
| 472 | for (slot = 0; slot < 32; slot++) { | ||
| 473 | for (func = 0; func < 8; func++) { | ||
| 474 | unsigned cap; | ||
| 475 | |||
| 476 | cap = __find_dbgp(bus, slot, func); | ||
| 477 | |||
| 478 | if (!cap) | ||
| 479 | continue; | ||
| 480 | if (ehci_num-- != 0) | ||
| 481 | continue; | ||
| 482 | *rbus = bus; | ||
| 483 | *rslot = slot; | ||
| 484 | *rfunc = func; | ||
| 485 | return cap; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | } | ||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | static int ehci_reset_port(int port) | ||
| 493 | { | ||
| 494 | u32 portsc; | ||
| 495 | u32 delay_time, delay; | ||
| 496 | int loop; | ||
| 497 | |||
| 498 | /* Reset the usb debug port */ | ||
| 499 | portsc = readl(&ehci_regs->port_status[port - 1]); | ||
| 500 | portsc &= ~PORT_PE; | ||
| 501 | portsc |= PORT_RESET; | ||
| 502 | writel(portsc, &ehci_regs->port_status[port - 1]); | ||
| 503 | |||
| 504 | delay = HUB_ROOT_RESET_TIME; | ||
| 505 | for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; | ||
| 506 | delay_time += delay) { | ||
| 507 | dbgp_mdelay(delay); | ||
| 508 | |||
| 509 | portsc = readl(&ehci_regs->port_status[port - 1]); | ||
| 510 | if (portsc & PORT_RESET) { | ||
| 511 | /* force reset to complete */ | ||
| 512 | loop = 2; | ||
| 513 | writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), | ||
| 514 | &ehci_regs->port_status[port - 1]); | ||
| 515 | do { | ||
| 516 | portsc = readl(&ehci_regs->port_status[port-1]); | ||
| 517 | } while ((portsc & PORT_RESET) && (--loop > 0)); | ||
| 518 | } | ||
| 519 | |||
| 520 | /* Device went away? */ | ||
| 521 | if (!(portsc & PORT_CONNECT)) | ||
| 522 | return -ENOTCONN; | ||
| 523 | |||
| 524 | /* bomb out completely if something weird happend */ | ||
| 525 | if ((portsc & PORT_CSC)) | ||
| 526 | return -EINVAL; | ||
| 527 | |||
| 528 | /* If we've finished resetting, then break out of the loop */ | ||
| 529 | if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) | ||
| 530 | return 0; | ||
| 531 | } | ||
| 532 | return -EBUSY; | ||
| 533 | } | ||
| 534 | |||
| 535 | static int ehci_wait_for_port(int port) | ||
| 536 | { | ||
| 537 | u32 status; | ||
| 538 | int ret, reps; | ||
| 539 | |||
| 540 | for (reps = 0; reps < 3; reps++) { | ||
| 541 | dbgp_mdelay(100); | ||
| 542 | status = readl(&ehci_regs->status); | ||
| 543 | if (status & STS_PCD) { | ||
| 544 | ret = ehci_reset_port(port); | ||
| 545 | if (ret == 0) | ||
| 546 | return 0; | ||
| 547 | } | ||
| 548 | } | ||
| 549 | return -ENOTCONN; | ||
| 550 | } | ||
| 551 | |||
| 552 | #ifdef DBGP_DEBUG | ||
| 553 | # define dbgp_printk early_printk | ||
| 554 | #else | ||
| 555 | static inline void dbgp_printk(const char *fmt, ...) { } | ||
| 556 | #endif | ||
| 557 | |||
| 558 | typedef void (*set_debug_port_t)(int port); | ||
| 559 | |||
| 560 | static void default_set_debug_port(int port) | ||
| 561 | { | ||
| 562 | } | ||
| 563 | |||
| 564 | static set_debug_port_t set_debug_port = default_set_debug_port; | ||
| 565 | |||
| 566 | static void nvidia_set_debug_port(int port) | ||
| 567 | { | ||
| 568 | u32 dword; | ||
| 569 | dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, | ||
| 570 | 0x74); | ||
| 571 | dword &= ~(0x0f<<12); | ||
| 572 | dword |= ((port & 0x0f)<<12); | ||
| 573 | write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74, | ||
| 574 | dword); | ||
| 575 | dbgp_printk("set debug port to %d\n", port); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void __init detect_set_debug_port(void) | ||
| 579 | { | ||
| 580 | u32 vendorid; | ||
| 581 | |||
| 582 | vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, | ||
| 583 | 0x00); | ||
| 584 | |||
| 585 | if ((vendorid & 0xffff) == 0x10de) { | ||
| 586 | dbgp_printk("using nvidia set_debug_port\n"); | ||
| 587 | set_debug_port = nvidia_set_debug_port; | ||
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 591 | static int __init ehci_setup(void) | ||
| 592 | { | ||
| 593 | struct usb_debug_descriptor dbgp_desc; | ||
| 594 | u32 cmd, ctrl, status, portsc, hcs_params; | ||
| 595 | u32 debug_port, new_debug_port = 0, n_ports; | ||
| 596 | u32 devnum; | ||
| 597 | int ret, i; | ||
| 598 | int loop; | ||
| 599 | int port_map_tried; | ||
| 600 | int playtimes = 3; | ||
| 601 | |||
| 602 | try_next_time: | ||
| 603 | port_map_tried = 0; | ||
| 604 | |||
| 605 | try_next_port: | ||
| 606 | |||
| 607 | hcs_params = readl(&ehci_caps->hcs_params); | ||
| 608 | debug_port = HCS_DEBUG_PORT(hcs_params); | ||
| 609 | n_ports = HCS_N_PORTS(hcs_params); | ||
| 610 | |||
| 611 | dbgp_printk("debug_port: %d\n", debug_port); | ||
| 612 | dbgp_printk("n_ports: %d\n", n_ports); | ||
| 613 | |||
| 614 | for (i = 1; i <= n_ports; i++) { | ||
| 615 | portsc = readl(&ehci_regs->port_status[i-1]); | ||
| 616 | dbgp_printk("portstatus%d: %08x\n", i, portsc); | ||
| 617 | } | ||
| 618 | |||
| 619 | if (port_map_tried && (new_debug_port != debug_port)) { | ||
| 620 | if (--playtimes) { | ||
| 621 | set_debug_port(new_debug_port); | ||
| 622 | goto try_next_time; | ||
| 623 | } | ||
| 624 | return -1; | ||
| 625 | } | ||
| 626 | |||
| 627 | loop = 10; | ||
| 628 | /* Reset the EHCI controller */ | ||
| 629 | cmd = readl(&ehci_regs->command); | ||
| 630 | cmd |= CMD_RESET; | ||
| 631 | writel(cmd, &ehci_regs->command); | ||
| 632 | do { | ||
| 633 | cmd = readl(&ehci_regs->command); | ||
| 634 | } while ((cmd & CMD_RESET) && (--loop > 0)); | ||
| 635 | |||
| 636 | if (!loop) { | ||
| 637 | dbgp_printk("can not reset ehci\n"); | ||
| 638 | return -1; | ||
| 639 | } | ||
| 640 | dbgp_printk("ehci reset done\n"); | ||
| 641 | |||
| 642 | /* Claim ownership, but do not enable yet */ | ||
| 643 | ctrl = readl(&ehci_debug->control); | ||
| 644 | ctrl |= DBGP_OWNER; | ||
| 645 | ctrl &= ~(DBGP_ENABLED | DBGP_INUSE); | ||
| 646 | writel(ctrl, &ehci_debug->control); | ||
| 647 | |||
| 648 | /* Start the ehci running */ | ||
| 649 | cmd = readl(&ehci_regs->command); | ||
| 650 | cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET); | ||
| 651 | cmd |= CMD_RUN; | ||
| 652 | writel(cmd, &ehci_regs->command); | ||
| 653 | |||
| 654 | /* Ensure everything is routed to the EHCI */ | ||
| 655 | writel(FLAG_CF, &ehci_regs->configured_flag); | ||
| 656 | |||
| 657 | /* Wait until the controller is no longer halted */ | ||
| 658 | loop = 10; | ||
| 659 | do { | ||
| 660 | status = readl(&ehci_regs->status); | ||
| 661 | } while ((status & STS_HALT) && (--loop > 0)); | ||
| 662 | |||
| 663 | if (!loop) { | ||
| 664 | dbgp_printk("ehci can be started\n"); | ||
| 665 | return -1; | ||
| 666 | } | ||
| 667 | dbgp_printk("ehci started\n"); | ||
| 668 | |||
| 669 | /* Wait for a device to show up in the debug port */ | ||
| 670 | ret = ehci_wait_for_port(debug_port); | ||
| 671 | if (ret < 0) { | ||
| 672 | dbgp_printk("No device found in debug port\n"); | ||
| 673 | goto next_debug_port; | ||
| 674 | } | ||
| 675 | dbgp_printk("ehci wait for port done\n"); | ||
| 676 | |||
| 677 | /* Enable the debug port */ | ||
| 678 | ctrl = readl(&ehci_debug->control); | ||
| 679 | ctrl |= DBGP_CLAIM; | ||
| 680 | writel(ctrl, &ehci_debug->control); | ||
| 681 | ctrl = readl(&ehci_debug->control); | ||
| 682 | if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) { | ||
| 683 | dbgp_printk("No device in debug port\n"); | ||
| 684 | writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control); | ||
| 685 | goto err; | ||
| 686 | } | ||
| 687 | dbgp_printk("debug ported enabled\n"); | ||
| 688 | |||
| 689 | /* Completely transfer the debug device to the debug controller */ | ||
| 690 | portsc = readl(&ehci_regs->port_status[debug_port - 1]); | ||
| 691 | portsc &= ~PORT_PE; | ||
| 692 | writel(portsc, &ehci_regs->port_status[debug_port - 1]); | ||
| 693 | |||
| 694 | dbgp_mdelay(100); | ||
| 695 | |||
| 696 | /* Find the debug device and make it device number 127 */ | ||
| 697 | for (devnum = 0; devnum <= 127; devnum++) { | ||
| 698 | ret = dbgp_control_msg(devnum, | ||
| 699 | USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | ||
| 700 | USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0, | ||
| 701 | &dbgp_desc, sizeof(dbgp_desc)); | ||
| 702 | if (ret > 0) | ||
| 703 | break; | ||
| 704 | } | ||
| 705 | if (devnum > 127) { | ||
| 706 | dbgp_printk("Could not find attached debug device\n"); | ||
| 707 | goto err; | ||
| 708 | } | ||
| 709 | if (ret < 0) { | ||
| 710 | dbgp_printk("Attached device is not a debug device\n"); | ||
| 711 | goto err; | ||
| 712 | } | ||
| 713 | dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; | ||
| 714 | |||
| 715 | /* Move the device to 127 if it isn't already there */ | ||
| 716 | if (devnum != USB_DEBUG_DEVNUM) { | ||
| 717 | ret = dbgp_control_msg(devnum, | ||
| 718 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | ||
| 719 | USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); | ||
| 720 | if (ret < 0) { | ||
| 721 | dbgp_printk("Could not move attached device to %d\n", | ||
| 722 | USB_DEBUG_DEVNUM); | ||
| 723 | goto err; | ||
| 724 | } | ||
| 725 | devnum = USB_DEBUG_DEVNUM; | ||
| 726 | dbgp_printk("debug device renamed to 127\n"); | ||
| 727 | } | ||
| 728 | |||
| 729 | /* Enable the debug interface */ | ||
| 730 | ret = dbgp_control_msg(USB_DEBUG_DEVNUM, | ||
| 731 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | ||
| 732 | USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0); | ||
| 733 | if (ret < 0) { | ||
| 734 | dbgp_printk(" Could not enable the debug device\n"); | ||
| 735 | goto err; | ||
| 736 | } | ||
| 737 | dbgp_printk("debug interface enabled\n"); | ||
| 738 | |||
| 739 | /* Perform a small write to get the even/odd data state in sync | ||
| 740 | */ | ||
| 741 | ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1); | ||
| 742 | if (ret < 0) { | ||
| 743 | dbgp_printk("dbgp_bulk_write failed: %d\n", ret); | ||
| 744 | goto err; | ||
| 745 | } | ||
| 746 | dbgp_printk("small write doned\n"); | ||
| 747 | |||
| 748 | return 0; | ||
| 749 | err: | ||
| 750 | /* Things didn't work so remove my claim */ | ||
| 751 | ctrl = readl(&ehci_debug->control); | ||
| 752 | ctrl &= ~(DBGP_CLAIM | DBGP_OUT); | ||
| 753 | writel(ctrl, &ehci_debug->control); | ||
| 754 | return -1; | ||
| 755 | |||
| 756 | next_debug_port: | ||
| 757 | port_map_tried |= (1<<(debug_port - 1)); | ||
| 758 | new_debug_port = ((debug_port-1+1)%n_ports) + 1; | ||
| 759 | if (port_map_tried != ((1<<n_ports) - 1)) { | ||
| 760 | set_debug_port(new_debug_port); | ||
| 761 | goto try_next_port; | ||
| 762 | } | ||
| 763 | if (--playtimes) { | ||
| 764 | set_debug_port(new_debug_port); | ||
| 765 | goto try_next_time; | ||
| 766 | } | ||
| 767 | |||
| 768 | return -1; | ||
| 769 | } | ||
| 770 | |||
| 771 | static int __init early_dbgp_init(char *s) | ||
| 772 | { | ||
| 773 | u32 debug_port, bar, offset; | ||
| 774 | u32 bus, slot, func, cap; | ||
| 775 | void __iomem *ehci_bar; | ||
| 776 | u32 dbgp_num; | ||
| 777 | u32 bar_val; | ||
| 778 | char *e; | ||
| 779 | int ret; | ||
| 780 | u8 byte; | ||
| 781 | |||
| 782 | if (!early_pci_allowed()) | ||
| 783 | return -1; | ||
| 784 | |||
| 785 | dbgp_num = 0; | ||
| 786 | if (*s) | ||
| 787 | dbgp_num = simple_strtoul(s, &e, 10); | ||
| 788 | dbgp_printk("dbgp_num: %d\n", dbgp_num); | ||
| 789 | |||
| 790 | cap = find_dbgp(dbgp_num, &bus, &slot, &func); | ||
| 791 | if (!cap) | ||
| 792 | return -1; | ||
| 793 | |||
| 794 | dbgp_printk("Found EHCI debug port on %02x:%02x.%1x\n", bus, slot, | ||
| 795 | func); | ||
| 796 | |||
| 797 | debug_port = read_pci_config(bus, slot, func, cap); | ||
| 798 | bar = (debug_port >> 29) & 0x7; | ||
| 799 | bar = (bar * 4) + 0xc; | ||
| 800 | offset = (debug_port >> 16) & 0xfff; | ||
| 801 | dbgp_printk("bar: %02x offset: %03x\n", bar, offset); | ||
| 802 | if (bar != PCI_BASE_ADDRESS_0) { | ||
| 803 | dbgp_printk("only debug ports on bar 1 handled.\n"); | ||
| 804 | |||
| 805 | return -1; | ||
| 806 | } | ||
| 807 | |||
| 808 | bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); | ||
| 809 | dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset); | ||
| 810 | if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) { | ||
| 811 | dbgp_printk("only simple 32bit mmio bars supported\n"); | ||
| 812 | |||
| 813 | return -1; | ||
| 814 | } | ||
| 815 | |||
| 816 | /* double check if the mem space is enabled */ | ||
| 817 | byte = read_pci_config_byte(bus, slot, func, 0x04); | ||
| 818 | if (!(byte & 0x2)) { | ||
| 819 | byte |= 0x02; | ||
| 820 | write_pci_config_byte(bus, slot, func, 0x04, byte); | ||
| 821 | dbgp_printk("mmio for ehci enabled\n"); | ||
| 822 | } | ||
| 823 | |||
| 824 | /* | ||
| 825 | * FIXME I don't have the bar size so just guess PAGE_SIZE is more | ||
| 826 | * than enough. 1K is the biggest I have seen. | ||
| 827 | */ | ||
| 828 | set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); | ||
| 829 | ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); | ||
| 830 | ehci_bar += bar_val & ~PAGE_MASK; | ||
| 831 | dbgp_printk("ehci_bar: %p\n", ehci_bar); | ||
| 832 | |||
| 833 | ehci_caps = ehci_bar; | ||
| 834 | ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)); | ||
| 835 | ehci_debug = ehci_bar + offset; | ||
| 836 | ehci_dev.bus = bus; | ||
| 837 | ehci_dev.slot = slot; | ||
| 838 | ehci_dev.func = func; | ||
| 839 | |||
| 840 | detect_set_debug_port(); | ||
| 841 | |||
| 842 | ret = ehci_setup(); | ||
| 843 | if (ret < 0) { | ||
| 844 | dbgp_printk("ehci_setup failed\n"); | ||
| 845 | ehci_debug = NULL; | ||
| 846 | |||
| 847 | return -1; | ||
| 848 | } | ||
| 849 | |||
| 850 | return 0; | ||
| 851 | } | ||
| 852 | |||
| 853 | static void early_dbgp_write(struct console *con, const char *str, u32 n) | ||
| 854 | { | ||
| 855 | int chunk, ret; | ||
| 856 | |||
| 857 | if (!ehci_debug) | ||
| 858 | return; | ||
| 859 | while (n > 0) { | ||
| 860 | chunk = n; | ||
| 861 | if (chunk > DBGP_MAX_PACKET) | ||
| 862 | chunk = DBGP_MAX_PACKET; | ||
| 863 | ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, | ||
| 864 | dbgp_endpoint_out, str, chunk); | ||
| 865 | str += chunk; | ||
| 866 | n -= chunk; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | static struct console early_dbgp_console = { | ||
| 871 | .name = "earlydbg", | ||
| 872 | .write = early_dbgp_write, | ||
| 873 | .flags = CON_PRINTBUFFER, | ||
| 874 | .index = -1, | ||
| 875 | }; | ||
| 876 | #endif | ||
| 877 | |||
| 154 | /* Console interface to a host file on AMD's SimNow! */ | 878 | /* Console interface to a host file on AMD's SimNow! */ |
| 155 | 879 | ||
| 156 | static int simnow_fd; | 880 | static int simnow_fd; |
| @@ -165,6 +889,7 @@ enum { | |||
| 165 | static noinline long simnow(long cmd, long a, long b, long c) | 889 | static noinline long simnow(long cmd, long a, long b, long c) |
| 166 | { | 890 | { |
| 167 | long ret; | 891 | long ret; |
| 892 | |||
| 168 | asm volatile("cpuid" : | 893 | asm volatile("cpuid" : |
| 169 | "=a" (ret) : | 894 | "=a" (ret) : |
| 170 | "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2)); | 895 | "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2)); |
| @@ -174,6 +899,7 @@ static noinline long simnow(long cmd, long a, long b, long c) | |||
| 174 | static void __init simnow_init(char *str) | 899 | static void __init simnow_init(char *str) |
| 175 | { | 900 | { |
| 176 | char *fn = "klog"; | 901 | char *fn = "klog"; |
| 902 | |||
| 177 | if (*str == '=') | 903 | if (*str == '=') |
| 178 | fn = ++str; | 904 | fn = ++str; |
| 179 | /* error ignored */ | 905 | /* error ignored */ |
| @@ -194,7 +920,7 @@ static struct console simnow_console = { | |||
| 194 | 920 | ||
| 195 | /* Direct interface for emergencies */ | 921 | /* Direct interface for emergencies */ |
| 196 | static struct console *early_console = &early_vga_console; | 922 | static struct console *early_console = &early_vga_console; |
| 197 | static int early_console_initialized; | 923 | static int __initdata early_console_initialized; |
| 198 | 924 | ||
| 199 | asmlinkage void early_printk(const char *fmt, ...) | 925 | asmlinkage void early_printk(const char *fmt, ...) |
| 200 | { | 926 | { |
| @@ -208,10 +934,11 @@ asmlinkage void early_printk(const char *fmt, ...) | |||
| 208 | va_end(ap); | 934 | va_end(ap); |
| 209 | } | 935 | } |
| 210 | 936 | ||
| 211 | static int __initdata keep_early; | ||
| 212 | 937 | ||
| 213 | static int __init setup_early_printk(char *buf) | 938 | static int __init setup_early_printk(char *buf) |
| 214 | { | 939 | { |
| 940 | int keep_early; | ||
| 941 | |||
| 215 | if (!buf) | 942 | if (!buf) |
| 216 | return 0; | 943 | return 0; |
| 217 | 944 | ||
| @@ -219,8 +946,7 @@ static int __init setup_early_printk(char *buf) | |||
| 219 | return 0; | 946 | return 0; |
| 220 | early_console_initialized = 1; | 947 | early_console_initialized = 1; |
| 221 | 948 | ||
| 222 | if (strstr(buf, "keep")) | 949 | keep_early = (strstr(buf, "keep") != NULL); |
| 223 | keep_early = 1; | ||
| 224 | 950 | ||
| 225 | if (!strncmp(buf, "serial", 6)) { | 951 | if (!strncmp(buf, "serial", 6)) { |
| 226 | early_serial_init(buf + 6); | 952 | early_serial_init(buf + 6); |
| @@ -238,6 +964,17 @@ static int __init setup_early_printk(char *buf) | |||
| 238 | simnow_init(buf + 6); | 964 | simnow_init(buf + 6); |
| 239 | early_console = &simnow_console; | 965 | early_console = &simnow_console; |
| 240 | keep_early = 1; | 966 | keep_early = 1; |
| 967 | #ifdef CONFIG_EARLY_PRINTK_DBGP | ||
| 968 | } else if (!strncmp(buf, "dbgp", 4)) { | ||
| 969 | if (early_dbgp_init(buf+4) < 0) | ||
| 970 | return 0; | ||
| 971 | early_console = &early_dbgp_console; | ||
| 972 | /* | ||
| 973 | * usb subsys will reset ehci controller, so don't keep | ||
| 974 | * that early console | ||
| 975 | */ | ||
| 976 | keep_early = 0; | ||
| 977 | #endif | ||
| 241 | #ifdef CONFIG_HVC_XEN | 978 | #ifdef CONFIG_HVC_XEN |
| 242 | } else if (!strncmp(buf, "xen", 3)) { | 979 | } else if (!strncmp(buf, "xen", 3)) { |
| 243 | early_console = &xenboot_console; | 980 | early_console = &xenboot_console; |
| @@ -251,4 +988,5 @@ static int __init setup_early_printk(char *buf) | |||
| 251 | register_console(early_console); | 988 | register_console(early_console); |
| 252 | return 0; | 989 | return 0; |
| 253 | } | 990 | } |
| 991 | |||
| 254 | early_param("earlyprintk", setup_early_printk); | 992 | early_param("earlyprintk", setup_early_printk); |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 45723f1fe198..1f20608d4ca8 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -468,9 +468,23 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
| 468 | 468 | ||
| 469 | static int save_i387_xsave(void __user *buf) | 469 | static int save_i387_xsave(void __user *buf) |
| 470 | { | 470 | { |
| 471 | struct task_struct *tsk = current; | ||
| 471 | struct _fpstate_ia32 __user *fx = buf; | 472 | struct _fpstate_ia32 __user *fx = buf; |
| 472 | int err = 0; | 473 | int err = 0; |
| 473 | 474 | ||
| 475 | /* | ||
| 476 | * For legacy compatible, we always set FP/SSE bits in the bit | ||
| 477 | * vector while saving the state to the user context. | ||
| 478 | * This will enable us capturing any changes(during sigreturn) to | ||
| 479 | * the FP/SSE bits by the legacy applications which don't touch | ||
| 480 | * xstate_bv in the xsave header. | ||
| 481 | * | ||
| 482 | * xsave aware applications can change the xstate_bv in the xsave | ||
| 483 | * header as well as change any contents in the memory layout. | ||
| 484 | * xrestore as part of sigreturn will capture all the changes. | ||
| 485 | */ | ||
| 486 | tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; | ||
| 487 | |||
| 474 | if (save_i387_fxsave(fx) < 0) | 488 | if (save_i387_fxsave(fx) < 0) |
| 475 | return -1; | 489 | return -1; |
| 476 | 490 | ||
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index a1bec2969c6a..02063ae042f7 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c | |||
| @@ -1281,8 +1281,8 @@ __apicdebuginit(void) print_local_APIC(void *dummy) | |||
| 1281 | printk(KERN_DEBUG "... APIC ESR: %08x\n", v); | 1281 | printk(KERN_DEBUG "... APIC ESR: %08x\n", v); |
| 1282 | 1282 | ||
| 1283 | icr = apic_icr_read(); | 1283 | icr = apic_icr_read(); |
| 1284 | printk(KERN_DEBUG "... APIC ICR: %08x\n", icr); | 1284 | printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr); |
| 1285 | printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32); | 1285 | printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32)); |
| 1286 | 1286 | ||
| 1287 | v = apic_read(APIC_LVTT); | 1287 | v = apic_read(APIC_LVTT); |
| 1288 | printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); | 1288 | printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); |
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 0ed5f939b905..eee32b43fee3 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c | |||
| @@ -52,6 +52,8 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) | |||
| 52 | memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, | 52 | memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, |
| 53 | (mincount - oldsize) * LDT_ENTRY_SIZE); | 53 | (mincount - oldsize) * LDT_ENTRY_SIZE); |
| 54 | 54 | ||
| 55 | paravirt_alloc_ldt(newldt, mincount); | ||
| 56 | |||
| 55 | #ifdef CONFIG_X86_64 | 57 | #ifdef CONFIG_X86_64 |
| 56 | /* CHECKME: Do we really need this ? */ | 58 | /* CHECKME: Do we really need this ? */ |
| 57 | wmb(); | 59 | wmb(); |
| @@ -74,6 +76,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) | |||
| 74 | #endif | 76 | #endif |
| 75 | } | 77 | } |
| 76 | if (oldsize) { | 78 | if (oldsize) { |
| 79 | paravirt_free_ldt(oldldt, oldsize); | ||
| 77 | if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) | 80 | if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) |
| 78 | vfree(oldldt); | 81 | vfree(oldldt); |
| 79 | else | 82 | else |
| @@ -85,10 +88,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) | |||
| 85 | static inline int copy_ldt(mm_context_t *new, mm_context_t *old) | 88 | static inline int copy_ldt(mm_context_t *new, mm_context_t *old) |
| 86 | { | 89 | { |
| 87 | int err = alloc_ldt(new, old->size, 0); | 90 | int err = alloc_ldt(new, old->size, 0); |
| 91 | int i; | ||
| 88 | 92 | ||
| 89 | if (err < 0) | 93 | if (err < 0) |
| 90 | return err; | 94 | return err; |
| 91 | memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); | 95 | |
| 96 | for(i = 0; i < old->size; i++) | ||
| 97 | write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE); | ||
| 92 | return 0; | 98 | return 0; |
| 93 | } | 99 | } |
| 94 | 100 | ||
| @@ -125,6 +131,7 @@ void destroy_context(struct mm_struct *mm) | |||
| 125 | if (mm == current->active_mm) | 131 | if (mm == current->active_mm) |
| 126 | clear_LDT(); | 132 | clear_LDT(); |
| 127 | #endif | 133 | #endif |
| 134 | paravirt_free_ldt(mm->context.ldt, mm->context.size); | ||
| 128 | if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) | 135 | if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) |
| 129 | vfree(mm->context.ldt); | 136 | vfree(mm->context.ldt); |
| 130 | else | 137 | else |
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c deleted file mode 100644 index 652fa5c38ebe..000000000000 --- a/arch/x86/kernel/microcode.c +++ /dev/null | |||
| @@ -1,853 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Intel CPU Microcode Update Driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | ||
| 5 | * 2006 Shaohua Li <shaohua.li@intel.com> | ||
| 6 | * | ||
| 7 | * This driver allows to upgrade microcode on Intel processors | ||
| 8 | * belonging to IA-32 family - PentiumPro, Pentium II, | ||
| 9 | * Pentium III, Xeon, Pentium 4, etc. | ||
| 10 | * | ||
| 11 | * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture | ||
| 12 | * Software Developer's Manual | ||
| 13 | * Order Number 253668 or free download from: | ||
| 14 | * | ||
| 15 | * http://developer.intel.com/design/pentium4/manuals/253668.htm | ||
| 16 | * | ||
| 17 | * For more information, go to http://www.urbanmyth.org/microcode | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or | ||
| 20 | * modify it under the terms of the GNU General Public License | ||
| 21 | * as published by the Free Software Foundation; either version | ||
| 22 | * 2 of the License, or (at your option) any later version. | ||
| 23 | * | ||
| 24 | * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 25 | * Initial release. | ||
| 26 | * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 27 | * Added read() support + cleanups. | ||
| 28 | * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 29 | * Added 'device trimming' support. open(O_WRONLY) zeroes | ||
| 30 | * and frees the saved copy of applied microcode. | ||
| 31 | * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 32 | * Made to use devfs (/dev/cpu/microcode) + cleanups. | ||
| 33 | * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 34 | * Added misc device support (now uses both devfs and misc). | ||
| 35 | * Added MICROCODE_IOCFREE ioctl to clear memory. | ||
| 36 | * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 37 | * Messages for error cases (non Intel & no suitable microcode). | ||
| 38 | * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 39 | * Removed ->release(). Removed exclusive open and status bitmap. | ||
| 40 | * Added microcode_rwsem to serialize read()/write()/ioctl(). | ||
| 41 | * Removed global kernel lock usage. | ||
| 42 | * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 43 | * Write 0 to 0x8B msr and then cpuid before reading revision, | ||
| 44 | * so that it works even if there were no update done by the | ||
| 45 | * BIOS. Otherwise, reading from 0x8B gives junk (which happened | ||
| 46 | * to be 0 on my machine which is why it worked even when I | ||
| 47 | * disabled update by the BIOS) | ||
| 48 | * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix. | ||
| 49 | * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and | ||
| 50 | * Tigran Aivazian <tigran@veritas.com> | ||
| 51 | * Intel Pentium 4 processor support and bugfixes. | ||
| 52 | * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com> | ||
| 53 | * Bugfix for HT (Hyper-Threading) enabled processors | ||
| 54 | * whereby processor resources are shared by all logical processors | ||
| 55 | * in a single CPU package. | ||
| 56 | * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and | ||
| 57 | * Tigran Aivazian <tigran@veritas.com>, | ||
| 58 | * Serialize updates as required on HT processors due to speculative | ||
| 59 | * nature of implementation. | ||
| 60 | * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> | ||
| 61 | * Fix the panic when writing zero-length microcode chunk. | ||
| 62 | * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, | ||
| 63 | * Jun Nakajima <jun.nakajima@intel.com> | ||
| 64 | * Support for the microcode updates in the new format. | ||
| 65 | * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> | ||
| 66 | * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl | ||
| 67 | * because we no longer hold a copy of applied microcode | ||
| 68 | * in kernel memory. | ||
| 69 | * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> | ||
| 70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. | ||
| 71 | * Thanks to Stuart Swales for pointing out this bug. | ||
| 72 | */ | ||
| 73 | |||
| 74 | //#define DEBUG /* pr_debug */ | ||
| 75 | #include <linux/capability.h> | ||
| 76 | #include <linux/kernel.h> | ||
| 77 | #include <linux/init.h> | ||
| 78 | #include <linux/sched.h> | ||
| 79 | #include <linux/smp_lock.h> | ||
| 80 | #include <linux/cpumask.h> | ||
| 81 | #include <linux/module.h> | ||
| 82 | #include <linux/slab.h> | ||
| 83 | #include <linux/vmalloc.h> | ||
| 84 | #include <linux/miscdevice.h> | ||
| 85 | #include <linux/spinlock.h> | ||
| 86 | #include <linux/mm.h> | ||
| 87 | #include <linux/fs.h> | ||
| 88 | #include <linux/mutex.h> | ||
| 89 | #include <linux/cpu.h> | ||
| 90 | #include <linux/firmware.h> | ||
| 91 | #include <linux/platform_device.h> | ||
| 92 | |||
| 93 | #include <asm/msr.h> | ||
| 94 | #include <asm/uaccess.h> | ||
| 95 | #include <asm/processor.h> | ||
| 96 | |||
| 97 | MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); | ||
| 98 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | ||
| 99 | MODULE_LICENSE("GPL"); | ||
| 100 | |||
| 101 | #define MICROCODE_VERSION "1.14a" | ||
| 102 | |||
| 103 | #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ | ||
| 104 | #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ | ||
| 105 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ | ||
| 106 | #define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ | ||
| 107 | #define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ | ||
| 108 | #define DWSIZE (sizeof (u32)) | ||
| 109 | #define get_totalsize(mc) \ | ||
| 110 | (((microcode_t *)mc)->hdr.totalsize ? \ | ||
| 111 | ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) | ||
| 112 | #define get_datasize(mc) \ | ||
| 113 | (((microcode_t *)mc)->hdr.datasize ? \ | ||
| 114 | ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) | ||
| 115 | |||
| 116 | #define sigmatch(s1, s2, p1, p2) \ | ||
| 117 | (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) | ||
| 118 | |||
| 119 | #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) | ||
| 120 | |||
| 121 | /* serialize access to the physical write to MSR 0x79 */ | ||
| 122 | static DEFINE_SPINLOCK(microcode_update_lock); | ||
| 123 | |||
| 124 | /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ | ||
| 125 | static DEFINE_MUTEX(microcode_mutex); | ||
| 126 | |||
| 127 | static struct ucode_cpu_info { | ||
| 128 | int valid; | ||
| 129 | unsigned int sig; | ||
| 130 | unsigned int pf; | ||
| 131 | unsigned int rev; | ||
| 132 | microcode_t *mc; | ||
| 133 | } ucode_cpu_info[NR_CPUS]; | ||
| 134 | |||
| 135 | static void collect_cpu_info(int cpu_num) | ||
| 136 | { | ||
| 137 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 138 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | ||
| 139 | unsigned int val[2]; | ||
| 140 | |||
| 141 | /* We should bind the task to the CPU */ | ||
| 142 | BUG_ON(raw_smp_processor_id() != cpu_num); | ||
| 143 | uci->pf = uci->rev = 0; | ||
| 144 | uci->mc = NULL; | ||
| 145 | uci->valid = 1; | ||
| 146 | |||
| 147 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
| 148 | cpu_has(c, X86_FEATURE_IA64)) { | ||
| 149 | printk(KERN_ERR "microcode: CPU%d not a capable Intel " | ||
| 150 | "processor\n", cpu_num); | ||
| 151 | uci->valid = 0; | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 155 | uci->sig = cpuid_eax(0x00000001); | ||
| 156 | |||
| 157 | if ((c->x86_model >= 5) || (c->x86 > 6)) { | ||
| 158 | /* get processor flags from MSR 0x17 */ | ||
| 159 | rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
| 160 | uci->pf = 1 << ((val[1] >> 18) & 7); | ||
| 161 | } | ||
| 162 | |||
| 163 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 164 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 165 | sync_core(); | ||
| 166 | /* get the current revision from MSR 0x8B */ | ||
| 167 | rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); | ||
| 168 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", | ||
| 169 | uci->sig, uci->pf, uci->rev); | ||
| 170 | } | ||
| 171 | |||
| 172 | static inline int microcode_update_match(int cpu_num, | ||
| 173 | microcode_header_t *mc_header, int sig, int pf) | ||
| 174 | { | ||
| 175 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | ||
| 176 | |||
| 177 | if (!sigmatch(sig, uci->sig, pf, uci->pf) | ||
| 178 | || mc_header->rev <= uci->rev) | ||
| 179 | return 0; | ||
| 180 | return 1; | ||
| 181 | } | ||
| 182 | |||
| 183 | static int microcode_sanity_check(void *mc) | ||
| 184 | { | ||
| 185 | microcode_header_t *mc_header = mc; | ||
| 186 | struct extended_sigtable *ext_header = NULL; | ||
| 187 | struct extended_signature *ext_sig; | ||
| 188 | unsigned long total_size, data_size, ext_table_size; | ||
| 189 | int sum, orig_sum, ext_sigcount = 0, i; | ||
| 190 | |||
| 191 | total_size = get_totalsize(mc_header); | ||
| 192 | data_size = get_datasize(mc_header); | ||
| 193 | if (data_size + MC_HEADER_SIZE > total_size) { | ||
| 194 | printk(KERN_ERR "microcode: error! " | ||
| 195 | "Bad data size in microcode data file\n"); | ||
| 196 | return -EINVAL; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | ||
| 200 | printk(KERN_ERR "microcode: error! " | ||
| 201 | "Unknown microcode update format\n"); | ||
| 202 | return -EINVAL; | ||
| 203 | } | ||
| 204 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | ||
| 205 | if (ext_table_size) { | ||
| 206 | if ((ext_table_size < EXT_HEADER_SIZE) | ||
| 207 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | ||
| 208 | printk(KERN_ERR "microcode: error! " | ||
| 209 | "Small exttable size in microcode data file\n"); | ||
| 210 | return -EINVAL; | ||
| 211 | } | ||
| 212 | ext_header = mc + MC_HEADER_SIZE + data_size; | ||
| 213 | if (ext_table_size != exttable_size(ext_header)) { | ||
| 214 | printk(KERN_ERR "microcode: error! " | ||
| 215 | "Bad exttable size in microcode data file\n"); | ||
| 216 | return -EFAULT; | ||
| 217 | } | ||
| 218 | ext_sigcount = ext_header->count; | ||
| 219 | } | ||
| 220 | |||
| 221 | /* check extended table checksum */ | ||
| 222 | if (ext_table_size) { | ||
| 223 | int ext_table_sum = 0; | ||
| 224 | int *ext_tablep = (int *)ext_header; | ||
| 225 | |||
| 226 | i = ext_table_size / DWSIZE; | ||
| 227 | while (i--) | ||
| 228 | ext_table_sum += ext_tablep[i]; | ||
| 229 | if (ext_table_sum) { | ||
| 230 | printk(KERN_WARNING "microcode: aborting, " | ||
| 231 | "bad extended signature table checksum\n"); | ||
| 232 | return -EINVAL; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /* calculate the checksum */ | ||
| 237 | orig_sum = 0; | ||
| 238 | i = (MC_HEADER_SIZE + data_size) / DWSIZE; | ||
| 239 | while (i--) | ||
| 240 | orig_sum += ((int *)mc)[i]; | ||
| 241 | if (orig_sum) { | ||
| 242 | printk(KERN_ERR "microcode: aborting, bad checksum\n"); | ||
| 243 | return -EINVAL; | ||
| 244 | } | ||
| 245 | if (!ext_table_size) | ||
| 246 | return 0; | ||
| 247 | /* check extended signature checksum */ | ||
| 248 | for (i = 0; i < ext_sigcount; i++) { | ||
| 249 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | ||
| 250 | EXT_SIGNATURE_SIZE * i; | ||
| 251 | sum = orig_sum | ||
| 252 | - (mc_header->sig + mc_header->pf + mc_header->cksum) | ||
| 253 | + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | ||
| 254 | if (sum) { | ||
| 255 | printk(KERN_ERR "microcode: aborting, bad checksum\n"); | ||
| 256 | return -EINVAL; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | /* | ||
| 263 | * return 0 - no update found | ||
| 264 | * return 1 - found update | ||
| 265 | * return < 0 - error | ||
| 266 | */ | ||
| 267 | static int get_maching_microcode(void *mc, int cpu) | ||
| 268 | { | ||
| 269 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 270 | microcode_header_t *mc_header = mc; | ||
| 271 | struct extended_sigtable *ext_header; | ||
| 272 | unsigned long total_size = get_totalsize(mc_header); | ||
| 273 | int ext_sigcount, i; | ||
| 274 | struct extended_signature *ext_sig; | ||
| 275 | void *new_mc; | ||
| 276 | |||
| 277 | if (microcode_update_match(cpu, mc_header, | ||
| 278 | mc_header->sig, mc_header->pf)) | ||
| 279 | goto find; | ||
| 280 | |||
| 281 | if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) | ||
| 282 | return 0; | ||
| 283 | |||
| 284 | ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; | ||
| 285 | ext_sigcount = ext_header->count; | ||
| 286 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
| 287 | for (i = 0; i < ext_sigcount; i++) { | ||
| 288 | if (microcode_update_match(cpu, mc_header, | ||
| 289 | ext_sig->sig, ext_sig->pf)) | ||
| 290 | goto find; | ||
| 291 | ext_sig++; | ||
| 292 | } | ||
| 293 | return 0; | ||
| 294 | find: | ||
| 295 | pr_debug("microcode: CPU%d found a matching microcode update with" | ||
| 296 | " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev); | ||
| 297 | new_mc = vmalloc(total_size); | ||
| 298 | if (!new_mc) { | ||
| 299 | printk(KERN_ERR "microcode: error! Can not allocate memory\n"); | ||
| 300 | return -ENOMEM; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* free previous update file */ | ||
| 304 | vfree(uci->mc); | ||
| 305 | |||
| 306 | memcpy(new_mc, mc, total_size); | ||
| 307 | uci->mc = new_mc; | ||
| 308 | return 1; | ||
| 309 | } | ||
| 310 | |||
| 311 | static void apply_microcode(int cpu) | ||
| 312 | { | ||
| 313 | unsigned long flags; | ||
| 314 | unsigned int val[2]; | ||
| 315 | int cpu_num = raw_smp_processor_id(); | ||
| 316 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | ||
| 317 | |||
| 318 | /* We should bind the task to the CPU */ | ||
| 319 | BUG_ON(cpu_num != cpu); | ||
| 320 | |||
| 321 | if (uci->mc == NULL) | ||
| 322 | return; | ||
| 323 | |||
| 324 | /* serialize access to the physical write to MSR 0x79 */ | ||
| 325 | spin_lock_irqsave(µcode_update_lock, flags); | ||
| 326 | |||
| 327 | /* write microcode via MSR 0x79 */ | ||
| 328 | wrmsr(MSR_IA32_UCODE_WRITE, | ||
| 329 | (unsigned long) uci->mc->bits, | ||
| 330 | (unsigned long) uci->mc->bits >> 16 >> 16); | ||
| 331 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 332 | |||
| 333 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 334 | sync_core(); | ||
| 335 | |||
| 336 | /* get the current revision from MSR 0x8B */ | ||
| 337 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 338 | |||
| 339 | spin_unlock_irqrestore(µcode_update_lock, flags); | ||
| 340 | if (val[1] != uci->mc->hdr.rev) { | ||
| 341 | printk(KERN_ERR "microcode: CPU%d update from revision " | ||
| 342 | "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); | ||
| 343 | return; | ||
| 344 | } | ||
| 345 | printk(KERN_INFO "microcode: CPU%d updated from revision " | ||
| 346 | "0x%x to 0x%x, date = %08x \n", | ||
| 347 | cpu_num, uci->rev, val[1], uci->mc->hdr.date); | ||
| 348 | uci->rev = val[1]; | ||
| 349 | } | ||
| 350 | |||
| 351 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE | ||
| 352 | static void __user *user_buffer; /* user area microcode data buffer */ | ||
| 353 | static unsigned int user_buffer_size; /* it's size */ | ||
| 354 | |||
| 355 | static long get_next_ucode(void **mc, long offset) | ||
| 356 | { | ||
| 357 | microcode_header_t mc_header; | ||
| 358 | unsigned long total_size; | ||
| 359 | |||
| 360 | /* No more data */ | ||
| 361 | if (offset >= user_buffer_size) | ||
| 362 | return 0; | ||
| 363 | if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) { | ||
| 364 | printk(KERN_ERR "microcode: error! Can not read user data\n"); | ||
| 365 | return -EFAULT; | ||
| 366 | } | ||
| 367 | total_size = get_totalsize(&mc_header); | ||
| 368 | if (offset + total_size > user_buffer_size) { | ||
| 369 | printk(KERN_ERR "microcode: error! Bad total size in microcode " | ||
| 370 | "data file\n"); | ||
| 371 | return -EINVAL; | ||
| 372 | } | ||
| 373 | *mc = vmalloc(total_size); | ||
| 374 | if (!*mc) | ||
| 375 | return -ENOMEM; | ||
| 376 | if (copy_from_user(*mc, user_buffer + offset, total_size)) { | ||
| 377 | printk(KERN_ERR "microcode: error! Can not read user data\n"); | ||
| 378 | vfree(*mc); | ||
| 379 | return -EFAULT; | ||
| 380 | } | ||
| 381 | return offset + total_size; | ||
| 382 | } | ||
| 383 | |||
| 384 | static int do_microcode_update (void) | ||
| 385 | { | ||
| 386 | long cursor = 0; | ||
| 387 | int error = 0; | ||
| 388 | void *new_mc = NULL; | ||
| 389 | int cpu; | ||
| 390 | cpumask_t old; | ||
| 391 | |||
| 392 | old = current->cpus_allowed; | ||
| 393 | |||
| 394 | while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { | ||
| 395 | error = microcode_sanity_check(new_mc); | ||
| 396 | if (error) | ||
| 397 | goto out; | ||
| 398 | /* | ||
| 399 | * It's possible the data file has multiple matching ucode, | ||
| 400 | * lets keep searching till the latest version | ||
| 401 | */ | ||
| 402 | for_each_online_cpu(cpu) { | ||
| 403 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 404 | |||
| 405 | if (!uci->valid) | ||
| 406 | continue; | ||
| 407 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 408 | error = get_maching_microcode(new_mc, cpu); | ||
| 409 | if (error < 0) | ||
| 410 | goto out; | ||
| 411 | if (error == 1) | ||
| 412 | apply_microcode(cpu); | ||
| 413 | } | ||
| 414 | vfree(new_mc); | ||
| 415 | } | ||
| 416 | out: | ||
| 417 | if (cursor > 0) | ||
| 418 | vfree(new_mc); | ||
| 419 | if (cursor < 0) | ||
| 420 | error = cursor; | ||
| 421 | set_cpus_allowed_ptr(current, &old); | ||
| 422 | return error; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int microcode_open (struct inode *unused1, struct file *unused2) | ||
| 426 | { | ||
| 427 | cycle_kernel_lock(); | ||
| 428 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | ||
| 429 | } | ||
| 430 | |||
| 431 | static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) | ||
| 432 | { | ||
| 433 | ssize_t ret; | ||
| 434 | |||
| 435 | if ((len >> PAGE_SHIFT) > num_physpages) { | ||
| 436 | printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); | ||
| 437 | return -EINVAL; | ||
| 438 | } | ||
| 439 | |||
| 440 | get_online_cpus(); | ||
| 441 | mutex_lock(µcode_mutex); | ||
| 442 | |||
| 443 | user_buffer = (void __user *) buf; | ||
| 444 | user_buffer_size = (int) len; | ||
| 445 | |||
| 446 | ret = do_microcode_update(); | ||
| 447 | if (!ret) | ||
| 448 | ret = (ssize_t)len; | ||
| 449 | |||
| 450 | mutex_unlock(µcode_mutex); | ||
| 451 | put_online_cpus(); | ||
| 452 | |||
| 453 | return ret; | ||
| 454 | } | ||
| 455 | |||
| 456 | static const struct file_operations microcode_fops = { | ||
| 457 | .owner = THIS_MODULE, | ||
| 458 | .write = microcode_write, | ||
| 459 | .open = microcode_open, | ||
| 460 | }; | ||
| 461 | |||
| 462 | static struct miscdevice microcode_dev = { | ||
| 463 | .minor = MICROCODE_MINOR, | ||
| 464 | .name = "microcode", | ||
| 465 | .fops = µcode_fops, | ||
| 466 | }; | ||
| 467 | |||
| 468 | static int __init microcode_dev_init (void) | ||
| 469 | { | ||
| 470 | int error; | ||
| 471 | |||
| 472 | error = misc_register(µcode_dev); | ||
| 473 | if (error) { | ||
| 474 | printk(KERN_ERR | ||
| 475 | "microcode: can't misc_register on minor=%d\n", | ||
| 476 | MICROCODE_MINOR); | ||
| 477 | return error; | ||
| 478 | } | ||
| 479 | |||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | static void microcode_dev_exit (void) | ||
| 484 | { | ||
| 485 | misc_deregister(µcode_dev); | ||
| 486 | } | ||
| 487 | |||
| 488 | MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); | ||
| 489 | #else | ||
| 490 | #define microcode_dev_init() 0 | ||
| 491 | #define microcode_dev_exit() do { } while(0) | ||
| 492 | #endif | ||
| 493 | |||
| 494 | static long get_next_ucode_from_buffer(void **mc, const u8 *buf, | ||
| 495 | unsigned long size, long offset) | ||
| 496 | { | ||
| 497 | microcode_header_t *mc_header; | ||
| 498 | unsigned long total_size; | ||
| 499 | |||
| 500 | /* No more data */ | ||
| 501 | if (offset >= size) | ||
| 502 | return 0; | ||
| 503 | mc_header = (microcode_header_t *)(buf + offset); | ||
| 504 | total_size = get_totalsize(mc_header); | ||
| 505 | |||
| 506 | if (offset + total_size > size) { | ||
| 507 | printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); | ||
| 508 | return -EINVAL; | ||
| 509 | } | ||
| 510 | |||
| 511 | *mc = vmalloc(total_size); | ||
| 512 | if (!*mc) { | ||
| 513 | printk(KERN_ERR "microcode: error! Can not allocate memory\n"); | ||
| 514 | return -ENOMEM; | ||
| 515 | } | ||
| 516 | memcpy(*mc, buf + offset, total_size); | ||
| 517 | return offset + total_size; | ||
| 518 | } | ||
| 519 | |||
| 520 | /* fake device for request_firmware */ | ||
| 521 | static struct platform_device *microcode_pdev; | ||
| 522 | |||
| 523 | static int cpu_request_microcode(int cpu) | ||
| 524 | { | ||
| 525 | char name[30]; | ||
| 526 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 527 | const struct firmware *firmware; | ||
| 528 | const u8 *buf; | ||
| 529 | unsigned long size; | ||
| 530 | long offset = 0; | ||
| 531 | int error; | ||
| 532 | void *mc; | ||
| 533 | |||
| 534 | /* We should bind the task to the CPU */ | ||
| 535 | BUG_ON(cpu != raw_smp_processor_id()); | ||
| 536 | sprintf(name,"intel-ucode/%02x-%02x-%02x", | ||
| 537 | c->x86, c->x86_model, c->x86_mask); | ||
| 538 | error = request_firmware(&firmware, name, µcode_pdev->dev); | ||
| 539 | if (error) { | ||
| 540 | pr_debug("microcode: data file %s load failed\n", name); | ||
| 541 | return error; | ||
| 542 | } | ||
| 543 | buf = firmware->data; | ||
| 544 | size = firmware->size; | ||
| 545 | while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) | ||
| 546 | > 0) { | ||
| 547 | error = microcode_sanity_check(mc); | ||
| 548 | if (error) | ||
| 549 | break; | ||
| 550 | error = get_maching_microcode(mc, cpu); | ||
| 551 | if (error < 0) | ||
| 552 | break; | ||
| 553 | /* | ||
| 554 | * It's possible the data file has multiple matching ucode, | ||
| 555 | * lets keep searching till the latest version | ||
| 556 | */ | ||
| 557 | if (error == 1) { | ||
| 558 | apply_microcode(cpu); | ||
| 559 | error = 0; | ||
| 560 | } | ||
| 561 | vfree(mc); | ||
| 562 | } | ||
| 563 | if (offset > 0) | ||
| 564 | vfree(mc); | ||
| 565 | if (offset < 0) | ||
| 566 | error = offset; | ||
| 567 | release_firmware(firmware); | ||
| 568 | |||
| 569 | return error; | ||
| 570 | } | ||
| 571 | |||
| 572 | static int apply_microcode_check_cpu(int cpu) | ||
| 573 | { | ||
| 574 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 575 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 576 | cpumask_t old; | ||
| 577 | unsigned int val[2]; | ||
| 578 | int err = 0; | ||
| 579 | |||
| 580 | /* Check if the microcode is available */ | ||
| 581 | if (!uci->mc) | ||
| 582 | return 0; | ||
| 583 | |||
| 584 | old = current->cpus_allowed; | ||
| 585 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 586 | |||
| 587 | /* Check if the microcode we have in memory matches the CPU */ | ||
| 588 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
| 589 | cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001)) | ||
| 590 | err = -EINVAL; | ||
| 591 | |||
| 592 | if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) { | ||
| 593 | /* get processor flags from MSR 0x17 */ | ||
| 594 | rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
| 595 | if (uci->pf != (1 << ((val[1] >> 18) & 7))) | ||
| 596 | err = -EINVAL; | ||
| 597 | } | ||
| 598 | |||
| 599 | if (!err) { | ||
| 600 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 601 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 602 | sync_core(); | ||
| 603 | /* get the current revision from MSR 0x8B */ | ||
| 604 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 605 | if (uci->rev != val[1]) | ||
| 606 | err = -EINVAL; | ||
| 607 | } | ||
| 608 | |||
| 609 | if (!err) | ||
| 610 | apply_microcode(cpu); | ||
| 611 | else | ||
| 612 | printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:" | ||
| 613 | " sig=0x%x, pf=0x%x, rev=0x%x\n", | ||
| 614 | cpu, uci->sig, uci->pf, uci->rev); | ||
| 615 | |||
| 616 | set_cpus_allowed_ptr(current, &old); | ||
| 617 | return err; | ||
| 618 | } | ||
| 619 | |||
| 620 | static void microcode_init_cpu(int cpu, int resume) | ||
| 621 | { | ||
| 622 | cpumask_t old; | ||
| 623 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 624 | |||
| 625 | old = current->cpus_allowed; | ||
| 626 | |||
| 627 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 628 | mutex_lock(µcode_mutex); | ||
| 629 | collect_cpu_info(cpu); | ||
| 630 | if (uci->valid && system_state == SYSTEM_RUNNING && !resume) | ||
| 631 | cpu_request_microcode(cpu); | ||
| 632 | mutex_unlock(µcode_mutex); | ||
| 633 | set_cpus_allowed_ptr(current, &old); | ||
| 634 | } | ||
| 635 | |||
| 636 | static void microcode_fini_cpu(int cpu) | ||
| 637 | { | ||
| 638 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 639 | |||
| 640 | mutex_lock(µcode_mutex); | ||
| 641 | uci->valid = 0; | ||
| 642 | vfree(uci->mc); | ||
| 643 | uci->mc = NULL; | ||
| 644 | mutex_unlock(µcode_mutex); | ||
| 645 | } | ||
| 646 | |||
| 647 | static ssize_t reload_store(struct sys_device *dev, | ||
| 648 | struct sysdev_attribute *attr, | ||
| 649 | const char *buf, size_t sz) | ||
| 650 | { | ||
| 651 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 652 | char *end; | ||
| 653 | unsigned long val = simple_strtoul(buf, &end, 0); | ||
| 654 | int err = 0; | ||
| 655 | int cpu = dev->id; | ||
| 656 | |||
| 657 | if (end == buf) | ||
| 658 | return -EINVAL; | ||
| 659 | if (val == 1) { | ||
| 660 | cpumask_t old = current->cpus_allowed; | ||
| 661 | |||
| 662 | get_online_cpus(); | ||
| 663 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 664 | |||
| 665 | mutex_lock(µcode_mutex); | ||
| 666 | if (uci->valid) | ||
| 667 | err = cpu_request_microcode(cpu); | ||
| 668 | mutex_unlock(µcode_mutex); | ||
| 669 | put_online_cpus(); | ||
| 670 | set_cpus_allowed_ptr(current, &old); | ||
| 671 | } | ||
| 672 | if (err) | ||
| 673 | return err; | ||
| 674 | return sz; | ||
| 675 | } | ||
| 676 | |||
| 677 | static ssize_t version_show(struct sys_device *dev, | ||
| 678 | struct sysdev_attribute *attr, char *buf) | ||
| 679 | { | ||
| 680 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 681 | |||
| 682 | return sprintf(buf, "0x%x\n", uci->rev); | ||
| 683 | } | ||
| 684 | |||
| 685 | static ssize_t pf_show(struct sys_device *dev, | ||
| 686 | struct sysdev_attribute *attr, char *buf) | ||
| 687 | { | ||
| 688 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 689 | |||
| 690 | return sprintf(buf, "0x%x\n", uci->pf); | ||
| 691 | } | ||
| 692 | |||
| 693 | static SYSDEV_ATTR(reload, 0200, NULL, reload_store); | ||
| 694 | static SYSDEV_ATTR(version, 0400, version_show, NULL); | ||
| 695 | static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); | ||
| 696 | |||
| 697 | static struct attribute *mc_default_attrs[] = { | ||
| 698 | &attr_reload.attr, | ||
| 699 | &attr_version.attr, | ||
| 700 | &attr_processor_flags.attr, | ||
| 701 | NULL | ||
| 702 | }; | ||
| 703 | |||
| 704 | static struct attribute_group mc_attr_group = { | ||
| 705 | .attrs = mc_default_attrs, | ||
| 706 | .name = "microcode", | ||
| 707 | }; | ||
| 708 | |||
| 709 | static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) | ||
| 710 | { | ||
| 711 | int err, cpu = sys_dev->id; | ||
| 712 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 713 | |||
| 714 | if (!cpu_online(cpu)) | ||
| 715 | return 0; | ||
| 716 | |||
| 717 | pr_debug("microcode: CPU%d added\n", cpu); | ||
| 718 | memset(uci, 0, sizeof(*uci)); | ||
| 719 | |||
| 720 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); | ||
| 721 | if (err) | ||
| 722 | return err; | ||
| 723 | |||
| 724 | microcode_init_cpu(cpu, resume); | ||
| 725 | |||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | |||
| 729 | static int mc_sysdev_add(struct sys_device *sys_dev) | ||
| 730 | { | ||
| 731 | return __mc_sysdev_add(sys_dev, 0); | ||
| 732 | } | ||
| 733 | |||
| 734 | static int mc_sysdev_remove(struct sys_device *sys_dev) | ||
| 735 | { | ||
| 736 | int cpu = sys_dev->id; | ||
| 737 | |||
| 738 | if (!cpu_online(cpu)) | ||
| 739 | return 0; | ||
| 740 | |||
| 741 | pr_debug("microcode: CPU%d removed\n", cpu); | ||
| 742 | microcode_fini_cpu(cpu); | ||
| 743 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | ||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | |||
| 747 | static int mc_sysdev_resume(struct sys_device *dev) | ||
| 748 | { | ||
| 749 | int cpu = dev->id; | ||
| 750 | |||
| 751 | if (!cpu_online(cpu)) | ||
| 752 | return 0; | ||
| 753 | pr_debug("microcode: CPU%d resumed\n", cpu); | ||
| 754 | /* only CPU 0 will apply ucode here */ | ||
| 755 | apply_microcode(0); | ||
| 756 | return 0; | ||
| 757 | } | ||
| 758 | |||
| 759 | static struct sysdev_driver mc_sysdev_driver = { | ||
| 760 | .add = mc_sysdev_add, | ||
| 761 | .remove = mc_sysdev_remove, | ||
| 762 | .resume = mc_sysdev_resume, | ||
| 763 | }; | ||
| 764 | |||
| 765 | static __cpuinit int | ||
| 766 | mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
| 767 | { | ||
| 768 | unsigned int cpu = (unsigned long)hcpu; | ||
| 769 | struct sys_device *sys_dev; | ||
| 770 | |||
| 771 | sys_dev = get_cpu_sysdev(cpu); | ||
| 772 | switch (action) { | ||
| 773 | case CPU_UP_CANCELED_FROZEN: | ||
| 774 | /* The CPU refused to come up during a system resume */ | ||
| 775 | microcode_fini_cpu(cpu); | ||
| 776 | break; | ||
| 777 | case CPU_ONLINE: | ||
| 778 | case CPU_DOWN_FAILED: | ||
| 779 | mc_sysdev_add(sys_dev); | ||
| 780 | break; | ||
| 781 | case CPU_ONLINE_FROZEN: | ||
| 782 | /* System-wide resume is in progress, try to apply microcode */ | ||
| 783 | if (apply_microcode_check_cpu(cpu)) { | ||
| 784 | /* The application of microcode failed */ | ||
| 785 | microcode_fini_cpu(cpu); | ||
| 786 | __mc_sysdev_add(sys_dev, 1); | ||
| 787 | break; | ||
| 788 | } | ||
| 789 | case CPU_DOWN_FAILED_FROZEN: | ||
| 790 | if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) | ||
| 791 | printk(KERN_ERR "microcode: Failed to create the sysfs " | ||
| 792 | "group for CPU%d\n", cpu); | ||
| 793 | break; | ||
| 794 | case CPU_DOWN_PREPARE: | ||
| 795 | mc_sysdev_remove(sys_dev); | ||
| 796 | break; | ||
| 797 | case CPU_DOWN_PREPARE_FROZEN: | ||
| 798 | /* Suspend is in progress, only remove the interface */ | ||
| 799 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | ||
| 800 | break; | ||
| 801 | } | ||
| 802 | return NOTIFY_OK; | ||
| 803 | } | ||
| 804 | |||
| 805 | static struct notifier_block __refdata mc_cpu_notifier = { | ||
| 806 | .notifier_call = mc_cpu_callback, | ||
| 807 | }; | ||
| 808 | |||
| 809 | static int __init microcode_init (void) | ||
| 810 | { | ||
| 811 | int error; | ||
| 812 | |||
| 813 | printk(KERN_INFO | ||
| 814 | "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n"); | ||
| 815 | |||
| 816 | error = microcode_dev_init(); | ||
| 817 | if (error) | ||
| 818 | return error; | ||
| 819 | microcode_pdev = platform_device_register_simple("microcode", -1, | ||
| 820 | NULL, 0); | ||
| 821 | if (IS_ERR(microcode_pdev)) { | ||
| 822 | microcode_dev_exit(); | ||
| 823 | return PTR_ERR(microcode_pdev); | ||
| 824 | } | ||
| 825 | |||
| 826 | get_online_cpus(); | ||
| 827 | error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); | ||
| 828 | put_online_cpus(); | ||
| 829 | if (error) { | ||
| 830 | microcode_dev_exit(); | ||
| 831 | platform_device_unregister(microcode_pdev); | ||
| 832 | return error; | ||
| 833 | } | ||
| 834 | |||
| 835 | register_hotcpu_notifier(&mc_cpu_notifier); | ||
| 836 | return 0; | ||
| 837 | } | ||
| 838 | |||
| 839 | static void __exit microcode_exit (void) | ||
| 840 | { | ||
| 841 | microcode_dev_exit(); | ||
| 842 | |||
| 843 | unregister_hotcpu_notifier(&mc_cpu_notifier); | ||
| 844 | |||
| 845 | get_online_cpus(); | ||
| 846 | sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); | ||
| 847 | put_online_cpus(); | ||
| 848 | |||
| 849 | platform_device_unregister(microcode_pdev); | ||
| 850 | } | ||
| 851 | |||
| 852 | module_init(microcode_init) | ||
| 853 | module_exit(microcode_exit) | ||
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c new file mode 100644 index 000000000000..7a1f8eeac2c7 --- /dev/null +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -0,0 +1,435 @@ | |||
| 1 | /* | ||
| 2 | * AMD CPU Microcode Update Driver for Linux | ||
| 3 | * Copyright (C) 2008 Advanced Micro Devices Inc. | ||
| 4 | * | ||
| 5 | * Author: Peter Oruba <peter.oruba@amd.com> | ||
| 6 | * | ||
| 7 | * Based on work by: | ||
| 8 | * Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | ||
| 9 | * | ||
| 10 | * This driver allows to upgrade microcode on AMD | ||
| 11 | * family 0x10 and 0x11 processors. | ||
| 12 | * | ||
| 13 | * Licensed unter the terms of the GNU General Public | ||
| 14 | * License version 2. See file COPYING for details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/capability.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/cpumask.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/vmalloc.h> | ||
| 25 | #include <linux/miscdevice.h> | ||
| 26 | #include <linux/spinlock.h> | ||
| 27 | #include <linux/mm.h> | ||
| 28 | #include <linux/fs.h> | ||
| 29 | #include <linux/mutex.h> | ||
| 30 | #include <linux/cpu.h> | ||
| 31 | #include <linux/firmware.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/pci.h> | ||
| 34 | #include <linux/pci_ids.h> | ||
| 35 | |||
| 36 | #include <asm/msr.h> | ||
| 37 | #include <asm/uaccess.h> | ||
| 38 | #include <asm/processor.h> | ||
| 39 | #include <asm/microcode.h> | ||
| 40 | |||
| 41 | MODULE_DESCRIPTION("AMD Microcode Update Driver"); | ||
| 42 | MODULE_AUTHOR("Peter Oruba <peter.oruba@amd.com>"); | ||
| 43 | MODULE_LICENSE("GPL v2"); | ||
| 44 | |||
| 45 | #define UCODE_MAGIC 0x00414d44 | ||
| 46 | #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 | ||
| 47 | #define UCODE_UCODE_TYPE 0x00000001 | ||
| 48 | |||
| 49 | struct equiv_cpu_entry { | ||
| 50 | unsigned int installed_cpu; | ||
| 51 | unsigned int fixed_errata_mask; | ||
| 52 | unsigned int fixed_errata_compare; | ||
| 53 | unsigned int equiv_cpu; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct microcode_header_amd { | ||
| 57 | unsigned int data_code; | ||
| 58 | unsigned int patch_id; | ||
| 59 | unsigned char mc_patch_data_id[2]; | ||
| 60 | unsigned char mc_patch_data_len; | ||
| 61 | unsigned char init_flag; | ||
| 62 | unsigned int mc_patch_data_checksum; | ||
| 63 | unsigned int nb_dev_id; | ||
| 64 | unsigned int sb_dev_id; | ||
| 65 | unsigned char processor_rev_id[2]; | ||
| 66 | unsigned char nb_rev_id; | ||
| 67 | unsigned char sb_rev_id; | ||
| 68 | unsigned char bios_api_rev; | ||
| 69 | unsigned char reserved1[3]; | ||
| 70 | unsigned int match_reg[8]; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct microcode_amd { | ||
| 74 | struct microcode_header_amd hdr; | ||
| 75 | unsigned int mpb[0]; | ||
| 76 | }; | ||
| 77 | |||
| 78 | #define UCODE_MAX_SIZE (2048) | ||
| 79 | #define DEFAULT_UCODE_DATASIZE (896) | ||
| 80 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) | ||
| 81 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | ||
| 82 | #define DWSIZE (sizeof(u32)) | ||
| 83 | /* For now we support a fixed ucode total size only */ | ||
| 84 | #define get_totalsize(mc) \ | ||
| 85 | ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ | ||
| 86 | + MC_HEADER_SIZE) | ||
| 87 | |||
| 88 | /* serialize access to the physical write */ | ||
| 89 | static DEFINE_SPINLOCK(microcode_update_lock); | ||
| 90 | |||
| 91 | static struct equiv_cpu_entry *equiv_cpu_table; | ||
| 92 | |||
| 93 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | ||
| 94 | { | ||
| 95 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 96 | |||
| 97 | memset(csig, 0, sizeof(*csig)); | ||
| 98 | |||
| 99 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { | ||
| 100 | printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", | ||
| 101 | cpu); | ||
| 102 | return -1; | ||
| 103 | } | ||
| 104 | |||
| 105 | asm volatile("movl %1, %%ecx; rdmsr" | ||
| 106 | : "=a" (csig->rev) | ||
| 107 | : "i" (0x0000008B) : "ecx"); | ||
| 108 | |||
| 109 | printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", | ||
| 110 | csig->rev); | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static int get_matching_microcode(int cpu, void *mc, int rev) | ||
| 116 | { | ||
| 117 | struct microcode_header_amd *mc_header = mc; | ||
| 118 | struct pci_dev *nb_pci_dev, *sb_pci_dev; | ||
| 119 | unsigned int current_cpu_id; | ||
| 120 | unsigned int equiv_cpu_id = 0x00; | ||
| 121 | unsigned int i = 0; | ||
| 122 | |||
| 123 | BUG_ON(equiv_cpu_table == NULL); | ||
| 124 | current_cpu_id = cpuid_eax(0x00000001); | ||
| 125 | |||
| 126 | while (equiv_cpu_table[i].installed_cpu != 0) { | ||
| 127 | if (current_cpu_id == equiv_cpu_table[i].installed_cpu) { | ||
| 128 | equiv_cpu_id = equiv_cpu_table[i].equiv_cpu; | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | i++; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (!equiv_cpu_id) { | ||
| 135 | printk(KERN_ERR "microcode: CPU%d cpu_id " | ||
| 136 | "not found in equivalent cpu table \n", cpu); | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) { | ||
| 141 | printk(KERN_ERR | ||
| 142 | "microcode: CPU%d patch does not match " | ||
| 143 | "(patch is %x, cpu extended is %x) \n", | ||
| 144 | cpu, mc_header->processor_rev_id[0], | ||
| 145 | (equiv_cpu_id & 0xff)); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) { | ||
| 150 | printk(KERN_ERR "microcode: CPU%d patch does not match " | ||
| 151 | "(patch is %x, cpu base id is %x) \n", | ||
| 152 | cpu, mc_header->processor_rev_id[1], | ||
| 153 | ((equiv_cpu_id >> 16) & 0xff)); | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | /* ucode may be northbridge specific */ | ||
| 159 | if (mc_header->nb_dev_id) { | ||
| 160 | nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, | ||
| 161 | (mc_header->nb_dev_id & 0xff), | ||
| 162 | NULL); | ||
| 163 | if ((!nb_pci_dev) || | ||
| 164 | (mc_header->nb_rev_id != nb_pci_dev->revision)) { | ||
| 165 | printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu); | ||
| 166 | pci_dev_put(nb_pci_dev); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | pci_dev_put(nb_pci_dev); | ||
| 170 | } | ||
| 171 | |||
| 172 | /* ucode may be southbridge specific */ | ||
| 173 | if (mc_header->sb_dev_id) { | ||
| 174 | sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, | ||
| 175 | (mc_header->sb_dev_id & 0xff), | ||
| 176 | NULL); | ||
| 177 | if ((!sb_pci_dev) || | ||
| 178 | (mc_header->sb_rev_id != sb_pci_dev->revision)) { | ||
| 179 | printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu); | ||
| 180 | pci_dev_put(sb_pci_dev); | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | pci_dev_put(sb_pci_dev); | ||
| 184 | } | ||
| 185 | |||
| 186 | if (mc_header->patch_id <= rev) | ||
| 187 | return 0; | ||
| 188 | |||
| 189 | return 1; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void apply_microcode_amd(int cpu) | ||
| 193 | { | ||
| 194 | unsigned long flags; | ||
| 195 | unsigned int eax, edx; | ||
| 196 | unsigned int rev; | ||
| 197 | int cpu_num = raw_smp_processor_id(); | ||
| 198 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | ||
| 199 | struct microcode_amd *mc_amd = uci->mc; | ||
| 200 | unsigned long addr; | ||
| 201 | |||
| 202 | /* We should bind the task to the CPU */ | ||
| 203 | BUG_ON(cpu_num != cpu); | ||
| 204 | |||
| 205 | if (mc_amd == NULL) | ||
| 206 | return; | ||
| 207 | |||
| 208 | spin_lock_irqsave(µcode_update_lock, flags); | ||
| 209 | |||
| 210 | addr = (unsigned long)&mc_amd->hdr.data_code; | ||
| 211 | edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); | ||
| 212 | eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); | ||
| 213 | |||
| 214 | asm volatile("movl %0, %%ecx; wrmsr" : | ||
| 215 | : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx"); | ||
| 216 | |||
| 217 | /* get patch id after patching */ | ||
| 218 | asm volatile("movl %1, %%ecx; rdmsr" | ||
| 219 | : "=a" (rev) | ||
| 220 | : "i" (0x0000008B) : "ecx"); | ||
| 221 | |||
| 222 | spin_unlock_irqrestore(µcode_update_lock, flags); | ||
| 223 | |||
| 224 | /* check current patch id and patch's id for match */ | ||
| 225 | if (rev != mc_amd->hdr.patch_id) { | ||
| 226 | printk(KERN_ERR "microcode: CPU%d update from revision " | ||
| 227 | "0x%x to 0x%x failed\n", cpu_num, | ||
| 228 | mc_amd->hdr.patch_id, rev); | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | printk(KERN_INFO "microcode: CPU%d updated from revision " | ||
| 233 | "0x%x to 0x%x \n", | ||
| 234 | cpu_num, uci->cpu_sig.rev, mc_amd->hdr.patch_id); | ||
| 235 | |||
| 236 | uci->cpu_sig.rev = rev; | ||
| 237 | } | ||
| 238 | |||
| 239 | static void * get_next_ucode(u8 *buf, unsigned int size, | ||
| 240 | int (*get_ucode_data)(void *, const void *, size_t), | ||
| 241 | unsigned int *mc_size) | ||
| 242 | { | ||
| 243 | unsigned int total_size; | ||
| 244 | #define UCODE_CONTAINER_SECTION_HDR 8 | ||
| 245 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; | ||
| 246 | void *mc; | ||
| 247 | |||
| 248 | if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR)) | ||
| 249 | return NULL; | ||
| 250 | |||
| 251 | if (section_hdr[0] != UCODE_UCODE_TYPE) { | ||
| 252 | printk(KERN_ERR "microcode: error! " | ||
| 253 | "Wrong microcode payload type field\n"); | ||
| 254 | return NULL; | ||
| 255 | } | ||
| 256 | |||
| 257 | total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); | ||
| 258 | |||
| 259 | printk(KERN_INFO "microcode: size %u, total_size %u\n", | ||
| 260 | size, total_size); | ||
| 261 | |||
| 262 | if (total_size > size || total_size > UCODE_MAX_SIZE) { | ||
| 263 | printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); | ||
| 264 | return NULL; | ||
| 265 | } | ||
| 266 | |||
| 267 | mc = vmalloc(UCODE_MAX_SIZE); | ||
| 268 | if (mc) { | ||
| 269 | memset(mc, 0, UCODE_MAX_SIZE); | ||
| 270 | if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size)) { | ||
| 271 | vfree(mc); | ||
| 272 | mc = NULL; | ||
| 273 | } else | ||
| 274 | *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; | ||
| 275 | } | ||
| 276 | #undef UCODE_CONTAINER_SECTION_HDR | ||
| 277 | return mc; | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 281 | static int install_equiv_cpu_table(u8 *buf, | ||
| 282 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 283 | { | ||
| 284 | #define UCODE_CONTAINER_HEADER_SIZE 12 | ||
| 285 | u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE]; | ||
| 286 | unsigned int *buf_pos = (unsigned int *)container_hdr; | ||
| 287 | unsigned long size; | ||
| 288 | |||
| 289 | if (get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE)) | ||
| 290 | return 0; | ||
| 291 | |||
| 292 | size = buf_pos[2]; | ||
| 293 | |||
| 294 | if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { | ||
| 295 | printk(KERN_ERR "microcode: error! " | ||
| 296 | "Wrong microcode equivalnet cpu table\n"); | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); | ||
| 301 | if (!equiv_cpu_table) { | ||
| 302 | printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n"); | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | buf += UCODE_CONTAINER_HEADER_SIZE; | ||
| 307 | if (get_ucode_data(equiv_cpu_table, buf, size)) { | ||
| 308 | vfree(equiv_cpu_table); | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ | ||
| 313 | #undef UCODE_CONTAINER_HEADER_SIZE | ||
| 314 | } | ||
| 315 | |||
| 316 | static void free_equiv_cpu_table(void) | ||
| 317 | { | ||
| 318 | if (equiv_cpu_table) { | ||
| 319 | vfree(equiv_cpu_table); | ||
| 320 | equiv_cpu_table = NULL; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | static int generic_load_microcode(int cpu, void *data, size_t size, | ||
| 325 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 326 | { | ||
| 327 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 328 | u8 *ucode_ptr = data, *new_mc = NULL, *mc; | ||
| 329 | int new_rev = uci->cpu_sig.rev; | ||
| 330 | unsigned int leftover; | ||
| 331 | unsigned long offset; | ||
| 332 | |||
| 333 | offset = install_equiv_cpu_table(ucode_ptr, get_ucode_data); | ||
| 334 | if (!offset) { | ||
| 335 | printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); | ||
| 336 | return -EINVAL; | ||
| 337 | } | ||
| 338 | |||
| 339 | ucode_ptr += offset; | ||
| 340 | leftover = size - offset; | ||
| 341 | |||
| 342 | while (leftover) { | ||
| 343 | unsigned int uninitialized_var(mc_size); | ||
| 344 | struct microcode_header_amd *mc_header; | ||
| 345 | |||
| 346 | mc = get_next_ucode(ucode_ptr, leftover, get_ucode_data, &mc_size); | ||
| 347 | if (!mc) | ||
| 348 | break; | ||
| 349 | |||
| 350 | mc_header = (struct microcode_header_amd *)mc; | ||
| 351 | if (get_matching_microcode(cpu, mc, new_rev)) { | ||
| 352 | if (new_mc) | ||
| 353 | vfree(new_mc); | ||
| 354 | new_rev = mc_header->patch_id; | ||
| 355 | new_mc = mc; | ||
| 356 | } else | ||
| 357 | vfree(mc); | ||
| 358 | |||
| 359 | ucode_ptr += mc_size; | ||
| 360 | leftover -= mc_size; | ||
| 361 | } | ||
| 362 | |||
| 363 | if (new_mc) { | ||
| 364 | if (!leftover) { | ||
| 365 | if (uci->mc) | ||
| 366 | vfree(uci->mc); | ||
| 367 | uci->mc = new_mc; | ||
| 368 | pr_debug("microcode: CPU%d found a matching microcode update with" | ||
| 369 | " version 0x%x (current=0x%x)\n", | ||
| 370 | cpu, new_rev, uci->cpu_sig.rev); | ||
| 371 | } else | ||
| 372 | vfree(new_mc); | ||
| 373 | } | ||
| 374 | |||
| 375 | free_equiv_cpu_table(); | ||
| 376 | |||
| 377 | return (int)leftover; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int get_ucode_fw(void *to, const void *from, size_t n) | ||
| 381 | { | ||
| 382 | memcpy(to, from, n); | ||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | static int request_microcode_fw(int cpu, struct device *device) | ||
| 387 | { | ||
| 388 | const char *fw_name = "amd-ucode/microcode_amd.bin"; | ||
| 389 | const struct firmware *firmware; | ||
| 390 | int ret; | ||
| 391 | |||
| 392 | /* We should bind the task to the CPU */ | ||
| 393 | BUG_ON(cpu != raw_smp_processor_id()); | ||
| 394 | |||
| 395 | ret = request_firmware(&firmware, fw_name, device); | ||
| 396 | if (ret) { | ||
| 397 | printk(KERN_ERR "microcode: ucode data file %s load failed\n", fw_name); | ||
| 398 | return ret; | ||
| 399 | } | ||
| 400 | |||
| 401 | ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, | ||
| 402 | &get_ucode_fw); | ||
| 403 | |||
| 404 | release_firmware(firmware); | ||
| 405 | |||
| 406 | return ret; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int request_microcode_user(int cpu, const void __user *buf, size_t size) | ||
| 410 | { | ||
| 411 | printk(KERN_WARNING "microcode: AMD microcode update via /dev/cpu/microcode" | ||
| 412 | "is not supported\n"); | ||
| 413 | return -1; | ||
| 414 | } | ||
| 415 | |||
| 416 | static void microcode_fini_cpu_amd(int cpu) | ||
| 417 | { | ||
| 418 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 419 | |||
| 420 | vfree(uci->mc); | ||
| 421 | uci->mc = NULL; | ||
| 422 | } | ||
| 423 | |||
| 424 | static struct microcode_ops microcode_amd_ops = { | ||
| 425 | .request_microcode_user = request_microcode_user, | ||
| 426 | .request_microcode_fw = request_microcode_fw, | ||
| 427 | .collect_cpu_info = collect_cpu_info_amd, | ||
| 428 | .apply_microcode = apply_microcode_amd, | ||
| 429 | .microcode_fini_cpu = microcode_fini_cpu_amd, | ||
| 430 | }; | ||
| 431 | |||
| 432 | struct microcode_ops * __init init_amd_microcode(void) | ||
| 433 | { | ||
| 434 | return µcode_amd_ops; | ||
| 435 | } | ||
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c new file mode 100644 index 000000000000..936d8d55f230 --- /dev/null +++ b/arch/x86/kernel/microcode_core.c | |||
| @@ -0,0 +1,508 @@ | |||
| 1 | /* | ||
| 2 | * Intel CPU Microcode Update Driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | ||
| 5 | * 2006 Shaohua Li <shaohua.li@intel.com> | ||
| 6 | * | ||
| 7 | * This driver allows to upgrade microcode on Intel processors | ||
| 8 | * belonging to IA-32 family - PentiumPro, Pentium II, | ||
| 9 | * Pentium III, Xeon, Pentium 4, etc. | ||
| 10 | * | ||
| 11 | * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture | ||
| 12 | * Software Developer's Manual | ||
| 13 | * Order Number 253668 or free download from: | ||
| 14 | * | ||
| 15 | * http://developer.intel.com/design/pentium4/manuals/253668.htm | ||
| 16 | * | ||
| 17 | * For more information, go to http://www.urbanmyth.org/microcode | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or | ||
| 20 | * modify it under the terms of the GNU General Public License | ||
| 21 | * as published by the Free Software Foundation; either version | ||
| 22 | * 2 of the License, or (at your option) any later version. | ||
| 23 | * | ||
| 24 | * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 25 | * Initial release. | ||
| 26 | * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 27 | * Added read() support + cleanups. | ||
| 28 | * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 29 | * Added 'device trimming' support. open(O_WRONLY) zeroes | ||
| 30 | * and frees the saved copy of applied microcode. | ||
| 31 | * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 32 | * Made to use devfs (/dev/cpu/microcode) + cleanups. | ||
| 33 | * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 34 | * Added misc device support (now uses both devfs and misc). | ||
| 35 | * Added MICROCODE_IOCFREE ioctl to clear memory. | ||
| 36 | * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 37 | * Messages for error cases (non Intel & no suitable microcode). | ||
| 38 | * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 39 | * Removed ->release(). Removed exclusive open and status bitmap. | ||
| 40 | * Added microcode_rwsem to serialize read()/write()/ioctl(). | ||
| 41 | * Removed global kernel lock usage. | ||
| 42 | * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 43 | * Write 0 to 0x8B msr and then cpuid before reading revision, | ||
| 44 | * so that it works even if there were no update done by the | ||
| 45 | * BIOS. Otherwise, reading from 0x8B gives junk (which happened | ||
| 46 | * to be 0 on my machine which is why it worked even when I | ||
| 47 | * disabled update by the BIOS) | ||
| 48 | * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix. | ||
| 49 | * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and | ||
| 50 | * Tigran Aivazian <tigran@veritas.com> | ||
| 51 | * Intel Pentium 4 processor support and bugfixes. | ||
| 52 | * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com> | ||
| 53 | * Bugfix for HT (Hyper-Threading) enabled processors | ||
| 54 | * whereby processor resources are shared by all logical processors | ||
| 55 | * in a single CPU package. | ||
| 56 | * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and | ||
| 57 | * Tigran Aivazian <tigran@veritas.com>, | ||
| 58 | * Serialize updates as required on HT processors due to | ||
| 59 | * speculative nature of implementation. | ||
| 60 | * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> | ||
| 61 | * Fix the panic when writing zero-length microcode chunk. | ||
| 62 | * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, | ||
| 63 | * Jun Nakajima <jun.nakajima@intel.com> | ||
| 64 | * Support for the microcode updates in the new format. | ||
| 65 | * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> | ||
| 66 | * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl | ||
| 67 | * because we no longer hold a copy of applied microcode | ||
| 68 | * in kernel memory. | ||
| 69 | * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> | ||
| 70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. | ||
| 71 | * Thanks to Stuart Swales for pointing out this bug. | ||
| 72 | */ | ||
| 73 | #include <linux/capability.h> | ||
| 74 | #include <linux/kernel.h> | ||
| 75 | #include <linux/init.h> | ||
| 76 | #include <linux/sched.h> | ||
| 77 | #include <linux/smp_lock.h> | ||
| 78 | #include <linux/cpumask.h> | ||
| 79 | #include <linux/module.h> | ||
| 80 | #include <linux/slab.h> | ||
| 81 | #include <linux/vmalloc.h> | ||
| 82 | #include <linux/miscdevice.h> | ||
| 83 | #include <linux/spinlock.h> | ||
| 84 | #include <linux/mm.h> | ||
| 85 | #include <linux/fs.h> | ||
| 86 | #include <linux/mutex.h> | ||
| 87 | #include <linux/cpu.h> | ||
| 88 | #include <linux/firmware.h> | ||
| 89 | #include <linux/platform_device.h> | ||
| 90 | |||
| 91 | #include <asm/msr.h> | ||
| 92 | #include <asm/uaccess.h> | ||
| 93 | #include <asm/processor.h> | ||
| 94 | #include <asm/microcode.h> | ||
| 95 | |||
| 96 | MODULE_DESCRIPTION("Microcode Update Driver"); | ||
| 97 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | ||
| 98 | MODULE_LICENSE("GPL"); | ||
| 99 | |||
| 100 | #define MICROCODE_VERSION "2.00" | ||
| 101 | |||
| 102 | struct microcode_ops *microcode_ops; | ||
| 103 | |||
| 104 | /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ | ||
| 105 | static DEFINE_MUTEX(microcode_mutex); | ||
| 106 | |||
| 107 | struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | ||
| 108 | EXPORT_SYMBOL_GPL(ucode_cpu_info); | ||
| 109 | |||
| 110 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE | ||
| 111 | static int do_microcode_update(const void __user *buf, size_t size) | ||
| 112 | { | ||
| 113 | cpumask_t old; | ||
| 114 | int error = 0; | ||
| 115 | int cpu; | ||
| 116 | |||
| 117 | old = current->cpus_allowed; | ||
| 118 | |||
| 119 | for_each_online_cpu(cpu) { | ||
| 120 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 121 | |||
| 122 | if (!uci->valid) | ||
| 123 | continue; | ||
| 124 | |||
| 125 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 126 | error = microcode_ops->request_microcode_user(cpu, buf, size); | ||
| 127 | if (error < 0) | ||
| 128 | goto out; | ||
| 129 | if (!error) | ||
| 130 | microcode_ops->apply_microcode(cpu); | ||
| 131 | } | ||
| 132 | out: | ||
| 133 | set_cpus_allowed_ptr(current, &old); | ||
| 134 | return error; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int microcode_open(struct inode *unused1, struct file *unused2) | ||
| 138 | { | ||
| 139 | cycle_kernel_lock(); | ||
| 140 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | ||
| 141 | } | ||
| 142 | |||
| 143 | static ssize_t microcode_write(struct file *file, const char __user *buf, | ||
| 144 | size_t len, loff_t *ppos) | ||
| 145 | { | ||
| 146 | ssize_t ret; | ||
| 147 | |||
| 148 | if ((len >> PAGE_SHIFT) > num_physpages) { | ||
| 149 | printk(KERN_ERR "microcode: too much data (max %ld pages)\n", | ||
| 150 | num_physpages); | ||
| 151 | return -EINVAL; | ||
| 152 | } | ||
| 153 | |||
| 154 | get_online_cpus(); | ||
| 155 | mutex_lock(µcode_mutex); | ||
| 156 | |||
| 157 | ret = do_microcode_update(buf, len); | ||
| 158 | if (!ret) | ||
| 159 | ret = (ssize_t)len; | ||
| 160 | |||
| 161 | mutex_unlock(µcode_mutex); | ||
| 162 | put_online_cpus(); | ||
| 163 | |||
| 164 | return ret; | ||
| 165 | } | ||
| 166 | |||
| 167 | static const struct file_operations microcode_fops = { | ||
| 168 | .owner = THIS_MODULE, | ||
| 169 | .write = microcode_write, | ||
| 170 | .open = microcode_open, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static struct miscdevice microcode_dev = { | ||
| 174 | .minor = MICROCODE_MINOR, | ||
| 175 | .name = "microcode", | ||
| 176 | .fops = µcode_fops, | ||
| 177 | }; | ||
| 178 | |||
| 179 | static int __init microcode_dev_init(void) | ||
| 180 | { | ||
| 181 | int error; | ||
| 182 | |||
| 183 | error = misc_register(µcode_dev); | ||
| 184 | if (error) { | ||
| 185 | printk(KERN_ERR | ||
| 186 | "microcode: can't misc_register on minor=%d\n", | ||
| 187 | MICROCODE_MINOR); | ||
| 188 | return error; | ||
| 189 | } | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static void microcode_dev_exit(void) | ||
| 195 | { | ||
| 196 | misc_deregister(µcode_dev); | ||
| 197 | } | ||
| 198 | |||
| 199 | MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); | ||
| 200 | #else | ||
| 201 | #define microcode_dev_init() 0 | ||
| 202 | #define microcode_dev_exit() do { } while (0) | ||
| 203 | #endif | ||
| 204 | |||
| 205 | /* fake device for request_firmware */ | ||
| 206 | struct platform_device *microcode_pdev; | ||
| 207 | |||
| 208 | static ssize_t reload_store(struct sys_device *dev, | ||
| 209 | struct sysdev_attribute *attr, | ||
| 210 | const char *buf, size_t sz) | ||
| 211 | { | ||
| 212 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 213 | char *end; | ||
| 214 | unsigned long val = simple_strtoul(buf, &end, 0); | ||
| 215 | int err = 0; | ||
| 216 | int cpu = dev->id; | ||
| 217 | |||
| 218 | if (end == buf) | ||
| 219 | return -EINVAL; | ||
| 220 | if (val == 1) { | ||
| 221 | cpumask_t old = current->cpus_allowed; | ||
| 222 | |||
| 223 | get_online_cpus(); | ||
| 224 | if (cpu_online(cpu)) { | ||
| 225 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 226 | mutex_lock(µcode_mutex); | ||
| 227 | if (uci->valid) { | ||
| 228 | err = microcode_ops->request_microcode_fw(cpu, | ||
| 229 | µcode_pdev->dev); | ||
| 230 | if (!err) | ||
| 231 | microcode_ops->apply_microcode(cpu); | ||
| 232 | } | ||
| 233 | mutex_unlock(µcode_mutex); | ||
| 234 | set_cpus_allowed_ptr(current, &old); | ||
| 235 | } | ||
| 236 | put_online_cpus(); | ||
| 237 | } | ||
| 238 | if (err) | ||
| 239 | return err; | ||
| 240 | return sz; | ||
| 241 | } | ||
| 242 | |||
| 243 | static ssize_t version_show(struct sys_device *dev, | ||
| 244 | struct sysdev_attribute *attr, char *buf) | ||
| 245 | { | ||
| 246 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 247 | |||
| 248 | return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); | ||
| 249 | } | ||
| 250 | |||
| 251 | static ssize_t pf_show(struct sys_device *dev, | ||
| 252 | struct sysdev_attribute *attr, char *buf) | ||
| 253 | { | ||
| 254 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 255 | |||
| 256 | return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); | ||
| 257 | } | ||
| 258 | |||
| 259 | static SYSDEV_ATTR(reload, 0200, NULL, reload_store); | ||
| 260 | static SYSDEV_ATTR(version, 0400, version_show, NULL); | ||
| 261 | static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL); | ||
| 262 | |||
| 263 | static struct attribute *mc_default_attrs[] = { | ||
| 264 | &attr_reload.attr, | ||
| 265 | &attr_version.attr, | ||
| 266 | &attr_processor_flags.attr, | ||
| 267 | NULL | ||
| 268 | }; | ||
| 269 | |||
| 270 | static struct attribute_group mc_attr_group = { | ||
| 271 | .attrs = mc_default_attrs, | ||
| 272 | .name = "microcode", | ||
| 273 | }; | ||
| 274 | |||
| 275 | static void microcode_fini_cpu(int cpu) | ||
| 276 | { | ||
| 277 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 278 | |||
| 279 | mutex_lock(µcode_mutex); | ||
| 280 | microcode_ops->microcode_fini_cpu(cpu); | ||
| 281 | uci->valid = 0; | ||
| 282 | mutex_unlock(µcode_mutex); | ||
| 283 | } | ||
| 284 | |||
| 285 | static void collect_cpu_info(int cpu) | ||
| 286 | { | ||
| 287 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 288 | |||
| 289 | memset(uci, 0, sizeof(*uci)); | ||
| 290 | if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig)) | ||
| 291 | uci->valid = 1; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int microcode_resume_cpu(int cpu) | ||
| 295 | { | ||
| 296 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 297 | struct cpu_signature nsig; | ||
| 298 | |||
| 299 | pr_debug("microcode: CPU%d resumed\n", cpu); | ||
| 300 | |||
| 301 | if (!uci->mc) | ||
| 302 | return 1; | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Let's verify that the 'cached' ucode does belong | ||
| 306 | * to this cpu (a bit of paranoia): | ||
| 307 | */ | ||
| 308 | if (microcode_ops->collect_cpu_info(cpu, &nsig)) { | ||
| 309 | microcode_fini_cpu(cpu); | ||
| 310 | return -1; | ||
| 311 | } | ||
| 312 | |||
| 313 | if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { | ||
| 314 | microcode_fini_cpu(cpu); | ||
| 315 | /* Should we look for a new ucode here? */ | ||
| 316 | return 1; | ||
| 317 | } | ||
| 318 | |||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | void microcode_update_cpu(int cpu) | ||
| 323 | { | ||
| 324 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 325 | int err = 0; | ||
| 326 | |||
| 327 | /* | ||
| 328 | * Check if the system resume is in progress (uci->valid != NULL), | ||
| 329 | * otherwise just request a firmware: | ||
| 330 | */ | ||
| 331 | if (uci->valid) { | ||
| 332 | err = microcode_resume_cpu(cpu); | ||
| 333 | } else { | ||
| 334 | collect_cpu_info(cpu); | ||
| 335 | if (uci->valid && system_state == SYSTEM_RUNNING) | ||
| 336 | err = microcode_ops->request_microcode_fw(cpu, | ||
| 337 | µcode_pdev->dev); | ||
| 338 | } | ||
| 339 | if (!err) | ||
| 340 | microcode_ops->apply_microcode(cpu); | ||
| 341 | } | ||
| 342 | |||
| 343 | static void microcode_init_cpu(int cpu) | ||
| 344 | { | ||
| 345 | cpumask_t old = current->cpus_allowed; | ||
| 346 | |||
| 347 | set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); | ||
| 348 | /* We should bind the task to the CPU */ | ||
| 349 | BUG_ON(raw_smp_processor_id() != cpu); | ||
| 350 | |||
| 351 | mutex_lock(µcode_mutex); | ||
| 352 | microcode_update_cpu(cpu); | ||
| 353 | mutex_unlock(µcode_mutex); | ||
| 354 | |||
| 355 | set_cpus_allowed_ptr(current, &old); | ||
| 356 | } | ||
| 357 | |||
| 358 | static int mc_sysdev_add(struct sys_device *sys_dev) | ||
| 359 | { | ||
| 360 | int err, cpu = sys_dev->id; | ||
| 361 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 362 | |||
| 363 | if (!cpu_online(cpu)) | ||
| 364 | return 0; | ||
| 365 | |||
| 366 | pr_debug("microcode: CPU%d added\n", cpu); | ||
| 367 | memset(uci, 0, sizeof(*uci)); | ||
| 368 | |||
| 369 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); | ||
| 370 | if (err) | ||
| 371 | return err; | ||
| 372 | |||
| 373 | microcode_init_cpu(cpu); | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | static int mc_sysdev_remove(struct sys_device *sys_dev) | ||
| 378 | { | ||
| 379 | int cpu = sys_dev->id; | ||
| 380 | |||
| 381 | if (!cpu_online(cpu)) | ||
| 382 | return 0; | ||
| 383 | |||
| 384 | pr_debug("microcode: CPU%d removed\n", cpu); | ||
| 385 | microcode_fini_cpu(cpu); | ||
| 386 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int mc_sysdev_resume(struct sys_device *dev) | ||
| 391 | { | ||
| 392 | int cpu = dev->id; | ||
| 393 | |||
| 394 | if (!cpu_online(cpu)) | ||
| 395 | return 0; | ||
| 396 | |||
| 397 | /* only CPU 0 will apply ucode here */ | ||
| 398 | microcode_update_cpu(0); | ||
| 399 | return 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | static struct sysdev_driver mc_sysdev_driver = { | ||
| 403 | .add = mc_sysdev_add, | ||
| 404 | .remove = mc_sysdev_remove, | ||
| 405 | .resume = mc_sysdev_resume, | ||
| 406 | }; | ||
| 407 | |||
| 408 | static __cpuinit int | ||
| 409 | mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
| 410 | { | ||
| 411 | unsigned int cpu = (unsigned long)hcpu; | ||
| 412 | struct sys_device *sys_dev; | ||
| 413 | |||
| 414 | sys_dev = get_cpu_sysdev(cpu); | ||
| 415 | switch (action) { | ||
| 416 | case CPU_ONLINE: | ||
| 417 | case CPU_ONLINE_FROZEN: | ||
| 418 | microcode_init_cpu(cpu); | ||
| 419 | case CPU_DOWN_FAILED: | ||
| 420 | case CPU_DOWN_FAILED_FROZEN: | ||
| 421 | pr_debug("microcode: CPU%d added\n", cpu); | ||
| 422 | if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) | ||
| 423 | printk(KERN_ERR "microcode: Failed to create the sysfs " | ||
| 424 | "group for CPU%d\n", cpu); | ||
| 425 | break; | ||
| 426 | case CPU_DOWN_PREPARE: | ||
| 427 | case CPU_DOWN_PREPARE_FROZEN: | ||
| 428 | /* Suspend is in progress, only remove the interface */ | ||
| 429 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | ||
| 430 | pr_debug("microcode: CPU%d removed\n", cpu); | ||
| 431 | break; | ||
| 432 | case CPU_DEAD: | ||
| 433 | case CPU_UP_CANCELED_FROZEN: | ||
| 434 | /* The CPU refused to come up during a system resume */ | ||
| 435 | microcode_fini_cpu(cpu); | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | return NOTIFY_OK; | ||
| 439 | } | ||
| 440 | |||
| 441 | static struct notifier_block __refdata mc_cpu_notifier = { | ||
| 442 | .notifier_call = mc_cpu_callback, | ||
| 443 | }; | ||
| 444 | |||
| 445 | static int __init microcode_init(void) | ||
| 446 | { | ||
| 447 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
| 448 | int error; | ||
| 449 | |||
| 450 | if (c->x86_vendor == X86_VENDOR_INTEL) | ||
| 451 | microcode_ops = init_intel_microcode(); | ||
| 452 | else if (c->x86_vendor == X86_VENDOR_AMD) | ||
| 453 | microcode_ops = init_amd_microcode(); | ||
| 454 | |||
| 455 | if (!microcode_ops) { | ||
| 456 | printk(KERN_ERR "microcode: no support for this CPU vendor\n"); | ||
| 457 | return -ENODEV; | ||
| 458 | } | ||
| 459 | |||
| 460 | error = microcode_dev_init(); | ||
| 461 | if (error) | ||
| 462 | return error; | ||
| 463 | microcode_pdev = platform_device_register_simple("microcode", -1, | ||
| 464 | NULL, 0); | ||
| 465 | if (IS_ERR(microcode_pdev)) { | ||
| 466 | microcode_dev_exit(); | ||
| 467 | return PTR_ERR(microcode_pdev); | ||
| 468 | } | ||
| 469 | |||
| 470 | get_online_cpus(); | ||
| 471 | error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver); | ||
| 472 | put_online_cpus(); | ||
| 473 | if (error) { | ||
| 474 | microcode_dev_exit(); | ||
| 475 | platform_device_unregister(microcode_pdev); | ||
| 476 | return error; | ||
| 477 | } | ||
| 478 | |||
| 479 | register_hotcpu_notifier(&mc_cpu_notifier); | ||
| 480 | |||
| 481 | printk(KERN_INFO | ||
| 482 | "Microcode Update Driver: v" MICROCODE_VERSION | ||
| 483 | " <tigran@aivazian.fsnet.co.uk>" | ||
| 484 | " <peter.oruba@amd.com>\n"); | ||
| 485 | |||
| 486 | return 0; | ||
| 487 | } | ||
| 488 | |||
| 489 | static void __exit microcode_exit(void) | ||
| 490 | { | ||
| 491 | microcode_dev_exit(); | ||
| 492 | |||
| 493 | unregister_hotcpu_notifier(&mc_cpu_notifier); | ||
| 494 | |||
| 495 | get_online_cpus(); | ||
| 496 | sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); | ||
| 497 | put_online_cpus(); | ||
| 498 | |||
| 499 | platform_device_unregister(microcode_pdev); | ||
| 500 | |||
| 501 | microcode_ops = NULL; | ||
| 502 | |||
| 503 | printk(KERN_INFO | ||
| 504 | "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); | ||
| 505 | } | ||
| 506 | |||
| 507 | module_init(microcode_init); | ||
| 508 | module_exit(microcode_exit); | ||
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c new file mode 100644 index 000000000000..622dc4a21784 --- /dev/null +++ b/arch/x86/kernel/microcode_intel.c | |||
| @@ -0,0 +1,480 @@ | |||
| 1 | /* | ||
| 2 | * Intel CPU Microcode Update Driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | ||
| 5 | * 2006 Shaohua Li <shaohua.li@intel.com> | ||
| 6 | * | ||
| 7 | * This driver allows to upgrade microcode on Intel processors | ||
| 8 | * belonging to IA-32 family - PentiumPro, Pentium II, | ||
| 9 | * Pentium III, Xeon, Pentium 4, etc. | ||
| 10 | * | ||
| 11 | * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture | ||
| 12 | * Software Developer's Manual | ||
| 13 | * Order Number 253668 or free download from: | ||
| 14 | * | ||
| 15 | * http://developer.intel.com/design/pentium4/manuals/253668.htm | ||
| 16 | * | ||
| 17 | * For more information, go to http://www.urbanmyth.org/microcode | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or | ||
| 20 | * modify it under the terms of the GNU General Public License | ||
| 21 | * as published by the Free Software Foundation; either version | ||
| 22 | * 2 of the License, or (at your option) any later version. | ||
| 23 | * | ||
| 24 | * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 25 | * Initial release. | ||
| 26 | * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 27 | * Added read() support + cleanups. | ||
| 28 | * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 29 | * Added 'device trimming' support. open(O_WRONLY) zeroes | ||
| 30 | * and frees the saved copy of applied microcode. | ||
| 31 | * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com> | ||
| 32 | * Made to use devfs (/dev/cpu/microcode) + cleanups. | ||
| 33 | * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 34 | * Added misc device support (now uses both devfs and misc). | ||
| 35 | * Added MICROCODE_IOCFREE ioctl to clear memory. | ||
| 36 | * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com> | ||
| 37 | * Messages for error cases (non Intel & no suitable microcode). | ||
| 38 | * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 39 | * Removed ->release(). Removed exclusive open and status bitmap. | ||
| 40 | * Added microcode_rwsem to serialize read()/write()/ioctl(). | ||
| 41 | * Removed global kernel lock usage. | ||
| 42 | * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com> | ||
| 43 | * Write 0 to 0x8B msr and then cpuid before reading revision, | ||
| 44 | * so that it works even if there were no update done by the | ||
| 45 | * BIOS. Otherwise, reading from 0x8B gives junk (which happened | ||
| 46 | * to be 0 on my machine which is why it worked even when I | ||
| 47 | * disabled update by the BIOS) | ||
| 48 | * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix. | ||
| 49 | * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and | ||
| 50 | * Tigran Aivazian <tigran@veritas.com> | ||
| 51 | * Intel Pentium 4 processor support and bugfixes. | ||
| 52 | * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com> | ||
| 53 | * Bugfix for HT (Hyper-Threading) enabled processors | ||
| 54 | * whereby processor resources are shared by all logical processors | ||
| 55 | * in a single CPU package. | ||
| 56 | * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and | ||
| 57 | * Tigran Aivazian <tigran@veritas.com>, | ||
| 58 | * Serialize updates as required on HT processors due to | ||
| 59 | * speculative nature of implementation. | ||
| 60 | * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> | ||
| 61 | * Fix the panic when writing zero-length microcode chunk. | ||
| 62 | * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, | ||
| 63 | * Jun Nakajima <jun.nakajima@intel.com> | ||
| 64 | * Support for the microcode updates in the new format. | ||
| 65 | * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> | ||
| 66 | * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl | ||
| 67 | * because we no longer hold a copy of applied microcode | ||
| 68 | * in kernel memory. | ||
| 69 | * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> | ||
| 70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. | ||
| 71 | * Thanks to Stuart Swales for pointing out this bug. | ||
| 72 | */ | ||
| 73 | #include <linux/capability.h> | ||
| 74 | #include <linux/kernel.h> | ||
| 75 | #include <linux/init.h> | ||
| 76 | #include <linux/sched.h> | ||
| 77 | #include <linux/smp_lock.h> | ||
| 78 | #include <linux/cpumask.h> | ||
| 79 | #include <linux/module.h> | ||
| 80 | #include <linux/slab.h> | ||
| 81 | #include <linux/vmalloc.h> | ||
| 82 | #include <linux/miscdevice.h> | ||
| 83 | #include <linux/spinlock.h> | ||
| 84 | #include <linux/mm.h> | ||
| 85 | #include <linux/fs.h> | ||
| 86 | #include <linux/mutex.h> | ||
| 87 | #include <linux/cpu.h> | ||
| 88 | #include <linux/firmware.h> | ||
| 89 | #include <linux/platform_device.h> | ||
| 90 | |||
| 91 | #include <asm/msr.h> | ||
| 92 | #include <asm/uaccess.h> | ||
| 93 | #include <asm/processor.h> | ||
| 94 | #include <asm/microcode.h> | ||
| 95 | |||
| 96 | MODULE_DESCRIPTION("Microcode Update Driver"); | ||
| 97 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | ||
| 98 | MODULE_LICENSE("GPL"); | ||
| 99 | |||
| 100 | struct microcode_header_intel { | ||
| 101 | unsigned int hdrver; | ||
| 102 | unsigned int rev; | ||
| 103 | unsigned int date; | ||
| 104 | unsigned int sig; | ||
| 105 | unsigned int cksum; | ||
| 106 | unsigned int ldrver; | ||
| 107 | unsigned int pf; | ||
| 108 | unsigned int datasize; | ||
| 109 | unsigned int totalsize; | ||
| 110 | unsigned int reserved[3]; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct microcode_intel { | ||
| 114 | struct microcode_header_intel hdr; | ||
| 115 | unsigned int bits[0]; | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* microcode format is extended from prescott processors */ | ||
| 119 | struct extended_signature { | ||
| 120 | unsigned int sig; | ||
| 121 | unsigned int pf; | ||
| 122 | unsigned int cksum; | ||
| 123 | }; | ||
| 124 | |||
| 125 | struct extended_sigtable { | ||
| 126 | unsigned int count; | ||
| 127 | unsigned int cksum; | ||
| 128 | unsigned int reserved[3]; | ||
| 129 | struct extended_signature sigs[0]; | ||
| 130 | }; | ||
| 131 | |||
| 132 | #define DEFAULT_UCODE_DATASIZE (2000) | ||
| 133 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) | ||
| 134 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | ||
| 135 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) | ||
| 136 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) | ||
| 137 | #define DWSIZE (sizeof(u32)) | ||
| 138 | #define get_totalsize(mc) \ | ||
| 139 | (((struct microcode_intel *)mc)->hdr.totalsize ? \ | ||
| 140 | ((struct microcode_intel *)mc)->hdr.totalsize : \ | ||
| 141 | DEFAULT_UCODE_TOTALSIZE) | ||
| 142 | |||
| 143 | #define get_datasize(mc) \ | ||
| 144 | (((struct microcode_intel *)mc)->hdr.datasize ? \ | ||
| 145 | ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) | ||
| 146 | |||
| 147 | #define sigmatch(s1, s2, p1, p2) \ | ||
| 148 | (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) | ||
| 149 | |||
| 150 | #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) | ||
| 151 | |||
| 152 | /* serialize access to the physical write to MSR 0x79 */ | ||
| 153 | static DEFINE_SPINLOCK(microcode_update_lock); | ||
| 154 | |||
| 155 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | ||
| 156 | { | ||
| 157 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 158 | unsigned int val[2]; | ||
| 159 | |||
| 160 | memset(csig, 0, sizeof(*csig)); | ||
| 161 | |||
| 162 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
| 163 | cpu_has(c, X86_FEATURE_IA64)) { | ||
| 164 | printk(KERN_ERR "microcode: CPU%d not a capable Intel " | ||
| 165 | "processor\n", cpu_num); | ||
| 166 | return -1; | ||
| 167 | } | ||
| 168 | |||
| 169 | csig->sig = cpuid_eax(0x00000001); | ||
| 170 | |||
| 171 | if ((c->x86_model >= 5) || (c->x86 > 6)) { | ||
| 172 | /* get processor flags from MSR 0x17 */ | ||
| 173 | rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
| 174 | csig->pf = 1 << ((val[1] >> 18) & 7); | ||
| 175 | } | ||
| 176 | |||
| 177 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 178 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 179 | sync_core(); | ||
| 180 | /* get the current revision from MSR 0x8B */ | ||
| 181 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); | ||
| 182 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", | ||
| 183 | csig->sig, csig->pf, csig->rev); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf) | ||
| 189 | { | ||
| 190 | return (!sigmatch(sig, csig->sig, pf, csig->pf)) ? 0 : 1; | ||
| 191 | } | ||
| 192 | |||
| 193 | static inline int | ||
| 194 | update_match_revision(struct microcode_header_intel *mc_header, int rev) | ||
| 195 | { | ||
| 196 | return (mc_header->rev <= rev) ? 0 : 1; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int microcode_sanity_check(void *mc) | ||
| 200 | { | ||
| 201 | struct microcode_header_intel *mc_header = mc; | ||
| 202 | struct extended_sigtable *ext_header = NULL; | ||
| 203 | struct extended_signature *ext_sig; | ||
| 204 | unsigned long total_size, data_size, ext_table_size; | ||
| 205 | int sum, orig_sum, ext_sigcount = 0, i; | ||
| 206 | |||
| 207 | total_size = get_totalsize(mc_header); | ||
| 208 | data_size = get_datasize(mc_header); | ||
| 209 | if (data_size + MC_HEADER_SIZE > total_size) { | ||
| 210 | printk(KERN_ERR "microcode: error! " | ||
| 211 | "Bad data size in microcode data file\n"); | ||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | ||
| 216 | printk(KERN_ERR "microcode: error! " | ||
| 217 | "Unknown microcode update format\n"); | ||
| 218 | return -EINVAL; | ||
| 219 | } | ||
| 220 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | ||
| 221 | if (ext_table_size) { | ||
| 222 | if ((ext_table_size < EXT_HEADER_SIZE) | ||
| 223 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | ||
| 224 | printk(KERN_ERR "microcode: error! " | ||
| 225 | "Small exttable size in microcode data file\n"); | ||
| 226 | return -EINVAL; | ||
| 227 | } | ||
| 228 | ext_header = mc + MC_HEADER_SIZE + data_size; | ||
| 229 | if (ext_table_size != exttable_size(ext_header)) { | ||
| 230 | printk(KERN_ERR "microcode: error! " | ||
| 231 | "Bad exttable size in microcode data file\n"); | ||
| 232 | return -EFAULT; | ||
| 233 | } | ||
| 234 | ext_sigcount = ext_header->count; | ||
| 235 | } | ||
| 236 | |||
| 237 | /* check extended table checksum */ | ||
| 238 | if (ext_table_size) { | ||
| 239 | int ext_table_sum = 0; | ||
| 240 | int *ext_tablep = (int *)ext_header; | ||
| 241 | |||
| 242 | i = ext_table_size / DWSIZE; | ||
| 243 | while (i--) | ||
| 244 | ext_table_sum += ext_tablep[i]; | ||
| 245 | if (ext_table_sum) { | ||
| 246 | printk(KERN_WARNING "microcode: aborting, " | ||
| 247 | "bad extended signature table checksum\n"); | ||
| 248 | return -EINVAL; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | /* calculate the checksum */ | ||
| 253 | orig_sum = 0; | ||
| 254 | i = (MC_HEADER_SIZE + data_size) / DWSIZE; | ||
| 255 | while (i--) | ||
| 256 | orig_sum += ((int *)mc)[i]; | ||
| 257 | if (orig_sum) { | ||
| 258 | printk(KERN_ERR "microcode: aborting, bad checksum\n"); | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | if (!ext_table_size) | ||
| 262 | return 0; | ||
| 263 | /* check extended signature checksum */ | ||
| 264 | for (i = 0; i < ext_sigcount; i++) { | ||
| 265 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | ||
| 266 | EXT_SIGNATURE_SIZE * i; | ||
| 267 | sum = orig_sum | ||
| 268 | - (mc_header->sig + mc_header->pf + mc_header->cksum) | ||
| 269 | + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | ||
| 270 | if (sum) { | ||
| 271 | printk(KERN_ERR "microcode: aborting, bad checksum\n"); | ||
| 272 | return -EINVAL; | ||
| 273 | } | ||
| 274 | } | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* | ||
| 279 | * return 0 - no update found | ||
| 280 | * return 1 - found update | ||
| 281 | */ | ||
| 282 | static int | ||
| 283 | get_matching_microcode(struct cpu_signature *cpu_sig, void *mc, int rev) | ||
| 284 | { | ||
| 285 | struct microcode_header_intel *mc_header = mc; | ||
| 286 | struct extended_sigtable *ext_header; | ||
| 287 | unsigned long total_size = get_totalsize(mc_header); | ||
| 288 | int ext_sigcount, i; | ||
| 289 | struct extended_signature *ext_sig; | ||
| 290 | |||
| 291 | if (!update_match_revision(mc_header, rev)) | ||
| 292 | return 0; | ||
| 293 | |||
| 294 | if (update_match_cpu(cpu_sig, mc_header->sig, mc_header->pf)) | ||
| 295 | return 1; | ||
| 296 | |||
| 297 | /* Look for ext. headers: */ | ||
| 298 | if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) | ||
| 299 | return 0; | ||
| 300 | |||
| 301 | ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; | ||
| 302 | ext_sigcount = ext_header->count; | ||
| 303 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
| 304 | |||
| 305 | for (i = 0; i < ext_sigcount; i++) { | ||
| 306 | if (update_match_cpu(cpu_sig, ext_sig->sig, ext_sig->pf)) | ||
| 307 | return 1; | ||
| 308 | ext_sig++; | ||
| 309 | } | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static void apply_microcode(int cpu) | ||
| 314 | { | ||
| 315 | unsigned long flags; | ||
| 316 | unsigned int val[2]; | ||
| 317 | int cpu_num = raw_smp_processor_id(); | ||
| 318 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 319 | struct microcode_intel *mc_intel = uci->mc; | ||
| 320 | |||
| 321 | /* We should bind the task to the CPU */ | ||
| 322 | BUG_ON(cpu_num != cpu); | ||
| 323 | |||
| 324 | if (mc_intel == NULL) | ||
| 325 | return; | ||
| 326 | |||
| 327 | /* serialize access to the physical write to MSR 0x79 */ | ||
| 328 | spin_lock_irqsave(µcode_update_lock, flags); | ||
| 329 | |||
| 330 | /* write microcode via MSR 0x79 */ | ||
| 331 | wrmsr(MSR_IA32_UCODE_WRITE, | ||
| 332 | (unsigned long) mc_intel->bits, | ||
| 333 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
| 334 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 335 | |||
| 336 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 337 | sync_core(); | ||
| 338 | |||
| 339 | /* get the current revision from MSR 0x8B */ | ||
| 340 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 341 | |||
| 342 | spin_unlock_irqrestore(µcode_update_lock, flags); | ||
| 343 | if (val[1] != mc_intel->hdr.rev) { | ||
| 344 | printk(KERN_ERR "microcode: CPU%d update from revision " | ||
| 345 | "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | printk(KERN_INFO "microcode: CPU%d updated from revision " | ||
| 349 | "0x%x to 0x%x, date = %04x-%02x-%02x \n", | ||
| 350 | cpu_num, uci->cpu_sig.rev, val[1], | ||
| 351 | mc_intel->hdr.date & 0xffff, | ||
| 352 | mc_intel->hdr.date >> 24, | ||
| 353 | (mc_intel->hdr.date >> 16) & 0xff); | ||
| 354 | uci->cpu_sig.rev = val[1]; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int generic_load_microcode(int cpu, void *data, size_t size, | ||
| 358 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 359 | { | ||
| 360 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 361 | u8 *ucode_ptr = data, *new_mc = NULL, *mc; | ||
| 362 | int new_rev = uci->cpu_sig.rev; | ||
| 363 | unsigned int leftover = size; | ||
| 364 | |||
| 365 | while (leftover) { | ||
| 366 | struct microcode_header_intel mc_header; | ||
| 367 | unsigned int mc_size; | ||
| 368 | |||
| 369 | if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header))) | ||
| 370 | break; | ||
| 371 | |||
| 372 | mc_size = get_totalsize(&mc_header); | ||
| 373 | if (!mc_size || mc_size > leftover) { | ||
| 374 | printk(KERN_ERR "microcode: error!" | ||
| 375 | "Bad data in microcode data file\n"); | ||
| 376 | break; | ||
| 377 | } | ||
| 378 | |||
| 379 | mc = vmalloc(mc_size); | ||
| 380 | if (!mc) | ||
| 381 | break; | ||
| 382 | |||
| 383 | if (get_ucode_data(mc, ucode_ptr, mc_size) || | ||
| 384 | microcode_sanity_check(mc) < 0) { | ||
| 385 | vfree(mc); | ||
| 386 | break; | ||
| 387 | } | ||
| 388 | |||
| 389 | if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { | ||
| 390 | if (new_mc) | ||
| 391 | vfree(new_mc); | ||
| 392 | new_rev = mc_header.rev; | ||
| 393 | new_mc = mc; | ||
| 394 | } else | ||
| 395 | vfree(mc); | ||
| 396 | |||
| 397 | ucode_ptr += mc_size; | ||
| 398 | leftover -= mc_size; | ||
| 399 | } | ||
| 400 | |||
| 401 | if (new_mc) { | ||
| 402 | if (!leftover) { | ||
| 403 | if (uci->mc) | ||
| 404 | vfree(uci->mc); | ||
| 405 | uci->mc = (struct microcode_intel *)new_mc; | ||
| 406 | pr_debug("microcode: CPU%d found a matching microcode update with" | ||
| 407 | " version 0x%x (current=0x%x)\n", | ||
| 408 | cpu, new_rev, uci->cpu_sig.rev); | ||
| 409 | } else | ||
| 410 | vfree(new_mc); | ||
| 411 | } | ||
| 412 | |||
| 413 | return (int)leftover; | ||
| 414 | } | ||
| 415 | |||
| 416 | static int get_ucode_fw(void *to, const void *from, size_t n) | ||
| 417 | { | ||
| 418 | memcpy(to, from, n); | ||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int request_microcode_fw(int cpu, struct device *device) | ||
| 423 | { | ||
| 424 | char name[30]; | ||
| 425 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 426 | const struct firmware *firmware; | ||
| 427 | int ret; | ||
| 428 | |||
| 429 | /* We should bind the task to the CPU */ | ||
| 430 | BUG_ON(cpu != raw_smp_processor_id()); | ||
| 431 | sprintf(name, "intel-ucode/%02x-%02x-%02x", | ||
| 432 | c->x86, c->x86_model, c->x86_mask); | ||
| 433 | ret = request_firmware(&firmware, name, device); | ||
| 434 | if (ret) { | ||
| 435 | pr_debug("microcode: data file %s load failed\n", name); | ||
| 436 | return ret; | ||
| 437 | } | ||
| 438 | |||
| 439 | ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, | ||
| 440 | &get_ucode_fw); | ||
| 441 | |||
| 442 | release_firmware(firmware); | ||
| 443 | |||
| 444 | return ret; | ||
| 445 | } | ||
| 446 | |||
| 447 | static int get_ucode_user(void *to, const void *from, size_t n) | ||
| 448 | { | ||
| 449 | return copy_from_user(to, from, n); | ||
| 450 | } | ||
| 451 | |||
| 452 | static int request_microcode_user(int cpu, const void __user *buf, size_t size) | ||
| 453 | { | ||
| 454 | /* We should bind the task to the CPU */ | ||
| 455 | BUG_ON(cpu != raw_smp_processor_id()); | ||
| 456 | |||
| 457 | return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user); | ||
| 458 | } | ||
| 459 | |||
| 460 | static void microcode_fini_cpu(int cpu) | ||
| 461 | { | ||
| 462 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 463 | |||
| 464 | vfree(uci->mc); | ||
| 465 | uci->mc = NULL; | ||
| 466 | } | ||
| 467 | |||
| 468 | struct microcode_ops microcode_intel_ops = { | ||
| 469 | .request_microcode_user = request_microcode_user, | ||
| 470 | .request_microcode_fw = request_microcode_fw, | ||
| 471 | .collect_cpu_info = collect_cpu_info, | ||
| 472 | .apply_microcode = apply_microcode, | ||
| 473 | .microcode_fini_cpu = microcode_fini_cpu, | ||
| 474 | }; | ||
| 475 | |||
| 476 | struct microcode_ops * __init init_intel_microcode(void) | ||
| 477 | { | ||
| 478 | return µcode_intel_ops; | ||
| 479 | } | ||
| 480 | |||
diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c new file mode 100644 index 000000000000..0e9f1982b1dd --- /dev/null +++ b/arch/x86/kernel/paravirt-spinlocks.c | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * Split spinlock implementation out into its own file, so it can be | ||
| 3 | * compiled in a FTRACE-compatible way. | ||
| 4 | */ | ||
| 5 | #include <linux/spinlock.h> | ||
| 6 | #include <linux/module.h> | ||
| 7 | |||
| 8 | #include <asm/paravirt.h> | ||
| 9 | |||
| 10 | static void default_spin_lock_flags(struct raw_spinlock *lock, unsigned long flags) | ||
| 11 | { | ||
| 12 | __raw_spin_lock(lock); | ||
| 13 | } | ||
| 14 | |||
| 15 | struct pv_lock_ops pv_lock_ops = { | ||
| 16 | #ifdef CONFIG_SMP | ||
| 17 | .spin_is_locked = __ticket_spin_is_locked, | ||
| 18 | .spin_is_contended = __ticket_spin_is_contended, | ||
| 19 | |||
| 20 | .spin_lock = __ticket_spin_lock, | ||
| 21 | .spin_lock_flags = default_spin_lock_flags, | ||
| 22 | .spin_trylock = __ticket_spin_trylock, | ||
| 23 | .spin_unlock = __ticket_spin_unlock, | ||
| 24 | #endif | ||
| 25 | }; | ||
| 26 | EXPORT_SYMBOL(pv_lock_ops); | ||
| 27 | |||
| 28 | void __init paravirt_use_bytelocks(void) | ||
| 29 | { | ||
| 30 | #ifdef CONFIG_SMP | ||
| 31 | pv_lock_ops.spin_is_locked = __byte_spin_is_locked; | ||
| 32 | pv_lock_ops.spin_is_contended = __byte_spin_is_contended; | ||
| 33 | pv_lock_ops.spin_lock = __byte_spin_lock; | ||
| 34 | pv_lock_ops.spin_trylock = __byte_spin_trylock; | ||
| 35 | pv_lock_ops.spin_unlock = __byte_spin_unlock; | ||
| 36 | #endif | ||
| 37 | } | ||
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 6b0bb73998dd..e4c8fb608873 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
| @@ -268,17 +268,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) | |||
| 268 | return __get_cpu_var(paravirt_lazy_mode); | 268 | return __get_cpu_var(paravirt_lazy_mode); |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | void __init paravirt_use_bytelocks(void) | ||
| 272 | { | ||
| 273 | #ifdef CONFIG_SMP | ||
| 274 | pv_lock_ops.spin_is_locked = __byte_spin_is_locked; | ||
| 275 | pv_lock_ops.spin_is_contended = __byte_spin_is_contended; | ||
| 276 | pv_lock_ops.spin_lock = __byte_spin_lock; | ||
| 277 | pv_lock_ops.spin_trylock = __byte_spin_trylock; | ||
| 278 | pv_lock_ops.spin_unlock = __byte_spin_unlock; | ||
| 279 | #endif | ||
| 280 | } | ||
| 281 | |||
| 282 | struct pv_info pv_info = { | 271 | struct pv_info pv_info = { |
| 283 | .name = "bare hardware", | 272 | .name = "bare hardware", |
| 284 | .paravirt_enabled = 0, | 273 | .paravirt_enabled = 0, |
| @@ -349,6 +338,10 @@ struct pv_cpu_ops pv_cpu_ops = { | |||
| 349 | .write_ldt_entry = native_write_ldt_entry, | 338 | .write_ldt_entry = native_write_ldt_entry, |
| 350 | .write_gdt_entry = native_write_gdt_entry, | 339 | .write_gdt_entry = native_write_gdt_entry, |
| 351 | .write_idt_entry = native_write_idt_entry, | 340 | .write_idt_entry = native_write_idt_entry, |
| 341 | |||
| 342 | .alloc_ldt = paravirt_nop, | ||
| 343 | .free_ldt = paravirt_nop, | ||
| 344 | |||
| 352 | .load_sp0 = native_load_sp0, | 345 | .load_sp0 = native_load_sp0, |
| 353 | 346 | ||
| 354 | #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) | 347 | #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) |
| @@ -460,18 +453,6 @@ struct pv_mmu_ops pv_mmu_ops = { | |||
| 460 | .set_fixmap = native_set_fixmap, | 453 | .set_fixmap = native_set_fixmap, |
| 461 | }; | 454 | }; |
| 462 | 455 | ||
| 463 | struct pv_lock_ops pv_lock_ops = { | ||
| 464 | #ifdef CONFIG_SMP | ||
| 465 | .spin_is_locked = __ticket_spin_is_locked, | ||
| 466 | .spin_is_contended = __ticket_spin_is_contended, | ||
| 467 | |||
| 468 | .spin_lock = __ticket_spin_lock, | ||
| 469 | .spin_trylock = __ticket_spin_trylock, | ||
| 470 | .spin_unlock = __ticket_spin_unlock, | ||
| 471 | #endif | ||
| 472 | }; | ||
| 473 | EXPORT_SYMBOL(pv_lock_ops); | ||
| 474 | |||
| 475 | EXPORT_SYMBOL_GPL(pv_time_ops); | 456 | EXPORT_SYMBOL_GPL(pv_time_ops); |
| 476 | EXPORT_SYMBOL (pv_cpu_ops); | 457 | EXPORT_SYMBOL (pv_cpu_ops); |
| 477 | EXPORT_SYMBOL (pv_mmu_ops); | 458 | EXPORT_SYMBOL (pv_mmu_ops); |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 205188db9626..922c14058f97 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -76,47 +76,12 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
| 76 | return ((unsigned long *)tsk->thread.sp)[3]; | 76 | return ((unsigned long *)tsk->thread.sp)[3]; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | #ifdef CONFIG_HOTPLUG_CPU | 79 | #ifndef CONFIG_SMP |
| 80 | #include <asm/nmi.h> | ||
| 81 | |||
| 82 | static void cpu_exit_clear(void) | ||
| 83 | { | ||
| 84 | int cpu = raw_smp_processor_id(); | ||
| 85 | |||
| 86 | idle_task_exit(); | ||
| 87 | |||
| 88 | cpu_uninit(); | ||
| 89 | irq_ctx_exit(cpu); | ||
| 90 | |||
| 91 | cpu_clear(cpu, cpu_callout_map); | ||
| 92 | cpu_clear(cpu, cpu_callin_map); | ||
| 93 | |||
| 94 | numa_remove_cpu(cpu); | ||
| 95 | c1e_remove_cpu(cpu); | ||
| 96 | } | ||
| 97 | |||
| 98 | /* We don't actually take CPU down, just spin without interrupts. */ | ||
| 99 | static inline void play_dead(void) | ||
| 100 | { | ||
| 101 | /* This must be done before dead CPU ack */ | ||
| 102 | cpu_exit_clear(); | ||
| 103 | mb(); | ||
| 104 | /* Ack it */ | ||
| 105 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
| 106 | |||
| 107 | /* | ||
| 108 | * With physical CPU hotplug, we should halt the cpu | ||
| 109 | */ | ||
| 110 | local_irq_disable(); | ||
| 111 | /* mask all interrupts, flush any and all caches, and halt */ | ||
| 112 | wbinvd_halt(); | ||
| 113 | } | ||
| 114 | #else | ||
| 115 | static inline void play_dead(void) | 80 | static inline void play_dead(void) |
| 116 | { | 81 | { |
| 117 | BUG(); | 82 | BUG(); |
| 118 | } | 83 | } |
| 119 | #endif /* CONFIG_HOTPLUG_CPU */ | 84 | #endif |
| 120 | 85 | ||
| 121 | /* | 86 | /* |
| 122 | * The idle thread. There's no useful work to be | 87 | * The idle thread. There's no useful work to be |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index b6b508ea7110..ca80394ef5b8 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -86,30 +86,12 @@ void exit_idle(void) | |||
| 86 | __exit_idle(); | 86 | __exit_idle(); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | #ifdef CONFIG_HOTPLUG_CPU | 89 | #ifndef CONFIG_SMP |
| 90 | DECLARE_PER_CPU(int, cpu_state); | ||
| 91 | |||
| 92 | #include <linux/nmi.h> | ||
| 93 | /* We halt the CPU with physical CPU hotplug */ | ||
| 94 | static inline void play_dead(void) | ||
| 95 | { | ||
| 96 | idle_task_exit(); | ||
| 97 | c1e_remove_cpu(raw_smp_processor_id()); | ||
| 98 | |||
| 99 | mb(); | ||
| 100 | /* Ack it */ | ||
| 101 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
| 102 | |||
| 103 | local_irq_disable(); | ||
| 104 | /* mask all interrupts, flush any and all caches, and halt */ | ||
| 105 | wbinvd_halt(); | ||
| 106 | } | ||
| 107 | #else | ||
| 108 | static inline void play_dead(void) | 90 | static inline void play_dead(void) |
| 109 | { | 91 | { |
| 110 | BUG(); | 92 | BUG(); |
| 111 | } | 93 | } |
| 112 | #endif /* CONFIG_HOTPLUG_CPU */ | 94 | #endif |
| 113 | 95 | ||
| 114 | /* | 96 | /* |
| 115 | * The idle thread. There's no useful work to be | 97 | * The idle thread. There's no useful work to be |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e375b658efc3..0a6d8c12e10d 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -40,7 +40,9 @@ enum x86_regset { | |||
| 40 | REGSET_GENERAL, | 40 | REGSET_GENERAL, |
| 41 | REGSET_FP, | 41 | REGSET_FP, |
| 42 | REGSET_XFP, | 42 | REGSET_XFP, |
| 43 | REGSET_IOPERM64 = REGSET_XFP, | ||
| 43 | REGSET_TLS, | 44 | REGSET_TLS, |
| 45 | REGSET_IOPERM32, | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | /* | 48 | /* |
| @@ -555,6 +557,29 @@ static int ptrace_set_debugreg(struct task_struct *child, | |||
| 555 | return 0; | 557 | return 0; |
| 556 | } | 558 | } |
| 557 | 559 | ||
| 560 | /* | ||
| 561 | * These access the current or another (stopped) task's io permission | ||
| 562 | * bitmap for debugging or core dump. | ||
| 563 | */ | ||
| 564 | static int ioperm_active(struct task_struct *target, | ||
| 565 | const struct user_regset *regset) | ||
| 566 | { | ||
| 567 | return target->thread.io_bitmap_max / regset->size; | ||
| 568 | } | ||
| 569 | |||
| 570 | static int ioperm_get(struct task_struct *target, | ||
| 571 | const struct user_regset *regset, | ||
| 572 | unsigned int pos, unsigned int count, | ||
| 573 | void *kbuf, void __user *ubuf) | ||
| 574 | { | ||
| 575 | if (!target->thread.io_bitmap_ptr) | ||
| 576 | return -ENXIO; | ||
| 577 | |||
| 578 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
| 579 | target->thread.io_bitmap_ptr, | ||
| 580 | 0, IO_BITMAP_BYTES); | ||
| 581 | } | ||
| 582 | |||
| 558 | #ifdef CONFIG_X86_PTRACE_BTS | 583 | #ifdef CONFIG_X86_PTRACE_BTS |
| 559 | /* | 584 | /* |
| 560 | * The configuration for a particular BTS hardware implementation. | 585 | * The configuration for a particular BTS hardware implementation. |
| @@ -1385,6 +1410,12 @@ static const struct user_regset x86_64_regsets[] = { | |||
| 1385 | .size = sizeof(long), .align = sizeof(long), | 1410 | .size = sizeof(long), .align = sizeof(long), |
| 1386 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1411 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
| 1387 | }, | 1412 | }, |
| 1413 | [REGSET_IOPERM64] = { | ||
| 1414 | .core_note_type = NT_386_IOPERM, | ||
| 1415 | .n = IO_BITMAP_LONGS, | ||
| 1416 | .size = sizeof(long), .align = sizeof(long), | ||
| 1417 | .active = ioperm_active, .get = ioperm_get | ||
| 1418 | }, | ||
| 1388 | }; | 1419 | }; |
| 1389 | 1420 | ||
| 1390 | static const struct user_regset_view user_x86_64_view = { | 1421 | static const struct user_regset_view user_x86_64_view = { |
| @@ -1431,6 +1462,12 @@ static const struct user_regset x86_32_regsets[] = { | |||
| 1431 | .active = regset_tls_active, | 1462 | .active = regset_tls_active, |
| 1432 | .get = regset_tls_get, .set = regset_tls_set | 1463 | .get = regset_tls_get, .set = regset_tls_set |
| 1433 | }, | 1464 | }, |
| 1465 | [REGSET_IOPERM32] = { | ||
| 1466 | .core_note_type = NT_386_IOPERM, | ||
| 1467 | .n = IO_BITMAP_BYTES / sizeof(u32), | ||
| 1468 | .size = sizeof(u32), .align = sizeof(u32), | ||
| 1469 | .active = ioperm_active, .get = ioperm_get | ||
| 1470 | }, | ||
| 1434 | }; | 1471 | }; |
| 1435 | 1472 | ||
| 1436 | static const struct user_regset_view user_x86_32_view = { | 1473 | static const struct user_regset_view user_x86_32_view = { |
| @@ -1452,7 +1489,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
| 1452 | #endif | 1489 | #endif |
| 1453 | } | 1490 | } |
| 1454 | 1491 | ||
| 1455 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | 1492 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
| 1493 | int error_code, int si_code) | ||
| 1456 | { | 1494 | { |
| 1457 | struct siginfo info; | 1495 | struct siginfo info; |
| 1458 | 1496 | ||
| @@ -1461,7 +1499,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | |||
| 1461 | 1499 | ||
| 1462 | memset(&info, 0, sizeof(info)); | 1500 | memset(&info, 0, sizeof(info)); |
| 1463 | info.si_signo = SIGTRAP; | 1501 | info.si_signo = SIGTRAP; |
| 1464 | info.si_code = TRAP_BRKPT; | 1502 | info.si_code = si_code; |
| 1465 | 1503 | ||
| 1466 | /* User-mode ip? */ | 1504 | /* User-mode ip? */ |
| 1467 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1505 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; |
| @@ -1548,5 +1586,5 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) | |||
| 1548 | */ | 1586 | */ |
| 1549 | if (test_thread_flag(TIF_SINGLESTEP) && | 1587 | if (test_thread_flag(TIF_SINGLESTEP) && |
| 1550 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) | 1588 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) |
| 1551 | send_sigtrap(current, regs, 0); | 1589 | send_sigtrap(current, regs, 0, TRAP_BRKPT); |
| 1552 | } | 1590 | } |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 46c98efbbf8d..21b8e0a59780 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -582,6 +582,190 @@ static struct x86_quirks default_x86_quirks __initdata; | |||
| 582 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; | 582 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; |
| 583 | 583 | ||
| 584 | /* | 584 | /* |
| 585 | * Some BIOSes seem to corrupt the low 64k of memory during events | ||
| 586 | * like suspend/resume and unplugging an HDMI cable. Reserve all | ||
| 587 | * remaining free memory in that area and fill it with a distinct | ||
| 588 | * pattern. | ||
| 589 | */ | ||
| 590 | #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION | ||
| 591 | #define MAX_SCAN_AREAS 8 | ||
| 592 | |||
| 593 | static int __read_mostly memory_corruption_check = -1; | ||
| 594 | |||
| 595 | static unsigned __read_mostly corruption_check_size = 64*1024; | ||
| 596 | static unsigned __read_mostly corruption_check_period = 60; /* seconds */ | ||
| 597 | |||
| 598 | static struct e820entry scan_areas[MAX_SCAN_AREAS]; | ||
| 599 | static int num_scan_areas; | ||
| 600 | |||
| 601 | |||
| 602 | static int set_corruption_check(char *arg) | ||
| 603 | { | ||
| 604 | char *end; | ||
| 605 | |||
| 606 | memory_corruption_check = simple_strtol(arg, &end, 10); | ||
| 607 | |||
| 608 | return (*end == 0) ? 0 : -EINVAL; | ||
| 609 | } | ||
| 610 | early_param("memory_corruption_check", set_corruption_check); | ||
| 611 | |||
| 612 | static int set_corruption_check_period(char *arg) | ||
| 613 | { | ||
| 614 | char *end; | ||
| 615 | |||
| 616 | corruption_check_period = simple_strtoul(arg, &end, 10); | ||
| 617 | |||
| 618 | return (*end == 0) ? 0 : -EINVAL; | ||
| 619 | } | ||
| 620 | early_param("memory_corruption_check_period", set_corruption_check_period); | ||
| 621 | |||
| 622 | static int set_corruption_check_size(char *arg) | ||
| 623 | { | ||
| 624 | char *end; | ||
| 625 | unsigned size; | ||
| 626 | |||
| 627 | size = memparse(arg, &end); | ||
| 628 | |||
| 629 | if (*end == '\0') | ||
| 630 | corruption_check_size = size; | ||
| 631 | |||
| 632 | return (size == corruption_check_size) ? 0 : -EINVAL; | ||
| 633 | } | ||
| 634 | early_param("memory_corruption_check_size", set_corruption_check_size); | ||
| 635 | |||
| 636 | |||
| 637 | static void __init setup_bios_corruption_check(void) | ||
| 638 | { | ||
| 639 | u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ | ||
| 640 | |||
| 641 | if (memory_corruption_check == -1) { | ||
| 642 | memory_corruption_check = | ||
| 643 | #ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK | ||
| 644 | 1 | ||
| 645 | #else | ||
| 646 | 0 | ||
| 647 | #endif | ||
| 648 | ; | ||
| 649 | } | ||
| 650 | |||
| 651 | if (corruption_check_size == 0) | ||
| 652 | memory_corruption_check = 0; | ||
| 653 | |||
| 654 | if (!memory_corruption_check) | ||
| 655 | return; | ||
| 656 | |||
| 657 | corruption_check_size = round_up(corruption_check_size, PAGE_SIZE); | ||
| 658 | |||
| 659 | while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) { | ||
| 660 | u64 size; | ||
| 661 | addr = find_e820_area_size(addr, &size, PAGE_SIZE); | ||
| 662 | |||
| 663 | if (addr == 0) | ||
| 664 | break; | ||
| 665 | |||
| 666 | if ((addr + size) > corruption_check_size) | ||
| 667 | size = corruption_check_size - addr; | ||
| 668 | |||
| 669 | if (size == 0) | ||
| 670 | break; | ||
| 671 | |||
| 672 | e820_update_range(addr, size, E820_RAM, E820_RESERVED); | ||
| 673 | scan_areas[num_scan_areas].addr = addr; | ||
| 674 | scan_areas[num_scan_areas].size = size; | ||
| 675 | num_scan_areas++; | ||
| 676 | |||
| 677 | /* Assume we've already mapped this early memory */ | ||
| 678 | memset(__va(addr), 0, size); | ||
| 679 | |||
| 680 | addr += size; | ||
| 681 | } | ||
| 682 | |||
| 683 | printk(KERN_INFO "Scanning %d areas for low memory corruption\n", | ||
| 684 | num_scan_areas); | ||
| 685 | update_e820(); | ||
| 686 | } | ||
| 687 | |||
| 688 | static struct timer_list periodic_check_timer; | ||
| 689 | |||
| 690 | void check_for_bios_corruption(void) | ||
| 691 | { | ||
| 692 | int i; | ||
| 693 | int corruption = 0; | ||
| 694 | |||
| 695 | if (!memory_corruption_check) | ||
| 696 | return; | ||
| 697 | |||
| 698 | for(i = 0; i < num_scan_areas; i++) { | ||
| 699 | unsigned long *addr = __va(scan_areas[i].addr); | ||
| 700 | unsigned long size = scan_areas[i].size; | ||
| 701 | |||
| 702 | for(; size; addr++, size -= sizeof(unsigned long)) { | ||
| 703 | if (!*addr) | ||
| 704 | continue; | ||
| 705 | printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n", | ||
| 706 | addr, __pa(addr), *addr); | ||
| 707 | corruption = 1; | ||
| 708 | *addr = 0; | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n"); | ||
| 713 | } | ||
| 714 | |||
| 715 | static void periodic_check_for_corruption(unsigned long data) | ||
| 716 | { | ||
| 717 | check_for_bios_corruption(); | ||
| 718 | mod_timer(&periodic_check_timer, round_jiffies(jiffies + corruption_check_period*HZ)); | ||
| 719 | } | ||
| 720 | |||
| 721 | void start_periodic_check_for_corruption(void) | ||
| 722 | { | ||
| 723 | if (!memory_corruption_check || corruption_check_period == 0) | ||
| 724 | return; | ||
| 725 | |||
| 726 | printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", | ||
| 727 | corruption_check_period); | ||
| 728 | |||
| 729 | init_timer(&periodic_check_timer); | ||
| 730 | periodic_check_timer.function = &periodic_check_for_corruption; | ||
| 731 | periodic_check_for_corruption(0); | ||
| 732 | } | ||
| 733 | #endif | ||
| 734 | |||
| 735 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) | ||
| 736 | { | ||
| 737 | printk(KERN_NOTICE | ||
| 738 | "%s detected: BIOS may corrupt low RAM, working it around.\n", | ||
| 739 | d->ident); | ||
| 740 | |||
| 741 | e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED); | ||
| 742 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
| 743 | |||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | |||
| 747 | /* List of systems that have known low memory corruption BIOS problems */ | ||
| 748 | static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | ||
| 749 | #ifdef CONFIG_X86_RESERVE_LOW_64K | ||
| 750 | { | ||
| 751 | .callback = dmi_low_memory_corruption, | ||
| 752 | .ident = "AMI BIOS", | ||
| 753 | .matches = { | ||
| 754 | DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), | ||
| 755 | }, | ||
| 756 | }, | ||
| 757 | { | ||
| 758 | .callback = dmi_low_memory_corruption, | ||
| 759 | .ident = "Phoenix BIOS", | ||
| 760 | .matches = { | ||
| 761 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), | ||
| 762 | }, | ||
| 763 | }, | ||
| 764 | #endif | ||
| 765 | {} | ||
| 766 | }; | ||
| 767 | |||
| 768 | /* | ||
| 585 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 769 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
| 586 | * passed the efi memmap, systab, etc., so we should use these data structures | 770 | * passed the efi memmap, systab, etc., so we should use these data structures |
| 587 | * for initialization. Note, the efi init code path is determined by the | 771 | * for initialization. Note, the efi init code path is determined by the |
| @@ -715,6 +899,10 @@ void __init setup_arch(char **cmdline_p) | |||
| 715 | 899 | ||
| 716 | finish_e820_parsing(); | 900 | finish_e820_parsing(); |
| 717 | 901 | ||
| 902 | dmi_scan_machine(); | ||
| 903 | |||
| 904 | dmi_check_system(bad_bios_dmi_table); | ||
| 905 | |||
| 718 | #ifdef CONFIG_X86_32 | 906 | #ifdef CONFIG_X86_32 |
| 719 | probe_roms(); | 907 | probe_roms(); |
| 720 | #endif | 908 | #endif |
| @@ -771,6 +959,10 @@ void __init setup_arch(char **cmdline_p) | |||
| 771 | high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; | 959 | high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; |
| 772 | #endif | 960 | #endif |
| 773 | 961 | ||
| 962 | #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION | ||
| 963 | setup_bios_corruption_check(); | ||
| 964 | #endif | ||
| 965 | |||
| 774 | /* max_pfn_mapped is updated here */ | 966 | /* max_pfn_mapped is updated here */ |
| 775 | max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); | 967 | max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); |
| 776 | max_pfn_mapped = max_low_pfn_mapped; | 968 | max_pfn_mapped = max_low_pfn_mapped; |
| @@ -799,8 +991,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 799 | vsmp_init(); | 991 | vsmp_init(); |
| 800 | #endif | 992 | #endif |
| 801 | 993 | ||
| 802 | dmi_scan_machine(); | ||
| 803 | |||
| 804 | io_delay_init(); | 994 | io_delay_init(); |
| 805 | 995 | ||
| 806 | /* | 996 | /* |
| @@ -903,3 +1093,5 @@ void __init setup_arch(char **cmdline_p) | |||
| 903 | #endif | 1093 | #endif |
| 904 | #endif | 1094 | #endif |
| 905 | } | 1095 | } |
| 1096 | |||
| 1097 | |||
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b21070ea33a4..d6dd057d0f22 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 28 | #include <asm/i387.h> | 28 | #include <asm/i387.h> |
| 29 | #include <asm/vdso.h> | 29 | #include <asm/vdso.h> |
| 30 | #include <asm/syscall.h> | ||
| 30 | #include <asm/syscalls.h> | 31 | #include <asm/syscalls.h> |
| 31 | 32 | ||
| 32 | #include "sigframe.h" | 33 | #include "sigframe.h" |
| @@ -112,6 +113,27 @@ asmlinkage int sys_sigaltstack(unsigned long bx) | |||
| 112 | return do_sigaltstack(uss, uoss, regs->sp); | 113 | return do_sigaltstack(uss, uoss, regs->sp); |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 116 | #define COPY(x) { \ | ||
| 117 | err |= __get_user(regs->x, &sc->x); \ | ||
| 118 | } | ||
| 119 | |||
| 120 | #define COPY_SEG(seg) { \ | ||
| 121 | unsigned short tmp; \ | ||
| 122 | err |= __get_user(tmp, &sc->seg); \ | ||
| 123 | regs->seg = tmp; \ | ||
| 124 | } | ||
| 125 | |||
| 126 | #define COPY_SEG_STRICT(seg) { \ | ||
| 127 | unsigned short tmp; \ | ||
| 128 | err |= __get_user(tmp, &sc->seg); \ | ||
| 129 | regs->seg = tmp | 3; \ | ||
| 130 | } | ||
| 131 | |||
| 132 | #define GET_SEG(seg) { \ | ||
| 133 | unsigned short tmp; \ | ||
| 134 | err |= __get_user(tmp, &sc->seg); \ | ||
| 135 | loadsegment(seg, tmp); \ | ||
| 136 | } | ||
| 115 | 137 | ||
| 116 | /* | 138 | /* |
| 117 | * Do a signal return; undo the signal stack. | 139 | * Do a signal return; undo the signal stack. |
| @@ -120,28 +142,13 @@ static int | |||
| 120 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | 142 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, |
| 121 | unsigned long *pax) | 143 | unsigned long *pax) |
| 122 | { | 144 | { |
| 145 | void __user *buf; | ||
| 146 | unsigned int tmpflags; | ||
| 123 | unsigned int err = 0; | 147 | unsigned int err = 0; |
| 124 | 148 | ||
| 125 | /* Always make any pending restarted system calls return -EINTR */ | 149 | /* Always make any pending restarted system calls return -EINTR */ |
| 126 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 150 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 127 | 151 | ||
| 128 | #define COPY(x) err |= __get_user(regs->x, &sc->x) | ||
| 129 | |||
| 130 | #define COPY_SEG(seg) \ | ||
| 131 | { unsigned short tmp; \ | ||
| 132 | err |= __get_user(tmp, &sc->seg); \ | ||
| 133 | regs->seg = tmp; } | ||
| 134 | |||
| 135 | #define COPY_SEG_STRICT(seg) \ | ||
| 136 | { unsigned short tmp; \ | ||
| 137 | err |= __get_user(tmp, &sc->seg); \ | ||
| 138 | regs->seg = tmp|3; } | ||
| 139 | |||
| 140 | #define GET_SEG(seg) \ | ||
| 141 | { unsigned short tmp; \ | ||
| 142 | err |= __get_user(tmp, &sc->seg); \ | ||
| 143 | loadsegment(seg, tmp); } | ||
| 144 | |||
| 145 | GET_SEG(gs); | 152 | GET_SEG(gs); |
| 146 | COPY_SEG(fs); | 153 | COPY_SEG(fs); |
| 147 | COPY_SEG(es); | 154 | COPY_SEG(es); |
| @@ -151,21 +158,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 151 | COPY_SEG_STRICT(cs); | 158 | COPY_SEG_STRICT(cs); |
| 152 | COPY_SEG_STRICT(ss); | 159 | COPY_SEG_STRICT(ss); |
| 153 | 160 | ||
| 154 | { | 161 | err |= __get_user(tmpflags, &sc->flags); |
| 155 | unsigned int tmpflags; | 162 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
| 156 | 163 | regs->orig_ax = -1; /* disable syscall checks */ | |
| 157 | err |= __get_user(tmpflags, &sc->flags); | ||
| 158 | regs->flags = (regs->flags & ~FIX_EFLAGS) | | ||
| 159 | (tmpflags & FIX_EFLAGS); | ||
| 160 | regs->orig_ax = -1; /* disable syscall checks */ | ||
| 161 | } | ||
| 162 | |||
| 163 | { | ||
| 164 | void __user *buf; | ||
| 165 | 164 | ||
| 166 | err |= __get_user(buf, &sc->fpstate); | 165 | err |= __get_user(buf, &sc->fpstate); |
| 167 | err |= restore_i387_xstate(buf); | 166 | err |= restore_i387_xstate(buf); |
| 168 | } | ||
| 169 | 167 | ||
| 170 | err |= __get_user(*pax, &sc->ax); | 168 | err |= __get_user(*pax, &sc->ax); |
| 171 | return err; | 169 | return err; |
| @@ -214,9 +212,8 @@ badframe: | |||
| 214 | return 0; | 212 | return 0; |
| 215 | } | 213 | } |
| 216 | 214 | ||
| 217 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | 215 | static long do_rt_sigreturn(struct pt_regs *regs) |
| 218 | { | 216 | { |
| 219 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
| 220 | struct rt_sigframe __user *frame; | 217 | struct rt_sigframe __user *frame; |
| 221 | unsigned long ax; | 218 | unsigned long ax; |
| 222 | sigset_t set; | 219 | sigset_t set; |
| @@ -242,10 +239,17 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) | |||
| 242 | return ax; | 239 | return ax; |
| 243 | 240 | ||
| 244 | badframe: | 241 | badframe: |
| 245 | force_sig(SIGSEGV, current); | 242 | signal_fault(regs, frame, "rt_sigreturn"); |
| 246 | return 0; | 243 | return 0; |
| 247 | } | 244 | } |
| 248 | 245 | ||
| 246 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
| 247 | { | ||
| 248 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
| 249 | |||
| 250 | return do_rt_sigreturn(regs); | ||
| 251 | } | ||
| 252 | |||
| 249 | /* | 253 | /* |
| 250 | * Set up a signal frame. | 254 | * Set up a signal frame. |
| 251 | */ | 255 | */ |
| @@ -337,39 +341,29 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
| 337 | } | 341 | } |
| 338 | 342 | ||
| 339 | static int | 343 | static int |
| 340 | setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 344 | __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
| 341 | struct pt_regs *regs) | 345 | struct pt_regs *regs) |
| 342 | { | 346 | { |
| 343 | struct sigframe __user *frame; | 347 | struct sigframe __user *frame; |
| 344 | void __user *restorer; | 348 | void __user *restorer; |
| 345 | int err = 0; | 349 | int err = 0; |
| 346 | int usig; | ||
| 347 | void __user *fpstate = NULL; | 350 | void __user *fpstate = NULL; |
| 348 | 351 | ||
| 349 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 352 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 350 | 353 | ||
| 351 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 354 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 352 | goto give_sigsegv; | 355 | return -EFAULT; |
| 353 | 356 | ||
| 354 | usig = current_thread_info()->exec_domain | 357 | if (__put_user(sig, &frame->sig)) |
| 355 | && current_thread_info()->exec_domain->signal_invmap | 358 | return -EFAULT; |
| 356 | && sig < 32 | ||
| 357 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 358 | : sig; | ||
| 359 | 359 | ||
| 360 | err = __put_user(usig, &frame->sig); | 360 | if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
| 361 | if (err) | 361 | return -EFAULT; |
| 362 | goto give_sigsegv; | ||
| 363 | |||
| 364 | err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); | ||
| 365 | if (err) | ||
| 366 | goto give_sigsegv; | ||
| 367 | 362 | ||
| 368 | if (_NSIG_WORDS > 1) { | 363 | if (_NSIG_WORDS > 1) { |
| 369 | err = __copy_to_user(&frame->extramask, &set->sig[1], | 364 | if (__copy_to_user(&frame->extramask, &set->sig[1], |
| 370 | sizeof(frame->extramask)); | 365 | sizeof(frame->extramask))) |
| 371 | if (err) | 366 | return -EFAULT; |
| 372 | goto give_sigsegv; | ||
| 373 | } | 367 | } |
| 374 | 368 | ||
| 375 | if (current->mm->context.vdso) | 369 | if (current->mm->context.vdso) |
| @@ -394,7 +388,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
| 394 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 388 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
| 395 | 389 | ||
| 396 | if (err) | 390 | if (err) |
| 397 | goto give_sigsegv; | 391 | return -EFAULT; |
| 398 | 392 | ||
| 399 | /* Set up registers for signal handler */ | 393 | /* Set up registers for signal handler */ |
| 400 | regs->sp = (unsigned long)frame; | 394 | regs->sp = (unsigned long)frame; |
| @@ -409,38 +403,27 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
| 409 | regs->cs = __USER_CS; | 403 | regs->cs = __USER_CS; |
| 410 | 404 | ||
| 411 | return 0; | 405 | return 0; |
| 412 | |||
| 413 | give_sigsegv: | ||
| 414 | force_sigsegv(sig, current); | ||
| 415 | return -EFAULT; | ||
| 416 | } | 406 | } |
| 417 | 407 | ||
| 418 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 408 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 419 | sigset_t *set, struct pt_regs *regs) | 409 | sigset_t *set, struct pt_regs *regs) |
| 420 | { | 410 | { |
| 421 | struct rt_sigframe __user *frame; | 411 | struct rt_sigframe __user *frame; |
| 422 | void __user *restorer; | 412 | void __user *restorer; |
| 423 | int err = 0; | 413 | int err = 0; |
| 424 | int usig; | ||
| 425 | void __user *fpstate = NULL; | 414 | void __user *fpstate = NULL; |
| 426 | 415 | ||
| 427 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 416 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 428 | 417 | ||
| 429 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 418 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 430 | goto give_sigsegv; | 419 | return -EFAULT; |
| 431 | |||
| 432 | usig = current_thread_info()->exec_domain | ||
| 433 | && current_thread_info()->exec_domain->signal_invmap | ||
| 434 | && sig < 32 | ||
| 435 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 436 | : sig; | ||
| 437 | 420 | ||
| 438 | err |= __put_user(usig, &frame->sig); | 421 | err |= __put_user(sig, &frame->sig); |
| 439 | err |= __put_user(&frame->info, &frame->pinfo); | 422 | err |= __put_user(&frame->info, &frame->pinfo); |
| 440 | err |= __put_user(&frame->uc, &frame->puc); | 423 | err |= __put_user(&frame->uc, &frame->puc); |
| 441 | err |= copy_siginfo_to_user(&frame->info, info); | 424 | err |= copy_siginfo_to_user(&frame->info, info); |
| 442 | if (err) | 425 | if (err) |
| 443 | goto give_sigsegv; | 426 | return -EFAULT; |
| 444 | 427 | ||
| 445 | /* Create the ucontext. */ | 428 | /* Create the ucontext. */ |
| 446 | if (cpu_has_xsave) | 429 | if (cpu_has_xsave) |
| @@ -456,7 +439,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 456 | regs, set->sig[0]); | 439 | regs, set->sig[0]); |
| 457 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 440 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 458 | if (err) | 441 | if (err) |
| 459 | goto give_sigsegv; | 442 | return -EFAULT; |
| 460 | 443 | ||
| 461 | /* Set up to return from userspace. */ | 444 | /* Set up to return from userspace. */ |
| 462 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 445 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
| @@ -476,12 +459,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 476 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 459 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
| 477 | 460 | ||
| 478 | if (err) | 461 | if (err) |
| 479 | goto give_sigsegv; | 462 | return -EFAULT; |
| 480 | 463 | ||
| 481 | /* Set up registers for signal handler */ | 464 | /* Set up registers for signal handler */ |
| 482 | regs->sp = (unsigned long)frame; | 465 | regs->sp = (unsigned long)frame; |
| 483 | regs->ip = (unsigned long)ka->sa.sa_handler; | 466 | regs->ip = (unsigned long)ka->sa.sa_handler; |
| 484 | regs->ax = (unsigned long)usig; | 467 | regs->ax = (unsigned long)sig; |
| 485 | regs->dx = (unsigned long)&frame->info; | 468 | regs->dx = (unsigned long)&frame->info; |
| 486 | regs->cx = (unsigned long)&frame->uc; | 469 | regs->cx = (unsigned long)&frame->uc; |
| 487 | 470 | ||
| @@ -491,15 +474,48 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 491 | regs->cs = __USER_CS; | 474 | regs->cs = __USER_CS; |
| 492 | 475 | ||
| 493 | return 0; | 476 | return 0; |
| 494 | |||
| 495 | give_sigsegv: | ||
| 496 | force_sigsegv(sig, current); | ||
| 497 | return -EFAULT; | ||
| 498 | } | 477 | } |
| 499 | 478 | ||
| 500 | /* | 479 | /* |
| 501 | * OK, we're invoking a handler: | 480 | * OK, we're invoking a handler: |
| 502 | */ | 481 | */ |
| 482 | static int signr_convert(int sig) | ||
| 483 | { | ||
| 484 | struct thread_info *info = current_thread_info(); | ||
| 485 | |||
| 486 | if (info->exec_domain && info->exec_domain->signal_invmap && sig < 32) | ||
| 487 | return info->exec_domain->signal_invmap[sig]; | ||
| 488 | return sig; | ||
| 489 | } | ||
| 490 | |||
| 491 | #define is_ia32 1 | ||
| 492 | #define ia32_setup_frame __setup_frame | ||
| 493 | #define ia32_setup_rt_frame __setup_rt_frame | ||
| 494 | |||
| 495 | static int | ||
| 496 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
| 497 | sigset_t *set, struct pt_regs *regs) | ||
| 498 | { | ||
| 499 | int usig = signr_convert(sig); | ||
| 500 | int ret; | ||
| 501 | |||
| 502 | /* Set up the stack frame */ | ||
| 503 | if (is_ia32) { | ||
| 504 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 505 | ret = ia32_setup_rt_frame(usig, ka, info, set, regs); | ||
| 506 | else | ||
| 507 | ret = ia32_setup_frame(usig, ka, set, regs); | ||
| 508 | } else | ||
| 509 | ret = __setup_rt_frame(sig, ka, info, set, regs); | ||
| 510 | |||
| 511 | if (ret) { | ||
| 512 | force_sigsegv(sig, current); | ||
| 513 | return -EFAULT; | ||
| 514 | } | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | ||
| 518 | |||
| 503 | static int | 519 | static int |
| 504 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 520 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
| 505 | sigset_t *oldset, struct pt_regs *regs) | 521 | sigset_t *oldset, struct pt_regs *regs) |
| @@ -507,9 +523,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 507 | int ret; | 523 | int ret; |
| 508 | 524 | ||
| 509 | /* Are we from a system call? */ | 525 | /* Are we from a system call? */ |
| 510 | if ((long)regs->orig_ax >= 0) { | 526 | if (syscall_get_nr(current, regs) >= 0) { |
| 511 | /* If so, check system call restarting.. */ | 527 | /* If so, check system call restarting.. */ |
| 512 | switch (regs->ax) { | 528 | switch (syscall_get_error(current, regs)) { |
| 513 | case -ERESTART_RESTARTBLOCK: | 529 | case -ERESTART_RESTARTBLOCK: |
| 514 | case -ERESTARTNOHAND: | 530 | case -ERESTARTNOHAND: |
| 515 | regs->ax = -EINTR; | 531 | regs->ax = -EINTR; |
| @@ -536,15 +552,20 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 536 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 552 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
| 537 | regs->flags &= ~X86_EFLAGS_TF; | 553 | regs->flags &= ~X86_EFLAGS_TF; |
| 538 | 554 | ||
| 539 | /* Set up the stack frame */ | 555 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
| 540 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 541 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||
| 542 | else | ||
| 543 | ret = setup_frame(sig, ka, oldset, regs); | ||
| 544 | 556 | ||
| 545 | if (ret) | 557 | if (ret) |
| 546 | return ret; | 558 | return ret; |
| 547 | 559 | ||
| 560 | #ifdef CONFIG_X86_64 | ||
| 561 | /* | ||
| 562 | * This has nothing to do with segment registers, | ||
| 563 | * despite the name. This magic affects uaccess.h | ||
| 564 | * macros' behavior. Reset it to the normal setting. | ||
| 565 | */ | ||
| 566 | set_fs(USER_DS); | ||
| 567 | #endif | ||
| 568 | |||
| 548 | /* | 569 | /* |
| 549 | * Clear the direction flag as per the ABI for function entry. | 570 | * Clear the direction flag as per the ABI for function entry. |
| 550 | */ | 571 | */ |
| @@ -571,6 +592,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 571 | return 0; | 592 | return 0; |
| 572 | } | 593 | } |
| 573 | 594 | ||
| 595 | #define NR_restart_syscall __NR_restart_syscall | ||
| 574 | /* | 596 | /* |
| 575 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 597 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
| 576 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 598 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| @@ -623,9 +645,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 623 | } | 645 | } |
| 624 | 646 | ||
| 625 | /* Did we come from a system call? */ | 647 | /* Did we come from a system call? */ |
| 626 | if ((long)regs->orig_ax >= 0) { | 648 | if (syscall_get_nr(current, regs) >= 0) { |
| 627 | /* Restart the system call - no handlers present */ | 649 | /* Restart the system call - no handlers present */ |
| 628 | switch (regs->ax) { | 650 | switch (syscall_get_error(current, regs)) { |
| 629 | case -ERESTARTNOHAND: | 651 | case -ERESTARTNOHAND: |
| 630 | case -ERESTARTSYS: | 652 | case -ERESTARTSYS: |
| 631 | case -ERESTARTNOINTR: | 653 | case -ERESTARTNOINTR: |
| @@ -634,7 +656,7 @@ static void do_signal(struct pt_regs *regs) | |||
| 634 | break; | 656 | break; |
| 635 | 657 | ||
| 636 | case -ERESTART_RESTARTBLOCK: | 658 | case -ERESTART_RESTARTBLOCK: |
| 637 | regs->ax = __NR_restart_syscall; | 659 | regs->ax = NR_restart_syscall; |
| 638 | regs->ip -= 2; | 660 | regs->ip -= 2; |
| 639 | break; | 661 | break; |
| 640 | } | 662 | } |
| @@ -657,6 +679,12 @@ static void do_signal(struct pt_regs *regs) | |||
| 657 | void | 679 | void |
| 658 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | 680 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) |
| 659 | { | 681 | { |
| 682 | #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) | ||
| 683 | /* notify userspace of pending MCEs */ | ||
| 684 | if (thread_info_flags & _TIF_MCE_NOTIFY) | ||
| 685 | mce_notify_user(); | ||
| 686 | #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ | ||
| 687 | |||
| 660 | /* deal with pending signal delivery */ | 688 | /* deal with pending signal delivery */ |
| 661 | if (thread_info_flags & _TIF_SIGPENDING) | 689 | if (thread_info_flags & _TIF_SIGPENDING) |
| 662 | do_signal(regs); | 690 | do_signal(regs); |
| @@ -666,5 +694,23 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
| 666 | tracehook_notify_resume(regs); | 694 | tracehook_notify_resume(regs); |
| 667 | } | 695 | } |
| 668 | 696 | ||
| 697 | #ifdef CONFIG_X86_32 | ||
| 669 | clear_thread_flag(TIF_IRET); | 698 | clear_thread_flag(TIF_IRET); |
| 699 | #endif /* CONFIG_X86_32 */ | ||
| 700 | } | ||
| 701 | |||
| 702 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | ||
| 703 | { | ||
| 704 | struct task_struct *me = current; | ||
| 705 | |||
| 706 | if (show_unhandled_signals && printk_ratelimit()) { | ||
| 707 | printk(KERN_INFO | ||
| 708 | "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | ||
| 709 | me->comm, me->pid, where, frame, | ||
| 710 | regs->ip, regs->sp, regs->orig_ax); | ||
| 711 | print_vma_addr(" in ", regs->ip); | ||
| 712 | printk(KERN_CONT "\n"); | ||
| 713 | } | ||
| 714 | |||
| 715 | force_sig(SIGSEGV, me); | ||
| 670 | } | 716 | } |
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 823a55bf8c39..a5c9627f4db9 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
| @@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
| 52 | return do_sigaltstack(uss, uoss, regs->sp); | 52 | return do_sigaltstack(uss, uoss, regs->sp); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #define COPY(x) { \ | ||
| 56 | err |= __get_user(regs->x, &sc->x); \ | ||
| 57 | } | ||
| 58 | |||
| 59 | #define COPY_SEG_STRICT(seg) { \ | ||
| 60 | unsigned short tmp; \ | ||
| 61 | err |= __get_user(tmp, &sc->seg); \ | ||
| 62 | regs->seg = tmp | 3; \ | ||
| 63 | } | ||
| 64 | |||
| 55 | /* | 65 | /* |
| 56 | * Do a signal return; undo the signal stack. | 66 | * Do a signal return; undo the signal stack. |
| 57 | */ | 67 | */ |
| @@ -59,13 +69,13 @@ static int | |||
| 59 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | 69 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, |
| 60 | unsigned long *pax) | 70 | unsigned long *pax) |
| 61 | { | 71 | { |
| 72 | void __user *buf; | ||
| 73 | unsigned int tmpflags; | ||
| 62 | unsigned int err = 0; | 74 | unsigned int err = 0; |
| 63 | 75 | ||
| 64 | /* Always make any pending restarted system calls return -EINTR */ | 76 | /* Always make any pending restarted system calls return -EINTR */ |
| 65 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 77 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 66 | 78 | ||
| 67 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) | ||
| 68 | |||
| 69 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 79 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
| 70 | COPY(dx); COPY(cx); COPY(ip); | 80 | COPY(dx); COPY(cx); COPY(ip); |
| 71 | COPY(r8); | 81 | COPY(r8); |
| @@ -80,34 +90,24 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 80 | /* Kernel saves and restores only the CS segment register on signals, | 90 | /* Kernel saves and restores only the CS segment register on signals, |
| 81 | * which is the bare minimum needed to allow mixed 32/64-bit code. | 91 | * which is the bare minimum needed to allow mixed 32/64-bit code. |
| 82 | * App's signal handler can save/restore other segments if needed. */ | 92 | * App's signal handler can save/restore other segments if needed. */ |
| 83 | { | 93 | COPY_SEG_STRICT(cs); |
| 84 | unsigned cs; | ||
| 85 | err |= __get_user(cs, &sc->cs); | ||
| 86 | regs->cs = cs | 3; /* Force into user mode */ | ||
| 87 | } | ||
| 88 | 94 | ||
| 89 | { | 95 | err |= __get_user(tmpflags, &sc->flags); |
| 90 | unsigned int tmpflags; | 96 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
| 91 | err |= __get_user(tmpflags, &sc->flags); | 97 | regs->orig_ax = -1; /* disable syscall checks */ |
| 92 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | ||
| 93 | regs->orig_ax = -1; /* disable syscall checks */ | ||
| 94 | } | ||
| 95 | 98 | ||
| 96 | { | 99 | err |= __get_user(buf, &sc->fpstate); |
| 97 | struct _fpstate __user *buf; | 100 | err |= restore_i387_xstate(buf); |
| 98 | err |= __get_user(buf, &sc->fpstate); | ||
| 99 | err |= restore_i387_xstate(buf); | ||
| 100 | } | ||
| 101 | 101 | ||
| 102 | err |= __get_user(*pax, &sc->ax); | 102 | err |= __get_user(*pax, &sc->ax); |
| 103 | return err; | 103 | return err; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 106 | static long do_rt_sigreturn(struct pt_regs *regs) |
| 107 | { | 107 | { |
| 108 | struct rt_sigframe __user *frame; | 108 | struct rt_sigframe __user *frame; |
| 109 | sigset_t set; | ||
| 110 | unsigned long ax; | 109 | unsigned long ax; |
| 110 | sigset_t set; | ||
| 111 | 111 | ||
| 112 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | 112 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); |
| 113 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 113 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -130,10 +130,15 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
| 130 | return ax; | 130 | return ax; |
| 131 | 131 | ||
| 132 | badframe: | 132 | badframe: |
| 133 | signal_fault(regs, frame, "sigreturn"); | 133 | signal_fault(regs, frame, "rt_sigreturn"); |
| 134 | return 0; | 134 | return 0; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
| 138 | { | ||
| 139 | return do_rt_sigreturn(regs); | ||
| 140 | } | ||
| 141 | |||
| 137 | /* | 142 | /* |
| 138 | * Set up a signal frame. | 143 | * Set up a signal frame. |
| 139 | */ | 144 | */ |
| @@ -195,8 +200,8 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
| 195 | return (void __user *)round_down(sp - size, 64); | 200 | return (void __user *)round_down(sp - size, 64); |
| 196 | } | 201 | } |
| 197 | 202 | ||
| 198 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 203 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 199 | sigset_t *set, struct pt_regs *regs) | 204 | sigset_t *set, struct pt_regs *regs) |
| 200 | { | 205 | { |
| 201 | struct rt_sigframe __user *frame; | 206 | struct rt_sigframe __user *frame; |
| 202 | void __user *fp = NULL; | 207 | void __user *fp = NULL; |
| @@ -209,17 +214,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 209 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 214 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
| 210 | 215 | ||
| 211 | if (save_i387_xstate(fp) < 0) | 216 | if (save_i387_xstate(fp) < 0) |
| 212 | err |= -1; | 217 | return -EFAULT; |
| 213 | } else | 218 | } else |
| 214 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 219 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
| 215 | 220 | ||
| 216 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 221 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 217 | goto give_sigsegv; | 222 | return -EFAULT; |
| 218 | 223 | ||
| 219 | if (ka->sa.sa_flags & SA_SIGINFO) { | 224 | if (ka->sa.sa_flags & SA_SIGINFO) { |
| 220 | err |= copy_siginfo_to_user(&frame->info, info); | 225 | if (copy_siginfo_to_user(&frame->info, info)) |
| 221 | if (err) | 226 | return -EFAULT; |
| 222 | goto give_sigsegv; | ||
| 223 | } | 227 | } |
| 224 | 228 | ||
| 225 | /* Create the ucontext. */ | 229 | /* Create the ucontext. */ |
| @@ -247,11 +251,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 247 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 251 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 248 | } else { | 252 | } else { |
| 249 | /* could use a vstub here */ | 253 | /* could use a vstub here */ |
| 250 | goto give_sigsegv; | 254 | return -EFAULT; |
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | if (err) | 257 | if (err) |
| 254 | goto give_sigsegv; | 258 | return -EFAULT; |
| 255 | 259 | ||
| 256 | /* Set up registers for signal handler */ | 260 | /* Set up registers for signal handler */ |
| 257 | regs->di = sig; | 261 | regs->di = sig; |
| @@ -271,15 +275,45 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 271 | regs->cs = __USER_CS; | 275 | regs->cs = __USER_CS; |
| 272 | 276 | ||
| 273 | return 0; | 277 | return 0; |
| 274 | |||
| 275 | give_sigsegv: | ||
| 276 | force_sigsegv(sig, current); | ||
| 277 | return -EFAULT; | ||
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | /* | 280 | /* |
| 281 | * OK, we're invoking a handler | 281 | * OK, we're invoking a handler |
| 282 | */ | 282 | */ |
| 283 | static int signr_convert(int sig) | ||
| 284 | { | ||
| 285 | return sig; | ||
| 286 | } | ||
| 287 | |||
| 288 | #ifdef CONFIG_IA32_EMULATION | ||
| 289 | #define is_ia32 test_thread_flag(TIF_IA32) | ||
| 290 | #else | ||
| 291 | #define is_ia32 0 | ||
| 292 | #endif | ||
| 293 | |||
| 294 | static int | ||
| 295 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
| 296 | sigset_t *set, struct pt_regs *regs) | ||
| 297 | { | ||
| 298 | int usig = signr_convert(sig); | ||
| 299 | int ret; | ||
| 300 | |||
| 301 | /* Set up the stack frame */ | ||
| 302 | if (is_ia32) { | ||
| 303 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 304 | ret = ia32_setup_rt_frame(usig, ka, info, set, regs); | ||
| 305 | else | ||
| 306 | ret = ia32_setup_frame(usig, ka, set, regs); | ||
| 307 | } else | ||
| 308 | ret = __setup_rt_frame(sig, ka, info, set, regs); | ||
| 309 | |||
| 310 | if (ret) { | ||
| 311 | force_sigsegv(sig, current); | ||
| 312 | return -EFAULT; | ||
| 313 | } | ||
| 314 | |||
| 315 | return ret; | ||
| 316 | } | ||
| 283 | 317 | ||
| 284 | static int | 318 | static int |
| 285 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 319 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
| @@ -317,51 +351,48 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 317 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 351 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
| 318 | regs->flags &= ~X86_EFLAGS_TF; | 352 | regs->flags &= ~X86_EFLAGS_TF; |
| 319 | 353 | ||
| 320 | #ifdef CONFIG_IA32_EMULATION | ||
| 321 | if (test_thread_flag(TIF_IA32)) { | ||
| 322 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 323 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | ||
| 324 | else | ||
| 325 | ret = ia32_setup_frame(sig, ka, oldset, regs); | ||
| 326 | } else | ||
| 327 | #endif | ||
| 328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 354 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
| 329 | 355 | ||
| 330 | if (ret == 0) { | 356 | if (ret) |
| 331 | /* | 357 | return ret; |
| 332 | * This has nothing to do with segment registers, | ||
| 333 | * despite the name. This magic affects uaccess.h | ||
| 334 | * macros' behavior. Reset it to the normal setting. | ||
| 335 | */ | ||
| 336 | set_fs(USER_DS); | ||
| 337 | 358 | ||
| 338 | /* | 359 | #ifdef CONFIG_X86_64 |
| 339 | * Clear the direction flag as per the ABI for function entry. | 360 | /* |
| 340 | */ | 361 | * This has nothing to do with segment registers, |
| 341 | regs->flags &= ~X86_EFLAGS_DF; | 362 | * despite the name. This magic affects uaccess.h |
| 363 | * macros' behavior. Reset it to the normal setting. | ||
| 364 | */ | ||
| 365 | set_fs(USER_DS); | ||
| 366 | #endif | ||
| 342 | 367 | ||
| 343 | /* | 368 | /* |
| 344 | * Clear TF when entering the signal handler, but | 369 | * Clear the direction flag as per the ABI for function entry. |
| 345 | * notify any tracer that was single-stepping it. | 370 | */ |
| 346 | * The tracer may want to single-step inside the | 371 | regs->flags &= ~X86_EFLAGS_DF; |
| 347 | * handler too. | ||
| 348 | */ | ||
| 349 | regs->flags &= ~X86_EFLAGS_TF; | ||
| 350 | 372 | ||
| 351 | spin_lock_irq(¤t->sighand->siglock); | 373 | /* |
| 352 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 374 | * Clear TF when entering the signal handler, but |
| 353 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 375 | * notify any tracer that was single-stepping it. |
| 354 | sigaddset(¤t->blocked, sig); | 376 | * The tracer may want to single-step inside the |
| 355 | recalc_sigpending(); | 377 | * handler too. |
| 356 | spin_unlock_irq(¤t->sighand->siglock); | 378 | */ |
| 379 | regs->flags &= ~X86_EFLAGS_TF; | ||
| 357 | 380 | ||
| 358 | tracehook_signal_handler(sig, info, ka, regs, | 381 | spin_lock_irq(¤t->sighand->siglock); |
| 359 | test_thread_flag(TIF_SINGLESTEP)); | 382 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
| 360 | } | 383 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
| 384 | sigaddset(¤t->blocked, sig); | ||
| 385 | recalc_sigpending(); | ||
| 386 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 361 | 387 | ||
| 362 | return ret; | 388 | tracehook_signal_handler(sig, info, ka, regs, |
| 389 | test_thread_flag(TIF_SINGLESTEP)); | ||
| 390 | |||
| 391 | return 0; | ||
| 363 | } | 392 | } |
| 364 | 393 | ||
| 394 | #define NR_restart_syscall \ | ||
| 395 | test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall | ||
| 365 | /* | 396 | /* |
| 366 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 397 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
| 367 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 398 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| @@ -391,7 +422,8 @@ static void do_signal(struct pt_regs *regs) | |||
| 391 | 422 | ||
| 392 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 423 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 393 | if (signr > 0) { | 424 | if (signr > 0) { |
| 394 | /* Re-enable any watchpoints before delivering the | 425 | /* |
| 426 | * Re-enable any watchpoints before delivering the | ||
| 395 | * signal to user space. The processor register will | 427 | * signal to user space. The processor register will |
| 396 | * have been cleared if the watchpoint triggered | 428 | * have been cleared if the watchpoint triggered |
| 397 | * inside the kernel. | 429 | * inside the kernel. |
| @@ -399,7 +431,7 @@ static void do_signal(struct pt_regs *regs) | |||
| 399 | if (current->thread.debugreg7) | 431 | if (current->thread.debugreg7) |
| 400 | set_debugreg(current->thread.debugreg7, 7); | 432 | set_debugreg(current->thread.debugreg7, 7); |
| 401 | 433 | ||
| 402 | /* Whee! Actually deliver the signal. */ | 434 | /* Whee! Actually deliver the signal. */ |
| 403 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 435 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
| 404 | /* | 436 | /* |
| 405 | * A signal was successfully delivered; the saved | 437 | * A signal was successfully delivered; the saved |
| @@ -422,10 +454,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 422 | regs->ax = regs->orig_ax; | 454 | regs->ax = regs->orig_ax; |
| 423 | regs->ip -= 2; | 455 | regs->ip -= 2; |
| 424 | break; | 456 | break; |
| 457 | |||
| 425 | case -ERESTART_RESTARTBLOCK: | 458 | case -ERESTART_RESTARTBLOCK: |
| 426 | regs->ax = test_thread_flag(TIF_IA32) ? | 459 | regs->ax = NR_restart_syscall; |
| 427 | __NR_ia32_restart_syscall : | ||
| 428 | __NR_restart_syscall; | ||
| 429 | regs->ip -= 2; | 460 | regs->ip -= 2; |
| 430 | break; | 461 | break; |
| 431 | } | 462 | } |
| @@ -441,14 +472,18 @@ static void do_signal(struct pt_regs *regs) | |||
| 441 | } | 472 | } |
| 442 | } | 473 | } |
| 443 | 474 | ||
| 444 | void do_notify_resume(struct pt_regs *regs, void *unused, | 475 | /* |
| 445 | __u32 thread_info_flags) | 476 | * notification of userspace execution resumption |
| 477 | * - triggered by the TIF_WORK_MASK flags | ||
| 478 | */ | ||
| 479 | void | ||
| 480 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | ||
| 446 | { | 481 | { |
| 447 | #ifdef CONFIG_X86_MCE | 482 | #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) |
| 448 | /* notify userspace of pending MCEs */ | 483 | /* notify userspace of pending MCEs */ |
| 449 | if (thread_info_flags & _TIF_MCE_NOTIFY) | 484 | if (thread_info_flags & _TIF_MCE_NOTIFY) |
| 450 | mce_notify_user(); | 485 | mce_notify_user(); |
| 451 | #endif /* CONFIG_X86_MCE */ | 486 | #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ |
| 452 | 487 | ||
| 453 | /* deal with pending signal delivery */ | 488 | /* deal with pending signal delivery */ |
| 454 | if (thread_info_flags & _TIF_SIGPENDING) | 489 | if (thread_info_flags & _TIF_SIGPENDING) |
| @@ -458,17 +493,23 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
| 458 | clear_thread_flag(TIF_NOTIFY_RESUME); | 493 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 459 | tracehook_notify_resume(regs); | 494 | tracehook_notify_resume(regs); |
| 460 | } | 495 | } |
| 496 | |||
| 497 | #ifdef CONFIG_X86_32 | ||
| 498 | clear_thread_flag(TIF_IRET); | ||
| 499 | #endif /* CONFIG_X86_32 */ | ||
| 461 | } | 500 | } |
| 462 | 501 | ||
| 463 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 502 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
| 464 | { | 503 | { |
| 465 | struct task_struct *me = current; | 504 | struct task_struct *me = current; |
| 505 | |||
| 466 | if (show_unhandled_signals && printk_ratelimit()) { | 506 | if (show_unhandled_signals && printk_ratelimit()) { |
| 467 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | 507 | printk(KERN_INFO |
| 468 | me->comm, me->pid, where, frame, regs->ip, | 508 | "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", |
| 469 | regs->sp, regs->orig_ax); | 509 | me->comm, me->pid, where, frame, |
| 510 | regs->ip, regs->sp, regs->orig_ax); | ||
| 470 | print_vma_addr(" in ", regs->ip); | 511 | print_vma_addr(" in ", regs->ip); |
| 471 | printk("\n"); | 512 | printk(KERN_CONT "\n"); |
| 472 | } | 513 | } |
| 473 | 514 | ||
| 474 | force_sig(SIGSEGV, me); | 515 | force_sig(SIGSEGV, me); |
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 361b7a4c640c..18f9b19f5f8f 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
| @@ -214,12 +214,16 @@ void smp_call_function_single_interrupt(struct pt_regs *regs) | |||
| 214 | struct smp_ops smp_ops = { | 214 | struct smp_ops smp_ops = { |
| 215 | .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, | 215 | .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, |
| 216 | .smp_prepare_cpus = native_smp_prepare_cpus, | 216 | .smp_prepare_cpus = native_smp_prepare_cpus, |
| 217 | .cpu_up = native_cpu_up, | ||
| 218 | .smp_cpus_done = native_smp_cpus_done, | 217 | .smp_cpus_done = native_smp_cpus_done, |
| 219 | 218 | ||
| 220 | .smp_send_stop = native_smp_send_stop, | 219 | .smp_send_stop = native_smp_send_stop, |
| 221 | .smp_send_reschedule = native_smp_send_reschedule, | 220 | .smp_send_reschedule = native_smp_send_reschedule, |
| 222 | 221 | ||
| 222 | .cpu_up = native_cpu_up, | ||
| 223 | .cpu_die = native_cpu_die, | ||
| 224 | .cpu_disable = native_cpu_disable, | ||
| 225 | .play_dead = native_play_dead, | ||
| 226 | |||
| 223 | .send_call_func_ipi = native_send_call_func_ipi, | 227 | .send_call_func_ipi = native_send_call_func_ipi, |
| 224 | .send_call_func_single_ipi = native_send_call_func_single_ipi, | 228 | .send_call_func_single_ipi = native_send_call_func_single_ipi, |
| 225 | }; | 229 | }; |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 9056f7e272c0..76b6f50978f7 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <asm/desc.h> | 52 | #include <asm/desc.h> |
| 53 | #include <asm/nmi.h> | 53 | #include <asm/nmi.h> |
| 54 | #include <asm/irq.h> | 54 | #include <asm/irq.h> |
| 55 | #include <asm/idle.h> | ||
| 55 | #include <asm/smp.h> | 56 | #include <asm/smp.h> |
| 56 | #include <asm/trampoline.h> | 57 | #include <asm/trampoline.h> |
| 57 | #include <asm/cpu.h> | 58 | #include <asm/cpu.h> |
| @@ -1344,25 +1345,9 @@ static void __ref remove_cpu_from_maps(int cpu) | |||
| 1344 | numa_remove_cpu(cpu); | 1345 | numa_remove_cpu(cpu); |
| 1345 | } | 1346 | } |
| 1346 | 1347 | ||
| 1347 | int __cpu_disable(void) | 1348 | void cpu_disable_common(void) |
| 1348 | { | 1349 | { |
| 1349 | int cpu = smp_processor_id(); | 1350 | int cpu = smp_processor_id(); |
| 1350 | |||
| 1351 | /* | ||
| 1352 | * Perhaps use cpufreq to drop frequency, but that could go | ||
| 1353 | * into generic code. | ||
| 1354 | * | ||
| 1355 | * We won't take down the boot processor on i386 due to some | ||
| 1356 | * interrupts only being able to be serviced by the BSP. | ||
| 1357 | * Especially so if we're not using an IOAPIC -zwane | ||
| 1358 | */ | ||
| 1359 | if (cpu == 0) | ||
| 1360 | return -EBUSY; | ||
| 1361 | |||
| 1362 | if (nmi_watchdog == NMI_LOCAL_APIC) | ||
| 1363 | stop_apic_nmi_watchdog(NULL); | ||
| 1364 | clear_local_APIC(); | ||
| 1365 | |||
| 1366 | /* | 1351 | /* |
| 1367 | * HACK: | 1352 | * HACK: |
| 1368 | * Allow any queued timer interrupts to get serviced | 1353 | * Allow any queued timer interrupts to get serviced |
| @@ -1380,10 +1365,32 @@ int __cpu_disable(void) | |||
| 1380 | remove_cpu_from_maps(cpu); | 1365 | remove_cpu_from_maps(cpu); |
| 1381 | unlock_vector_lock(); | 1366 | unlock_vector_lock(); |
| 1382 | fixup_irqs(cpu_online_map); | 1367 | fixup_irqs(cpu_online_map); |
| 1368 | } | ||
| 1369 | |||
| 1370 | int native_cpu_disable(void) | ||
| 1371 | { | ||
| 1372 | int cpu = smp_processor_id(); | ||
| 1373 | |||
| 1374 | /* | ||
| 1375 | * Perhaps use cpufreq to drop frequency, but that could go | ||
| 1376 | * into generic code. | ||
| 1377 | * | ||
| 1378 | * We won't take down the boot processor on i386 due to some | ||
| 1379 | * interrupts only being able to be serviced by the BSP. | ||
| 1380 | * Especially so if we're not using an IOAPIC -zwane | ||
| 1381 | */ | ||
| 1382 | if (cpu == 0) | ||
| 1383 | return -EBUSY; | ||
| 1384 | |||
| 1385 | if (nmi_watchdog == NMI_LOCAL_APIC) | ||
| 1386 | stop_apic_nmi_watchdog(NULL); | ||
| 1387 | clear_local_APIC(); | ||
| 1388 | |||
| 1389 | cpu_disable_common(); | ||
| 1383 | return 0; | 1390 | return 0; |
| 1384 | } | 1391 | } |
| 1385 | 1392 | ||
| 1386 | void __cpu_die(unsigned int cpu) | 1393 | void native_cpu_die(unsigned int cpu) |
| 1387 | { | 1394 | { |
| 1388 | /* We don't do anything here: idle task is faking death itself. */ | 1395 | /* We don't do anything here: idle task is faking death itself. */ |
| 1389 | unsigned int i; | 1396 | unsigned int i; |
| @@ -1400,15 +1407,45 @@ void __cpu_die(unsigned int cpu) | |||
| 1400 | } | 1407 | } |
| 1401 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 1408 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
| 1402 | } | 1409 | } |
| 1410 | |||
| 1411 | void play_dead_common(void) | ||
| 1412 | { | ||
| 1413 | idle_task_exit(); | ||
| 1414 | reset_lazy_tlbstate(); | ||
| 1415 | irq_ctx_exit(raw_smp_processor_id()); | ||
| 1416 | c1e_remove_cpu(raw_smp_processor_id()); | ||
| 1417 | |||
| 1418 | mb(); | ||
| 1419 | /* Ack it */ | ||
| 1420 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
| 1421 | |||
| 1422 | /* | ||
| 1423 | * With physical CPU hotplug, we should halt the cpu | ||
| 1424 | */ | ||
| 1425 | local_irq_disable(); | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | void native_play_dead(void) | ||
| 1429 | { | ||
| 1430 | play_dead_common(); | ||
| 1431 | wbinvd_halt(); | ||
| 1432 | } | ||
| 1433 | |||
| 1403 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1434 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
| 1404 | int __cpu_disable(void) | 1435 | int native_cpu_disable(void) |
| 1405 | { | 1436 | { |
| 1406 | return -ENOSYS; | 1437 | return -ENOSYS; |
| 1407 | } | 1438 | } |
| 1408 | 1439 | ||
| 1409 | void __cpu_die(unsigned int cpu) | 1440 | void native_cpu_die(unsigned int cpu) |
| 1410 | { | 1441 | { |
| 1411 | /* We said "no" in __cpu_disable */ | 1442 | /* We said "no" in __cpu_disable */ |
| 1412 | BUG(); | 1443 | BUG(); |
| 1413 | } | 1444 | } |
| 1445 | |||
| 1446 | void native_play_dead(void) | ||
| 1447 | { | ||
| 1448 | BUG(); | ||
| 1449 | } | ||
| 1450 | |||
| 1414 | #endif | 1451 | #endif |
diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index fec1ecedc9b7..e00534b33534 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c | |||
| @@ -241,3 +241,11 @@ void flush_tlb_all(void) | |||
| 241 | on_each_cpu(do_flush_tlb_all, NULL, 1); | 241 | on_each_cpu(do_flush_tlb_all, NULL, 1); |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | void reset_lazy_tlbstate(void) | ||
| 245 | { | ||
| 246 | int cpu = raw_smp_processor_id(); | ||
| 247 | |||
| 248 | per_cpu(cpu_tlbstate, cpu).state = 0; | ||
| 249 | per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; | ||
| 250 | } | ||
| 251 | |||
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index da5a5964fccb..0429c5de5ea9 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
| @@ -891,6 +891,7 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 891 | { | 891 | { |
| 892 | struct task_struct *tsk = current; | 892 | struct task_struct *tsk = current; |
| 893 | unsigned int condition; | 893 | unsigned int condition; |
| 894 | int si_code; | ||
| 894 | 895 | ||
| 895 | trace_hardirqs_fixup(); | 896 | trace_hardirqs_fixup(); |
| 896 | 897 | ||
| @@ -935,8 +936,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 935 | goto clear_TF_reenable; | 936 | goto clear_TF_reenable; |
| 936 | } | 937 | } |
| 937 | 938 | ||
| 939 | si_code = get_si_code((unsigned long)condition); | ||
| 938 | /* Ok, finally something we can handle */ | 940 | /* Ok, finally something we can handle */ |
| 939 | send_sigtrap(tsk, regs, error_code); | 941 | send_sigtrap(tsk, regs, error_code, si_code); |
| 940 | 942 | ||
| 941 | /* | 943 | /* |
| 942 | * Disable additional traps. They'll be re-enabled when | 944 | * Disable additional traps. They'll be re-enabled when |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 2887a789e38f..9c0ac0cab013 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
| @@ -940,7 +940,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs *regs, | |||
| 940 | tsk->thread.error_code = error_code; | 940 | tsk->thread.error_code = error_code; |
| 941 | info.si_signo = SIGTRAP; | 941 | info.si_signo = SIGTRAP; |
| 942 | info.si_errno = 0; | 942 | info.si_errno = 0; |
| 943 | info.si_code = TRAP_BRKPT; | 943 | info.si_code = get_si_code(condition); |
| 944 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; | 944 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; |
| 945 | force_sig_info(SIGTRAP, &info, tsk); | 945 | force_sig_info(SIGTRAP, &info, tsk); |
| 946 | 946 | ||
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 07713d64debe..9abac8a9d823 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
| @@ -95,7 +95,9 @@ int save_i387_xstate(void __user *buf) | |||
| 95 | * Start with clearing the user buffer. This will present a | 95 | * Start with clearing the user buffer. This will present a |
| 96 | * clean context for the bytes not touched by the fxsave/xsave. | 96 | * clean context for the bytes not touched by the fxsave/xsave. |
| 97 | */ | 97 | */ |
| 98 | __clear_user(buf, sig_xstate_size); | 98 | err = __clear_user(buf, sig_xstate_size); |
| 99 | if (err) | ||
| 100 | return err; | ||
| 99 | 101 | ||
| 100 | if (task_thread_info(tsk)->status & TS_XSAVE) | 102 | if (task_thread_info(tsk)->status & TS_XSAVE) |
| 101 | err = xsave_user(buf); | 103 | err = xsave_user(buf); |
| @@ -114,6 +116,8 @@ int save_i387_xstate(void __user *buf) | |||
| 114 | 116 | ||
| 115 | if (task_thread_info(tsk)->status & TS_XSAVE) { | 117 | if (task_thread_info(tsk)->status & TS_XSAVE) { |
| 116 | struct _fpstate __user *fx = buf; | 118 | struct _fpstate __user *fx = buf; |
| 119 | struct _xstate __user *x = buf; | ||
| 120 | u64 xstate_bv; | ||
| 117 | 121 | ||
| 118 | err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, | 122 | err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, |
| 119 | sizeof(struct _fpx_sw_bytes)); | 123 | sizeof(struct _fpx_sw_bytes)); |
| @@ -121,6 +125,31 @@ int save_i387_xstate(void __user *buf) | |||
| 121 | err |= __put_user(FP_XSTATE_MAGIC2, | 125 | err |= __put_user(FP_XSTATE_MAGIC2, |
| 122 | (__u32 __user *) (buf + sig_xstate_size | 126 | (__u32 __user *) (buf + sig_xstate_size |
| 123 | - FP_XSTATE_MAGIC2_SIZE)); | 127 | - FP_XSTATE_MAGIC2_SIZE)); |
| 128 | |||
| 129 | /* | ||
| 130 | * Read the xstate_bv which we copied (directly from the cpu or | ||
| 131 | * from the state in task struct) to the user buffers and | ||
| 132 | * set the FP/SSE bits. | ||
| 133 | */ | ||
| 134 | err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * For legacy compatible, we always set FP/SSE bits in the bit | ||
| 138 | * vector while saving the state to the user context. This will | ||
| 139 | * enable us capturing any changes(during sigreturn) to | ||
| 140 | * the FP/SSE bits by the legacy applications which don't touch | ||
| 141 | * xstate_bv in the xsave header. | ||
| 142 | * | ||
| 143 | * xsave aware apps can change the xstate_bv in the xsave | ||
| 144 | * header as well as change any contents in the memory layout. | ||
| 145 | * xrestore as part of sigreturn will capture all the changes. | ||
| 146 | */ | ||
| 147 | xstate_bv |= XSTATE_FPSSE; | ||
| 148 | |||
| 149 | err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); | ||
| 150 | |||
| 151 | if (err) | ||
| 152 | return err; | ||
| 124 | } | 153 | } |
| 125 | 154 | ||
| 126 | return 1; | 155 | return 1; |
| @@ -272,7 +301,7 @@ void __cpuinit xsave_init(void) | |||
| 272 | /* | 301 | /* |
| 273 | * setup the xstate image representing the init state | 302 | * setup the xstate image representing the init state |
| 274 | */ | 303 | */ |
| 275 | void setup_xstate_init(void) | 304 | static void __init setup_xstate_init(void) |
| 276 | { | 305 | { |
| 277 | init_xstate_buf = alloc_bootmem(xstate_size); | 306 | init_xstate_buf = alloc_bootmem(xstate_size); |
| 278 | init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; | 307 | init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; |
