From 9659d8acdb341eeb9fe74837b05c60c0dd5ff6ee Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 7 Apr 2010 15:26:32 -0700 Subject: [PATCH] .32 patches --- ...-lenovo-thinkpad-models-using-ad1981.patch | 41 ++ ...alsa-mixart-range-checking-proc-file.patch | 69 ++ ...ia_bl-add-five-more-macbook-variants.patch | 73 ++ ...laptop-add-hotplug_disable-parameter.patch | 48 ++ ...sable-cpu-speed-control-on-eeepc-701.patch | 183 +++++ ...-disable-wireless-hotplug-for-1005pe.patch | 34 + ...p-disable-wireless-hotplug-for-1201n.patch | 28 + ...lacklist-to-disable-pci-hotplug-code.patch | 82 +++ ...update-the-superblock-in-ext3_statfs.patch | 48 ++ ...difications-in-ext3_xattr_set_handle.patch | 49 ++ .../hid-fix-oops-in-gyration_event.patch | 37 + .../kvm-fix-segment-descriptor-loading.patch | 339 +++++++++ ...svm-reset-cr0-properly-on-vcpu-reset.patch | 55 ++ ...unrestricted-guest-when-ept-disabled.patch | 38 + ...instruction-length-on-intercepted-bp.patch | 56 ++ ...d-of-hex-value-on-cr0-initialization.patch | 34 + ...m-x86-disable-paravirt-mmu-reporting.patch | 40 ++ ...r-add-virtual-8086-mode-of-emulation.patch | 94 +++ ...evel-during-io-instruction-emulation.patch | 204 ++++++ ...x-memory-access-during-x86-emulation.patch | 512 ++++++++++++++ .../kvm-x86-emulator-fix-popf-emulation.patch | 107 +++ ...bata-disable-ncq-on-crucial-c300-ssd.patch | 55 ++ .../libata-unlock-hpa-if-device-shrunk.patch | 149 ++++ .../pata_via-add-via-vx900-support.patch | 27 + .../raw-fsync-method-is-now-required.patch | 89 +++ .../readahead-fix-null-filp-dereference.patch | 37 + ...ve-kernel-function-inside-__kernel__.patch | 76 ++ queue-2.6.32/series | 39 ++ .../thinkpad-acpi-adopt-input-device.patch | 31 + .../thinkpad-acpi-convert-to-seq_file.patch | 648 ++++++++++++++++++ ...inkpad-acpi-expose-module-parameters.patch | 95 +++ ...hinkpad-acpi-fix-some-version-quirks.patch | 41 ++ ...ad-acpi-issue-backlight-class-events.patch | 158 +++++ ...-lock-down-video-output-state-access.patch | 117 ++++ ...log-initial-state-of-rfkill-switches.patch | 51 ++ ...-log-temperatures-on-termal-alarm-v2.patch | 142 ++++ ...-silence-bogus-complain-during-rmmod.patch | 34 + ...ync-input-device-ev_sw-initial-state.patch | 92 +++ ...inkpad-acpi-use-input_set_capability.patch | 57 ++ ...deid-msr-instead-of-pci-config-space.patch | 119 ++++ 40 files changed, 4228 insertions(+) create mode 100644 queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch create mode 100644 queue-2.6.32/alsa-mixart-range-checking-proc-file.patch create mode 100644 queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch create mode 100644 queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch create mode 100644 queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch create mode 100644 queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch create mode 100644 queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch create mode 100644 queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch create mode 100644 queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch create mode 100644 queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch create mode 100644 queue-2.6.32/hid-fix-oops-in-gyration_event.patch create mode 100644 queue-2.6.32/kvm-fix-segment-descriptor-loading.patch create mode 100644 queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch create mode 100644 queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch create mode 100644 queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch create mode 100644 queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch create mode 100644 queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch create mode 100644 queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch create mode 100644 queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch create mode 100644 queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch create mode 100644 queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch create mode 100644 queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch create mode 100644 queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch create mode 100644 queue-2.6.32/pata_via-add-via-vx900-support.patch create mode 100644 queue-2.6.32/raw-fsync-method-is-now-required.patch create mode 100644 queue-2.6.32/readahead-fix-null-filp-dereference.patch create mode 100644 queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch create mode 100644 queue-2.6.32/thinkpad-acpi-adopt-input-device.patch create mode 100644 queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch create mode 100644 queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch create mode 100644 queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch create mode 100644 queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch create mode 100644 queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch create mode 100644 queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch create mode 100644 queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch create mode 100644 queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch create mode 100644 queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch create mode 100644 queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch create mode 100644 queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch diff --git a/queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch b/queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch new file mode 100644 index 00000000000..426e81d9b63 --- /dev/null +++ b/queue-2.6.32/alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch @@ -0,0 +1,41 @@ +From b8e80cf386419453678b01bef830f53445ebb15d Mon Sep 17 00:00:00 2001 +From: Daniel T Chen +Date: Tue, 30 Mar 2010 13:29:28 -0400 +Subject: ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981 + +From: Daniel T Chen + +commit b8e80cf386419453678b01bef830f53445ebb15d upstream. + +BugLink: https://launchpad.net/bugs/551606 + +The OR's hardware distorts at PCM 100% because it does not correspond to +0 dB. Fix this in patch_ad1981() for all models using the Thinkpad +quirk. + +Reported-by: Jane Silber +Signed-off-by: Daniel T Chen +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_analog.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/sound/pci/hda/patch_analog.c ++++ b/sound/pci/hda/patch_analog.c +@@ -1789,6 +1789,14 @@ static int patch_ad1981(struct hda_codec + case AD1981_THINKPAD: + spec->mixers[0] = ad1981_thinkpad_mixers; + spec->input_mux = &ad1981_thinkpad_capture_source; ++ /* set the upper-limit for mixer amp to 0dB for avoiding the ++ * possible damage by overloading ++ */ ++ snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, ++ (0x17 << AC_AMPCAP_OFFSET_SHIFT) | ++ (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | ++ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | ++ (1 << AC_AMPCAP_MUTE_SHIFT)); + break; + case AD1981_TOSHIBA: + spec->mixers[0] = ad1981_hp_mixers; diff --git a/queue-2.6.32/alsa-mixart-range-checking-proc-file.patch b/queue-2.6.32/alsa-mixart-range-checking-proc-file.patch new file mode 100644 index 00000000000..0773423046b --- /dev/null +++ b/queue-2.6.32/alsa-mixart-range-checking-proc-file.patch @@ -0,0 +1,69 @@ +From b0cc58a25d04160d39a80e436847eaa2fbc5aa09 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 6 Apr 2010 19:31:26 +0300 +Subject: ALSA: mixart: range checking proc file + +From: Dan Carpenter + +commit b0cc58a25d04160d39a80e436847eaa2fbc5aa09 upstream. + +The original code doesn't take into consideration that the value of +MIXART_BA0_SIZE - pos can be less than zero which would lead to a large +unsigned value for "count". + +Also I moved the check that read size is a multiple of 4 bytes below +the code that adjusts "count". + +Signed-off-by: Dan Carpenter +Acked-by: Linus Torvalds +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/mixart/mixart.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/sound/pci/mixart/mixart.c ++++ b/sound/pci/mixart/mixart.c +@@ -1161,13 +1161,15 @@ static long snd_mixart_BA0_read(struct s + unsigned long count, unsigned long pos) + { + struct mixart_mgr *mgr = entry->private_data; ++ unsigned long maxsize; + +- count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ +- if(count <= 0) ++ if (pos >= MIXART_BA0_SIZE) + return 0; +- if(pos + count > MIXART_BA0_SIZE) +- count = (long)(MIXART_BA0_SIZE - pos); +- if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count)) ++ maxsize = MIXART_BA0_SIZE - pos; ++ if (count > maxsize) ++ count = maxsize; ++ count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ ++ if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) + return -EFAULT; + return count; + } +@@ -1180,13 +1182,15 @@ static long snd_mixart_BA1_read(struct s + unsigned long count, unsigned long pos) + { + struct mixart_mgr *mgr = entry->private_data; ++ unsigned long maxsize; + +- count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ +- if(count <= 0) ++ if (pos > MIXART_BA1_SIZE) + return 0; +- if(pos + count > MIXART_BA1_SIZE) +- count = (long)(MIXART_BA1_SIZE - pos); +- if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count)) ++ maxsize = MIXART_BA1_SIZE - pos; ++ if (count > maxsize) ++ count = maxsize; ++ count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ ++ if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) + return -EFAULT; + return count; + } diff --git a/queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch b/queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch new file mode 100644 index 00000000000..99604a50cd0 --- /dev/null +++ b/queue-2.6.32/backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch @@ -0,0 +1,73 @@ +From 36bc5ee6a8d13333980fa54e97d3469d3d4cda98 Mon Sep 17 00:00:00 2001 +From: Evan McClain +Date: Tue, 9 Mar 2010 19:20:58 -0500 +Subject: backlight: mbp_nvidia_bl - add five more MacBook variants + +From: Evan McClain + +commit 36bc5ee6a8d13333980fa54e97d3469d3d4cda98 upstream. + +This adds the MacBook 1,1 2,1 3,1 4,1 and 4,2 to the DMI tables. + +Signed-off-by: Evan McClain +Signed-off-by: Richard Purdie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/backlight/mbp_nvidia_bl.c | 45 ++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/drivers/video/backlight/mbp_nvidia_bl.c ++++ b/drivers/video/backlight/mbp_nvidia_bl.c +@@ -139,6 +139,51 @@ static int mbp_dmi_match(const struct dm + static const struct dmi_system_id __initdata mbp_device_table[] = { + { + .callback = mbp_dmi_match, ++ .ident = "MacBook 1,1", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), ++ }, ++ .driver_data = (void *)&intel_chipset_data, ++ }, ++ { ++ .callback = mbp_dmi_match, ++ .ident = "MacBook 2,1", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), ++ }, ++ .driver_data = (void *)&intel_chipset_data, ++ }, ++ { ++ .callback = mbp_dmi_match, ++ .ident = "MacBook 3,1", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"), ++ }, ++ .driver_data = (void *)&intel_chipset_data, ++ }, ++ { ++ .callback = mbp_dmi_match, ++ .ident = "MacBook 4,1", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"), ++ }, ++ .driver_data = (void *)&intel_chipset_data, ++ }, ++ { ++ .callback = mbp_dmi_match, ++ .ident = "MacBook 4,2", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"), ++ }, ++ .driver_data = (void *)&intel_chipset_data, ++ }, ++ { ++ .callback = mbp_dmi_match, + .ident = "MacBookPro 3,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), diff --git a/queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch b/queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch new file mode 100644 index 00000000000..198ce87db3f --- /dev/null +++ b/queue-2.6.32/eeepc-laptop-add-hotplug_disable-parameter.patch @@ -0,0 +1,48 @@ +From: Corentin Chary +Date: Wed, 6 Jan 2010 22:07:40 +0100 +Subject: eeepc-laptop: add hotplug_disable parameter + +commit 322a1356be96bcc4b97e8e370f6468c821330077 upstream. + +Some new models need to disable wireless hotplug. +For the moment, we don't know excactly what models need that, +except 1005HA. +Users will be able to use that param as a workaround. + +[bwh: Backported to 2.6.32] + +Signed-off-by: Corentin Chary +Signed-off-by: Len Brown +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/eeepc-laptop.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/platform/x86/eeepc-laptop.c ++++ b/drivers/platform/x86/eeepc-laptop.c +@@ -254,6 +254,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Coop + MODULE_DESCRIPTION(EEEPC_HOTK_NAME); + MODULE_LICENSE("GPL"); + ++static bool hotplug_disabled; ++ ++module_param(hotplug_disabled, bool, 0644); ++MODULE_PARM_DESC(hotplug_disabled, ++ "Disable hotplug for wireless device. " ++ "If your laptop need that, please report to " ++ "acpi4asus-user@lists.sourceforge.net."); ++ + /* + * ACPI Helpers + */ +@@ -1305,6 +1313,8 @@ static int __devinit eeepc_hotk_add(stru + device->driver_data = ehotk; + ehotk->device = device; + ++ ehotk->hotplug_disabled = hotplug_disabled; ++ + eeepc_dmi_check(); + + result = eeepc_hotk_check(); diff --git a/queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch b/queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch new file mode 100644 index 00000000000..e2def8bb5dd --- /dev/null +++ b/queue-2.6.32/eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch @@ -0,0 +1,183 @@ +From: Alan Jenkins +Date: Wed, 6 Jan 2010 22:07:37 +0100 +Subject: eeepc-laptop: disable cpu speed control on EeePC 701 + +commit da8ba01deb98f3dc0558b1f5a37e64f40bba7904 upstream. + +The EeePC 4G ("701") implements CFVS, but it is not supported by the +pre-installed OS, and the original option to change it in the BIOS +setup screen was removed in later versions. Judging by the lack of +"Super Hybrid Engine" on Asus product pages, this applies to all "701" +models (4G/4G Surf/2G Surf). + +So Asus made a deliberate decision not to support it on this model. +We have several reports that using it can cause the system to hang [1]. +That said, it does not happen all the time. Some users do not +experience it at all (and apparently wish to continue "right-clocking"). + +Check for the EeePC 701 using DMI. If met, then disable writes to the +"cpufv" sysfs attribute and log an explanatory message. + +Add a "cpufv_disabled" attribute which allow users to override this +policy. Writing to this attribute will log a second message. + +The sysfs attribute is more useful than a module option, because it +makes it easier for userspace scripts to provide consistent behaviour +(according to user configuration), regardless of whether the kernel +includes this change. + +[1] + +[bwh: Backported to 2.6.32] + +Signed-off-by: Alan Jenkins +Signed-off-by: Corentin Chary +Signed-off-by: Len Brown +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/eeepc-laptop.c | 84 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 84 insertions(+) + +--- a/drivers/platform/x86/eeepc-laptop.c ++++ b/drivers/platform/x86/eeepc-laptop.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #define EEEPC_LAPTOP_VERSION "0.1" + +@@ -135,6 +136,7 @@ struct eeepc_hotk { + acpi_handle handle; /* the handle of the hotk device */ + u32 cm_supported; /* the control methods supported + by this BIOS */ ++ bool cpufv_disabled; + uint init_flag; /* Init flags */ + u16 event_count[128]; /* count for each event */ + struct input_dev *inputdev; +@@ -467,6 +469,8 @@ static ssize_t store_cpufv(struct device + struct eeepc_cpufv c; + int rv, value; + ++ if (ehotk->cpufv_disabled) ++ return -EPERM; + if (get_cpufv(&c)) + return -ENODEV; + rv = parse_arg(buf, count, &value); +@@ -478,6 +482,38 @@ static ssize_t store_cpufv(struct device + return rv; + } + ++static ssize_t show_cpufv_disabled(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", ehotk->cpufv_disabled); ++} ++ ++static ssize_t store_cpufv_disabled(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int rv, value; ++ ++ rv = parse_arg(buf, count, &value); ++ if (rv < 0) ++ return rv; ++ ++ switch (value) { ++ case 0: ++ if (ehotk->cpufv_disabled) ++ pr_warning("cpufv enabled (not officially supported " ++ "on this model)\n"); ++ ehotk->cpufv_disabled = false; ++ return rv; ++ case 1: ++ return -EPERM; ++ default: ++ return -EINVAL; ++ } ++} ++ ++ + static struct device_attribute dev_attr_cpufv = { + .attr = { + .name = "cpufv", +@@ -493,12 +529,22 @@ static struct device_attribute dev_attr_ + .show = show_available_cpufv + }; + ++static struct device_attribute dev_attr_cpufv_disabled = { ++ .attr = { ++ .name = "cpufv_disabled", ++ .mode = 0644 }, ++ .show = show_cpufv_disabled, ++ .store = store_cpufv_disabled ++}; ++ ++ + static struct attribute *platform_attributes[] = { + &dev_attr_camera.attr, + &dev_attr_cardr.attr, + &dev_attr_disp.attr, + &dev_attr_cpufv.attr, + &dev_attr_available_cpufv.attr, ++ &dev_attr_cpufv_disabled.attr, + NULL + }; + +@@ -564,6 +610,42 @@ static int eeepc_setkeycode(struct input + return -EINVAL; + } + ++static void eeepc_dmi_check(void) ++{ ++ const char *model; ++ ++ /* ++ * Blacklist for setting cpufv (cpu speed). ++ * ++ * EeePC 4G ("701") implements CFVS, but it is not supported ++ * by the pre-installed OS, and the original option to change it ++ * in the BIOS setup screen was removed in later versions. ++ * ++ * Judging by the lack of "Super Hybrid Engine" on Asus product pages, ++ * this applies to all "701" models (4G/4G Surf/2G Surf). ++ * ++ * So Asus made a deliberate decision not to support it on this model. ++ * We have several reports that using it can cause the system to hang ++ * ++ * The hang has also been reported on a "702" (Model name "8G"?). ++ * ++ * We avoid dmi_check_system() / dmi_match(), because they use ++ * substring matching. We don't want to affect the "701SD" ++ * and "701SDX" models, because they do support S.H.E. ++ */ ++ ++ model = dmi_get_system_info(DMI_PRODUCT_NAME); ++ if (!model) ++ return; ++ ++ if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { ++ ehotk->cpufv_disabled = true; ++ pr_info("model %s does not officially support setting cpu " ++ "speed\n", model); ++ pr_info("cpufv disabled to avoid instability\n"); ++ } ++} ++ + static void cmsg_quirk(int cm, const char *name) + { + int dummy; +@@ -1208,6 +1290,8 @@ static int __devinit eeepc_hotk_add(stru + device->driver_data = ehotk; + ehotk->device = device; + ++ eeepc_dmi_check(); ++ + result = eeepc_hotk_check(); + if (result) + goto fail_platform_driver; diff --git a/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch new file mode 100644 index 00000000000..b90f01d4c15 --- /dev/null +++ b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch @@ -0,0 +1,34 @@ +From: Alan Jenkins +Date: Sat, 20 Feb 2010 11:02:24 +0000 +Subject: eeepc-laptop: disable wireless hotplug for 1005PE + +commit ced69c59811f05b2f8378467cbb82ac6ed3c6a5a upstream. + +The wireless hotplug code is not needed on this model, and it disables +the wired ethernet card. (Like on the 1005HA and 1201N). + +References: + +[bwh: Backported to 2.6.32] + +Signed-off-by: Alan Jenkins +Reported-by: Ansgar Burchardt +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/eeepc-laptop.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/platform/x86/eeepc-laptop.c ++++ b/drivers/platform/x86/eeepc-laptop.c +@@ -660,7 +660,8 @@ static void eeepc_dmi_check(void) + * hotplug code. In fact, current hotplug code seems to unplug another + * device... + */ +- if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { ++ if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 || ++ strcmp(model, "1005PE") == 0) { + ehotk->hotplug_disabled = true; + pr_info("wlan hotplug disabled\n"); + } diff --git a/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch new file mode 100644 index 00000000000..18d88d58042 --- /dev/null +++ b/queue-2.6.32/eeepc-laptop-disable-wireless-hotplug-for-1201n.patch @@ -0,0 +1,28 @@ +From: Corentin Chary +Date: Wed, 6 Jan 2010 22:07:41 +0100 +Subject: eeepc-laptop: disable wireless hotplug for 1201N + +commit 4194e2f551a6308e6ab34ac88210bf54858aa7df upstream. + +[bwh: Backported to 2.6.32] + +Signed-off-by: Corentin Chary +Signed-off-by: Len Brown +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/eeepc-laptop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/platform/x86/eeepc-laptop.c ++++ b/drivers/platform/x86/eeepc-laptop.c +@@ -660,7 +660,7 @@ static void eeepc_dmi_check(void) + * hotplug code. In fact, current hotplug code seems to unplug another + * device... + */ +- if (strcmp(model, "1005HA") == 0) { ++ if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { + ehotk->hotplug_disabled = true; + pr_info("wlan hotplug disabled\n"); + } diff --git a/queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch b/queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch new file mode 100644 index 00000000000..4665ecf2212 --- /dev/null +++ b/queue-2.6.32/eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch @@ -0,0 +1,82 @@ +From: Corentin Chary +Date: Wed, 6 Jan 2010 22:07:38 +0100 +Subject: eeepc-laptop: dmi blacklist to disable pci hotplug code + +commit 10ae4b5663ff3092553bfbd867e7bd474ce6c553 upstream. + +This is a short term workaround for Eeepc 1005HA. + +refs: + +[bwh: Backported to 2.6.32] + +Signed-off-by: Corentin Chary +Signed-off-by: Len Brown +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/eeepc-laptop.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/platform/x86/eeepc-laptop.c ++++ b/drivers/platform/x86/eeepc-laptop.c +@@ -137,6 +137,7 @@ struct eeepc_hotk { + u32 cm_supported; /* the control methods supported + by this BIOS */ + bool cpufv_disabled; ++ bool hotplug_disabled; + uint init_flag; /* Init flags */ + u16 event_count[128]; /* count for each event */ + struct input_dev *inputdev; +@@ -614,6 +615,10 @@ static void eeepc_dmi_check(void) + { + const char *model; + ++ model = dmi_get_system_info(DMI_PRODUCT_NAME); ++ if (!model) ++ return; ++ + /* + * Blacklist for setting cpufv (cpu speed). + * +@@ -633,17 +638,24 @@ static void eeepc_dmi_check(void) + * substring matching. We don't want to affect the "701SD" + * and "701SDX" models, because they do support S.H.E. + */ +- +- model = dmi_get_system_info(DMI_PRODUCT_NAME); +- if (!model) +- return; +- + if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { + ehotk->cpufv_disabled = true; + pr_info("model %s does not officially support setting cpu " + "speed\n", model); + pr_info("cpufv disabled to avoid instability\n"); + } ++ ++ /* ++ * Blacklist for wlan hotplug ++ * ++ * Eeepc 1005HA doesn't work like others models and don't need the ++ * hotplug code. In fact, current hotplug code seems to unplug another ++ * device... ++ */ ++ if (strcmp(model, "1005HA") == 0) { ++ ehotk->hotplug_disabled = true; ++ pr_info("wlan hotplug disabled\n"); ++ } + } + + static void cmsg_quirk(int cm, const char *name) +@@ -1177,6 +1189,9 @@ static int eeepc_rfkill_init(struct devi + if (result && result != -ENODEV) + goto exit; + ++ if (ehotk->hotplug_disabled) ++ return 0; ++ + result = eeepc_setup_pci_hotplug(); + /* + * If we get -EBUSY then something else is handling the PCI hotplug - diff --git a/queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch b/queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch new file mode 100644 index 00000000000..dc5bf62decf --- /dev/null +++ b/queue-2.6.32/ext3-don-t-update-the-superblock-in-ext3_statfs.patch @@ -0,0 +1,48 @@ +From b918397542388de75bd86c32fbfa820e5d629fa9 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 16 Nov 2009 16:34:51 -0600 +Subject: ext3: Don't update the superblock in ext3_statfs() + +From: Eric Sandeen + +commit b918397542388de75bd86c32fbfa820e5d629fa9 upstream. + +commit a71ce8c6c9bf269b192f352ea555217815cf027e updated ext3_statfs() +to update the on-disk superblock counters, but modified this buffer +directly without any journaling of the change. This is one of the +accesses that was causing the crc errors in journal replay as seen in +kernel.org bugzilla #14354. + +The modifications were originally to keep the sb "more" in sync, +so that a readonly fsck of the device didn't flag this as an +error (as often), but apparently e2fsprogs deals with this differently +now, anyway. + +Based on Ted's patch for ext4, which was in turn based on my +work on that bug and another preliminary patch... + +Signed-off-by: Eric Sandeen +Signed-off-by: Jan Kara +Cc: maximilian attems +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext3/super.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/fs/ext3/super.c ++++ b/fs/ext3/super.c +@@ -2686,13 +2686,11 @@ static int ext3_statfs (struct dentry * + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last; + buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter); +- es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); + buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); + if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) + buf->f_bavail = 0; + buf->f_files = le32_to_cpu(es->s_inodes_count); + buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); +- es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); + buf->f_namelen = EXT3_NAME_LEN; + fsid = le64_to_cpup((void *)es->s_uuid) ^ + le64_to_cpup((void *)es->s_uuid + sizeof(u64)); diff --git a/queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch b/queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch new file mode 100644 index 00000000000..5e826003afa --- /dev/null +++ b/queue-2.6.32/ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch @@ -0,0 +1,49 @@ +From d965736b8cb42ae51ba9c3f13488035a98d025c6 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 16 Nov 2009 16:27:30 -0600 +Subject: ext3: journal all modifications in ext3_xattr_set_handle + +From: Eric Sandeen + +commit d965736b8cb42ae51ba9c3f13488035a98d025c6 upstream. + +ext3_xattr_set_handle() was zeroing out an inode outside +of journaling constraints; this is one of the accesses that +was causing the crc errors in journal replay as seen in +kernel.org bugzilla #14354. + +Although ext3 doesn't have the crc issue, modifications +out of journal control are a Bad Thing. + +Signed-off-by: Eric Sandeen +Signed-off-by: Jan Kara +Cc: maximilian attems +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext3/xattr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/fs/ext3/xattr.c ++++ b/fs/ext3/xattr.c +@@ -960,6 +960,10 @@ ext3_xattr_set_handle(handle_t *handle, + if (error) + goto cleanup; + ++ error = ext3_journal_get_write_access(handle, is.iloc.bh); ++ if (error) ++ goto cleanup; ++ + if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) { + struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc); + memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size); +@@ -985,9 +989,6 @@ ext3_xattr_set_handle(handle_t *handle, + if (flags & XATTR_CREATE) + goto cleanup; + } +- error = ext3_journal_get_write_access(handle, is.iloc.bh); +- if (error) +- goto cleanup; + if (!value) { + if (!is.s.not_found) + error = ext3_xattr_ibody_set(handle, inode, &i, &is); diff --git a/queue-2.6.32/hid-fix-oops-in-gyration_event.patch b/queue-2.6.32/hid-fix-oops-in-gyration_event.patch new file mode 100644 index 00000000000..f92c7e5084f --- /dev/null +++ b/queue-2.6.32/hid-fix-oops-in-gyration_event.patch @@ -0,0 +1,37 @@ +From d8e4ebf8b603bdcd091540e6b5bddf0dec10d516 Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Tue, 23 Mar 2010 16:32:37 +0100 +Subject: HID: fix oops in gyration_event() + +From: Jiri Kosina + +commit d8e4ebf8b603bdcd091540e6b5bddf0dec10d516 upstream. + +Fix oops caused by dereferencing field->hidinput in cases where +the device hasn't been claimed by hid-input. + +Reported-by: Andreas Demmer +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-gyration.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/hid/hid-gyration.c ++++ b/drivers/hid/hid-gyration.c +@@ -53,10 +53,13 @@ static int gyration_input_mapping(struct + static int gyration_event(struct hid_device *hdev, struct hid_field *field, + struct hid_usage *usage, __s32 value) + { +- struct input_dev *input = field->hidinput->input; ++ ++ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput) ++ return 0; + + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK && + (usage->hid & 0xff) == 0x82) { ++ struct input_dev *input = field->hidinput->input; + input_event(input, usage->type, usage->code, 1); + input_sync(input); + input_event(input, usage->type, usage->code, 0); diff --git a/queue-2.6.32/kvm-fix-segment-descriptor-loading.patch b/queue-2.6.32/kvm-fix-segment-descriptor-loading.patch new file mode 100644 index 00000000000..e11e758a1cf --- /dev/null +++ b/queue-2.6.32/kvm-fix-segment-descriptor-loading.patch @@ -0,0 +1,339 @@ +From stefan.bader@canonical.com Wed Apr 7 14:44:22 2010 +From: Gleb Natapov +Date: Fri, 19 Mar 2010 15:47:34 +0100 +Subject: KVM: Fix segment descriptor loading +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-7-git-send-email-stefan.bader@canonical.com> + + +From: Gleb Natapov + +commit c697518a861e6c43b92b848895f9926580ee63c3 upstream + +Add proper error and permission checking. This patch also change task +switching code to load segment selectors before segment descriptors, like +SDM requires, otherwise permission checking during segment descriptor +loading will be incorrect. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/kvm_host.h | 3 + arch/x86/kvm/emulate.c | 28 +----- + arch/x86/kvm/x86.c | 173 ++++++++++++++++++++++++++++++++++------ + 3 files changed, 158 insertions(+), 46 deletions(-) + +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -602,8 +602,7 @@ int emulator_set_dr(struct x86_emulate_c + unsigned long value); + + void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); +-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, +- int type_bits, int seg); ++int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg); + + int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason); + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1396,7 +1396,7 @@ static int emulate_ret_far(struct x86_em + rc = emulate_pop(ctxt, ops, &cs, c->op_bytes); + if (rc) + return rc; +- rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS); ++ rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, VCPU_SREG_CS); + return rc; + } + +@@ -1992,12 +1992,11 @@ special_insn: + break; + case 0x8e: { /* mov seg, r/m16 */ + uint16_t sel; +- int type_bits; +- int err; + + sel = c->src.val; + +- if (c->modrm_reg == VCPU_SREG_CS) { ++ if (c->modrm_reg == VCPU_SREG_CS || ++ c->modrm_reg > VCPU_SREG_GS) { + kvm_queue_exception(ctxt->vcpu, UD_VECTOR); + goto done; + } +@@ -2005,18 +2004,7 @@ special_insn: + if (c->modrm_reg == VCPU_SREG_SS) + toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS); + +- if (c->modrm_reg <= 5) { +- type_bits = (c->modrm_reg == 1) ? 9 : 1; +- err = kvm_load_segment_descriptor(ctxt->vcpu, sel, +- type_bits, c->modrm_reg); +- } else { +- printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n", +- c->modrm); +- goto cannot_emulate; +- } +- +- if (err < 0) +- goto cannot_emulate; ++ rc = kvm_load_segment_descriptor(ctxt->vcpu, sel, c->modrm_reg); + + c->dst.type = OP_NONE; /* Disable writeback. */ + break; +@@ -2186,11 +2174,9 @@ special_insn: + case 0xe9: /* jmp rel */ + goto jmp; + case 0xea: /* jmp far */ +- if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9, +- VCPU_SREG_CS) < 0) { +- DPRINTF("jmp far: Failed to load CS descriptor\n"); +- goto cannot_emulate; +- } ++ if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, ++ VCPU_SREG_CS)) ++ goto done; + + c->eip = c->src.val; + break; +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4207,7 +4207,7 @@ static int kvm_load_realmode_segment(str + .unusable = 0, + }; + kvm_x86_ops->set_segment(vcpu, &segvar, seg); +- return 0; ++ return X86EMUL_CONTINUE; + } + + static int is_vm86_segment(struct kvm_vcpu *vcpu, int seg) +@@ -4217,24 +4217,113 @@ static int is_vm86_segment(struct kvm_vc + (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_VM); + } + +-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, +- int type_bits, int seg) ++int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg) + { + struct kvm_segment kvm_seg; ++ struct desc_struct seg_desc; ++ u8 dpl, rpl, cpl; ++ unsigned err_vec = GP_VECTOR; ++ u32 err_code = 0; ++ bool null_selector = !(selector & ~0x3); /* 0000-0003 are null */ ++ int ret; + + if (is_vm86_segment(vcpu, seg) || !(vcpu->arch.cr0 & X86_CR0_PE)) + return kvm_load_realmode_segment(vcpu, selector, seg); +- if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg)) +- return 1; +- kvm_seg.type |= type_bits; + +- if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS && +- seg != VCPU_SREG_LDTR) +- if (!kvm_seg.s) +- kvm_seg.unusable = 1; + ++ /* NULL selector is not valid for TR, CS and SS */ ++ if ((seg == VCPU_SREG_CS || seg == VCPU_SREG_SS || seg == VCPU_SREG_TR) ++ && null_selector) ++ goto exception; ++ ++ /* TR should be in GDT only */ ++ if (seg == VCPU_SREG_TR && (selector & (1 << 2))) ++ goto exception; ++ ++ ret = load_guest_segment_descriptor(vcpu, selector, &seg_desc); ++ if (ret) ++ return ret; ++ ++ seg_desct_to_kvm_desct(&seg_desc, selector, &kvm_seg); ++ ++ if (null_selector) { /* for NULL selector skip all following checks */ ++ kvm_seg.unusable = 1; ++ goto load; ++ } ++ ++ err_code = selector & 0xfffc; ++ err_vec = GP_VECTOR; ++ ++ /* can't load system descriptor into segment selecor */ ++ if (seg <= VCPU_SREG_GS && !kvm_seg.s) ++ goto exception; ++ ++ if (!kvm_seg.present) { ++ err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR; ++ goto exception; ++ } ++ ++ rpl = selector & 3; ++ dpl = kvm_seg.dpl; ++ cpl = kvm_x86_ops->get_cpl(vcpu); ++ ++ switch (seg) { ++ case VCPU_SREG_SS: ++ /* ++ * segment is not a writable data segment or segment ++ * selector's RPL != CPL or segment selector's RPL != CPL ++ */ ++ if (rpl != cpl || (kvm_seg.type & 0xa) != 0x2 || dpl != cpl) ++ goto exception; ++ break; ++ case VCPU_SREG_CS: ++ if (!(kvm_seg.type & 8)) ++ goto exception; ++ ++ if (kvm_seg.type & 4) { ++ /* conforming */ ++ if (dpl > cpl) ++ goto exception; ++ } else { ++ /* nonconforming */ ++ if (rpl > cpl || dpl != cpl) ++ goto exception; ++ } ++ /* CS(RPL) <- CPL */ ++ selector = (selector & 0xfffc) | cpl; ++ break; ++ case VCPU_SREG_TR: ++ if (kvm_seg.s || (kvm_seg.type != 1 && kvm_seg.type != 9)) ++ goto exception; ++ break; ++ case VCPU_SREG_LDTR: ++ if (kvm_seg.s || kvm_seg.type != 2) ++ goto exception; ++ break; ++ default: /* DS, ES, FS, or GS */ ++ /* ++ * segment is not a data or readable code segment or ++ * ((segment is a data or nonconforming code segment) ++ * and (both RPL and CPL > DPL)) ++ */ ++ if ((kvm_seg.type & 0xa) == 0x8 || ++ (((kvm_seg.type & 0xc) != 0xc) && (rpl > dpl && cpl > dpl))) ++ goto exception; ++ break; ++ } ++ ++ if (!kvm_seg.unusable && kvm_seg.s) { ++ /* mark segment as accessed */ ++ kvm_seg.type |= 1; ++ seg_desc.type |= 1; ++ save_guest_segment_descriptor(vcpu, selector, &seg_desc); ++ } ++load: + kvm_set_segment(vcpu, &kvm_seg, seg); +- return 0; ++ return X86EMUL_CONTINUE; ++exception: ++ kvm_queue_exception_e(vcpu, err_vec, err_code); ++ return X86EMUL_PROPAGATE_FAULT; + } + + static void save_state_to_tss32(struct kvm_vcpu *vcpu, +@@ -4260,6 +4349,14 @@ static void save_state_to_tss32(struct k + tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR); + } + ++static void kvm_load_segment_selector(struct kvm_vcpu *vcpu, u16 sel, int seg) ++{ ++ struct kvm_segment kvm_seg; ++ kvm_get_segment(vcpu, &kvm_seg, seg); ++ kvm_seg.selector = sel; ++ kvm_set_segment(vcpu, &kvm_seg, seg); ++} ++ + static int load_state_from_tss32(struct kvm_vcpu *vcpu, + struct tss_segment_32 *tss) + { +@@ -4277,25 +4374,41 @@ static int load_state_from_tss32(struct + kvm_register_write(vcpu, VCPU_REGS_RSI, tss->esi); + kvm_register_write(vcpu, VCPU_REGS_RDI, tss->edi); + +- if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR)) ++ /* ++ * SDM says that segment selectors are loaded before segment ++ * descriptors ++ */ ++ kvm_load_segment_selector(vcpu, tss->ldt_selector, VCPU_SREG_LDTR); ++ kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES); ++ kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS); ++ kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS); ++ kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS); ++ kvm_load_segment_selector(vcpu, tss->fs, VCPU_SREG_FS); ++ kvm_load_segment_selector(vcpu, tss->gs, VCPU_SREG_GS); ++ ++ /* ++ * Now load segment descriptors. If fault happenes at this stage ++ * it is handled in a context of new task ++ */ ++ if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, VCPU_SREG_LDTR)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES)) ++ if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->fs, VCPU_SREG_FS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->gs, VCPU_SREG_GS)) + return 1; + return 0; + } +@@ -4336,19 +4449,33 @@ static int load_state_from_tss16(struct + kvm_register_write(vcpu, VCPU_REGS_RSI, tss->si); + kvm_register_write(vcpu, VCPU_REGS_RDI, tss->di); + +- if (kvm_load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR)) ++ /* ++ * SDM says that segment selectors are loaded before segment ++ * descriptors ++ */ ++ kvm_load_segment_selector(vcpu, tss->ldt, VCPU_SREG_LDTR); ++ kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES); ++ kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS); ++ kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS); ++ kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS); ++ ++ /* ++ * Now load segment descriptors. If fault happenes at this stage ++ * it is handled in a context of new task ++ */ ++ if (kvm_load_segment_descriptor(vcpu, tss->ldt, VCPU_SREG_LDTR)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES)) ++ if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS)) + return 1; + +- if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS)) ++ if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS)) + return 1; + return 0; + } diff --git a/queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch b/queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch new file mode 100644 index 00000000000..6d7f461123e --- /dev/null +++ b/queue-2.6.32/kvm-svm-reset-cr0-properly-on-vcpu-reset.patch @@ -0,0 +1,55 @@ +From stefan.bader@canonical.com Wed Apr 7 14:47:43 2010 +From: Eduardo Habkost +Date: Fri, 19 Mar 2010 15:47:37 +0100 +Subject: KVM: SVM: Reset cr0 properly on vcpu reset +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-10-git-send-email-stefan.bader@canonical.com> + + +From: Eduardo Habkost + +commit 18fa000ae453767b59ab97477925895a3f0c46ea upstream + +svm_vcpu_reset() was not properly resetting the contents of the guest-visible +cr0 register, causing the following issue: +https://bugzilla.redhat.com/show_bug.cgi?id=525699 + +Without resetting cr0 properly, the vcpu was running the SIPI bootstrap routine +with paging enabled, making the vcpu get a pagefault exception while trying to +run it. + +Instead of setting vmcb->save.cr0 directly, the new code just resets +kvm->arch.cr0 and calls kvm_set_cr0(). The bits that were set/cleared on +vmcb->save.cr0 (PG, WP, !CD, !NW) will be set properly by svm_set_cr0(). + +kvm_set_cr0() is used instead of calling svm_set_cr0() directly to make sure +kvm_mmu_reset_context() is called to reset the mmu to nonpaging mode. + +Signed-off-by: Eduardo Habkost +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -625,11 +625,12 @@ static void init_vmcb(struct vcpu_svm *s + save->rip = 0x0000fff0; + svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip; + +- /* +- * cr0 val on cpu init should be 0x60000010, we enable cpu +- * cache by default. the orderly way is to enable cache in bios. ++ /* This is the guest-visible cr0 value. ++ * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0. + */ +- save->cr0 = 0x00000010 | X86_CR0_PG | X86_CR0_WP; ++ svm->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; ++ kvm_set_cr0(&svm->vcpu, svm->vcpu.arch.cr0); ++ + save->cr4 = X86_CR4_PAE; + /* rdx = ?? */ + diff --git a/queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch b/queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch new file mode 100644 index 00000000000..ec9d8c5a6b5 --- /dev/null +++ b/queue-2.6.32/kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch @@ -0,0 +1,38 @@ +From stefan.bader@canonical.com Wed Apr 7 14:48:04 2010 +From: Sheng Yang +Date: Fri, 19 Mar 2010 15:47:38 +0100 +Subject: KVM: VMX: Disable unrestricted guest when EPT disabled +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-11-git-send-email-stefan.bader@canonical.com> + + +From: Sheng Yang + +commit 046d87103addc117f0d397196e85189722d4d7de upstream + +Otherwise would cause VMEntry failure when using ept=0 on unrestricted guest +supported processors. + +Signed-off-by: Sheng Yang +Signed-off-by: Marcelo Tosatti +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2302,8 +2302,10 @@ static int vmx_vcpu_setup(struct vcpu_vm + ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; + if (vmx->vpid == 0) + exec_control &= ~SECONDARY_EXEC_ENABLE_VPID; +- if (!enable_ept) ++ if (!enable_ept) { + exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; ++ enable_unrestricted_guest = 0; ++ } + if (!enable_unrestricted_guest) + exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); diff --git a/queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch b/queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch new file mode 100644 index 00000000000..2df3d058d57 --- /dev/null +++ b/queue-2.6.32/kvm-vmx-update-instruction-length-on-intercepted-bp.patch @@ -0,0 +1,56 @@ +From stefan.bader@canonical.com Wed Apr 7 14:44:45 2010 +From: Jan Kiszka +Date: Fri, 19 Mar 2010 15:47:35 +0100 +Subject: KVM: VMX: Update instruction length on intercepted BP +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-8-git-send-email-stefan.bader@canonical.com> + + +From: Jan Kiszka + +commit c573cd22939e54fc1b8e672054a505048987a7cb upstream + +We intercept #BP while in guest debugging mode. As VM exits due to +intercepted exceptions do not necessarily come with valid +idt_vectoring, we have to update event_exit_inst_len explicitly in such +cases. At least in the absence of migration, this ensures that +re-injections of #BP will find and use the correct instruction length. + +Signed-off-by: Jan Kiszka +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2674,6 +2674,12 @@ static int handle_rmode_exception(struct + kvm_queue_exception(vcpu, vec); + return 1; + case BP_VECTOR: ++ /* ++ * Update instruction length as we may reinject the exception ++ * from user space while in guest debugging mode. ++ */ ++ to_vmx(vcpu)->vcpu.arch.event_exit_inst_len = ++ vmcs_read32(VM_EXIT_INSTRUCTION_LEN); + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) + return 0; + /* fall through */ +@@ -2790,6 +2796,13 @@ static int handle_exception(struct kvm_v + kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7); + /* fall through */ + case BP_VECTOR: ++ /* ++ * Update instruction length as we may reinject #BP from ++ * user space while in guest debugging mode. Reading it for ++ * #DB as well causes no harm, it is not used in that case. ++ */ ++ vmx->vcpu.arch.event_exit_inst_len = ++ vmcs_read32(VM_EXIT_INSTRUCTION_LEN); + kvm_run->exit_reason = KVM_EXIT_DEBUG; + kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; + kvm_run->debug.arch.exception = ex_no; diff --git a/queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch b/queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch new file mode 100644 index 00000000000..b6980ead52a --- /dev/null +++ b/queue-2.6.32/kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch @@ -0,0 +1,34 @@ +From stefan.bader@canonical.com Wed Apr 7 14:47:24 2010 +From: Eduardo Habkost +Date: Fri, 19 Mar 2010 15:47:36 +0100 +Subject: KVM: VMX: Use macros instead of hex value on cr0 initialization +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-9-git-send-email-stefan.bader@canonical.com> + + +From: Eduardo Habkost + +commit fa40052ca04bdbbeb20b839cc8ffe9fa7beefbe9 upstream + +This should have no effect, it is just to make the code clearer. + +Signed-off-by: Eduardo Habkost +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2510,7 +2510,7 @@ static int vmx_vcpu_reset(struct kvm_vcp + if (vmx->vpid != 0) + vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); + +- vmx->vcpu.arch.cr0 = 0x60000010; ++ vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; + vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */ + vmx_set_cr4(&vmx->vcpu, 0); + vmx_set_efer(&vmx->vcpu, 0); diff --git a/queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch b/queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch new file mode 100644 index 00000000000..b1f10dd23d9 --- /dev/null +++ b/queue-2.6.32/kvm-x86-disable-paravirt-mmu-reporting.patch @@ -0,0 +1,40 @@ +From stefan.bader@canonical.com Wed Apr 7 14:48:33 2010 +From: Marcelo Tosatti +Date: Fri, 19 Mar 2010 15:47:39 +0100 +Subject: KVM: x86: disable paravirt mmu reporting +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-12-git-send-email-stefan.bader@canonical.com> + + +From: Marcelo Tosatti + +commit a68a6a7282373bedba8a2ed751b6384edb983a64 upstream + +Disable paravirt MMU capability reporting, so that new (or rebooted) +guests switch to native operation. + +Paravirt MMU is a burden to maintain and does not bring significant +advantages compared to shadow anymore. + +Signed-off-by: Marcelo Tosatti +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/x86.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1242,8 +1242,8 @@ int kvm_dev_ioctl_check_extension(long e + case KVM_CAP_NR_MEMSLOTS: + r = KVM_MEMORY_SLOTS; + break; +- case KVM_CAP_PV_MMU: +- r = !tdp_enabled; ++ case KVM_CAP_PV_MMU: /* obsolete */ ++ r = 0; + break; + case KVM_CAP_IOMMU: + r = iommu_found(); diff --git a/queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch b/queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch new file mode 100644 index 00000000000..e823869fbb2 --- /dev/null +++ b/queue-2.6.32/kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch @@ -0,0 +1,94 @@ +From stefan.bader@canonical.com Wed Apr 7 14:41:50 2010 +From: Gleb Natapov +Date: Fri, 19 Mar 2010 15:47:30 +0100 +Subject: KVM: x86 emulator: Add Virtual-8086 mode of emulation +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-3-git-send-email-stefan.bader@canonical.com> + + +From: Gleb Natapov + +commit a0044755679f3e761b8b95995e5f2db2b7efd0f6 upstream + +For some instructions CPU behaves differently for real-mode and +virtual 8086. Let emulator know which mode cpu is in, so it will +not poke into vcpu state directly. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/kvm_emulate.h | 1 + + arch/x86/kvm/emulate.c | 14 +++++++------- + arch/x86/kvm/x86.c | 3 ++- + 3 files changed, 10 insertions(+), 8 deletions(-) + +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -168,6 +168,7 @@ struct x86_emulate_ctxt { + + /* Execution mode, passed to the emulator. */ + #define X86EMUL_MODE_REAL 0 /* Real mode. */ ++#define X86EMUL_MODE_VM86 1 /* Virtual 8086 mode. */ + #define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */ + #define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */ + #define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */ +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -895,6 +895,7 @@ x86_decode_insn(struct x86_emulate_ctxt + + switch (mode) { + case X86EMUL_MODE_REAL: ++ case X86EMUL_MODE_VM86: + case X86EMUL_MODE_PROT16: + def_op_bytes = def_ad_bytes = 2; + break; +@@ -1453,7 +1454,7 @@ emulate_syscall(struct x86_emulate_ctxt + + /* syscall is not available in real mode */ + if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL +- || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) ++ || ctxt->mode == X86EMUL_MODE_VM86) + return -1; + + setup_syscalls_segments(ctxt, &cs, &ss); +@@ -1505,9 +1506,8 @@ emulate_sysenter(struct x86_emulate_ctxt + if (c->lock_prefix) + return -1; + +- /* inject #GP if in real mode or paging is disabled */ +- if (ctxt->mode == X86EMUL_MODE_REAL || +- !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) { ++ /* inject #GP if in real mode */ ++ if (ctxt->mode == X86EMUL_MODE_REAL) { + kvm_inject_gp(ctxt->vcpu, 0); + return -1; + } +@@ -1571,9 +1571,9 @@ emulate_sysexit(struct x86_emulate_ctxt + if (c->lock_prefix) + return -1; + +- /* inject #GP if in real mode or paging is disabled */ +- if (ctxt->mode == X86EMUL_MODE_REAL +- || !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) { ++ /* inject #GP if in real mode or Virtual 8086 mode */ ++ if (ctxt->mode == X86EMUL_MODE_REAL || ++ ctxt->mode == X86EMUL_MODE_VM86) { + kvm_inject_gp(ctxt->vcpu, 0); + return -1; + } +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -2828,8 +2828,9 @@ int emulate_instruction(struct kvm_vcpu + vcpu->arch.emulate_ctxt.vcpu = vcpu; + vcpu->arch.emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu); + vcpu->arch.emulate_ctxt.mode = ++ (!(vcpu->arch.cr0 & X86_CR0_PE)) ? X86EMUL_MODE_REAL : + (vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM) +- ? X86EMUL_MODE_REAL : cs_l ++ ? X86EMUL_MODE_VM86 : cs_l + ? X86EMUL_MODE_PROT64 : cs_db + ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; + diff --git a/queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch b/queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch new file mode 100644 index 00000000000..e474656bea6 --- /dev/null +++ b/queue-2.6.32/kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch @@ -0,0 +1,204 @@ +From stefan.bader@canonical.com Wed Apr 7 14:42:27 2010 +From: Gleb Natapov +Date: Fri, 19 Mar 2010 15:47:32 +0100 +Subject: KVM: x86 emulator: Check IOPL level during io instruction emulation +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-5-git-send-email-stefan.bader@canonical.com> + + +From: Gleb Natapov + +commit f850e2e603bf5a05b0aee7901857cf85715aa694 upstream + +Make emulator check that vcpu is allowed to execute IN, INS, OUT, +OUTS, CLI, STI. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/emulate.c | 89 ++++++++++++++++++++++++++++++++++++---- + arch/x86/kvm/x86.c | 10 +--- + 3 files changed, 87 insertions(+), 13 deletions(-) + +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -663,6 +663,7 @@ void kvm_disable_tdp(void); + + int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3); + int complete_pio(struct kvm_vcpu *vcpu); ++bool kvm_check_iopl(struct kvm_vcpu *vcpu); + + struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn); + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1620,6 +1620,57 @@ emulate_sysexit(struct x86_emulate_ctxt + return 0; + } + ++static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt) ++{ ++ int iopl; ++ if (ctxt->mode == X86EMUL_MODE_REAL) ++ return false; ++ if (ctxt->mode == X86EMUL_MODE_VM86) ++ return true; ++ iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT; ++ return kvm_x86_ops->get_cpl(ctxt->vcpu) > iopl; ++} ++ ++static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt, ++ struct x86_emulate_ops *ops, ++ u16 port, u16 len) ++{ ++ struct kvm_segment tr_seg; ++ int r; ++ u16 io_bitmap_ptr; ++ u8 perm, bit_idx = port & 0x7; ++ unsigned mask = (1 << len) - 1; ++ ++ kvm_get_segment(ctxt->vcpu, &tr_seg, VCPU_SREG_TR); ++ if (tr_seg.unusable) ++ return false; ++ if (tr_seg.limit < 103) ++ return false; ++ r = ops->read_std(tr_seg.base + 102, &io_bitmap_ptr, 2, ctxt->vcpu, ++ NULL); ++ if (r != X86EMUL_CONTINUE) ++ return false; ++ if (io_bitmap_ptr + port/8 > tr_seg.limit) ++ return false; ++ r = ops->read_std(tr_seg.base + io_bitmap_ptr + port/8, &perm, 1, ++ ctxt->vcpu, NULL); ++ if (r != X86EMUL_CONTINUE) ++ return false; ++ if ((perm >> bit_idx) & mask) ++ return false; ++ return true; ++} ++ ++static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt, ++ struct x86_emulate_ops *ops, ++ u16 port, u16 len) ++{ ++ if (emulator_bad_iopl(ctxt)) ++ if (!emulator_io_port_access_allowed(ctxt, ops, port, len)) ++ return false; ++ return true; ++} ++ + int + x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) + { +@@ -1779,7 +1830,12 @@ special_insn: + break; + case 0x6c: /* insb */ + case 0x6d: /* insw/insd */ +- if (kvm_emulate_pio_string(ctxt->vcpu, NULL, ++ if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], ++ (c->d & ByteOp) ? 1 : c->op_bytes)) { ++ kvm_inject_gp(ctxt->vcpu, 0); ++ goto done; ++ } ++ if (kvm_emulate_pio_string(ctxt->vcpu, NULL, + 1, + (c->d & ByteOp) ? 1 : c->op_bytes, + c->rep_prefix ? +@@ -1795,6 +1851,11 @@ special_insn: + return 0; + case 0x6e: /* outsb */ + case 0x6f: /* outsw/outsd */ ++ if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], ++ (c->d & ByteOp) ? 1 : c->op_bytes)) { ++ kvm_inject_gp(ctxt->vcpu, 0); ++ goto done; ++ } + if (kvm_emulate_pio_string(ctxt->vcpu, NULL, + 0, + (c->d & ByteOp) ? 1 : c->op_bytes, +@@ -2094,7 +2155,13 @@ special_insn: + case 0xef: /* out (e/r)ax,dx */ + port = c->regs[VCPU_REGS_RDX]; + io_dir_in = 0; +- do_io: if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in, ++ do_io: ++ if (!emulator_io_permited(ctxt, ops, port, ++ (c->d & ByteOp) ? 1 : c->op_bytes)) { ++ kvm_inject_gp(ctxt->vcpu, 0); ++ goto done; ++ } ++ if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in, + (c->d & ByteOp) ? 1 : c->op_bytes, + port) != 0) { + c->eip = saved_eip; +@@ -2119,13 +2186,21 @@ special_insn: + c->dst.type = OP_NONE; /* Disable writeback. */ + break; + case 0xfa: /* cli */ +- ctxt->eflags &= ~X86_EFLAGS_IF; +- c->dst.type = OP_NONE; /* Disable writeback. */ ++ if (emulator_bad_iopl(ctxt)) ++ kvm_inject_gp(ctxt->vcpu, 0); ++ else { ++ ctxt->eflags &= ~X86_EFLAGS_IF; ++ c->dst.type = OP_NONE; /* Disable writeback. */ ++ } + break; + case 0xfb: /* sti */ +- toggle_interruptibility(ctxt, X86_SHADOW_INT_STI); +- ctxt->eflags |= X86_EFLAGS_IF; +- c->dst.type = OP_NONE; /* Disable writeback. */ ++ if (emulator_bad_iopl(ctxt)) ++ kvm_inject_gp(ctxt->vcpu, 0); ++ else { ++ toggle_interruptibility(ctxt, X86_SHADOW_INT_STI); ++ ctxt->eflags |= X86_EFLAGS_IF; ++ c->dst.type = OP_NONE; /* Disable writeback. */ ++ } + break; + case 0xfc: /* cld */ + ctxt->eflags &= ~EFLG_DF; +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3079,6 +3079,8 @@ int kvm_emulate_pio(struct kvm_vcpu *vcp + { + unsigned long val; + ++ trace_kvm_pio(!in, port, size, 1); ++ + vcpu->run->exit_reason = KVM_EXIT_IO; + vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; + vcpu->run->io.size = vcpu->arch.pio.size = size; +@@ -3090,9 +3092,6 @@ int kvm_emulate_pio(struct kvm_vcpu *vcp + vcpu->arch.pio.down = 0; + vcpu->arch.pio.rep = 0; + +- trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port, +- size, 1); +- + val = kvm_register_read(vcpu, VCPU_REGS_RAX); + memcpy(vcpu->arch.pio_data, &val, 4); + +@@ -3111,6 +3110,8 @@ int kvm_emulate_pio_string(struct kvm_vc + unsigned now, in_page; + int ret = 0; + ++ trace_kvm_pio(!in, port, size, count); ++ + vcpu->run->exit_reason = KVM_EXIT_IO; + vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; + vcpu->run->io.size = vcpu->arch.pio.size = size; +@@ -3122,9 +3123,6 @@ int kvm_emulate_pio_string(struct kvm_vc + vcpu->arch.pio.down = down; + vcpu->arch.pio.rep = rep; + +- trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port, +- size, count); +- + if (!count) { + kvm_x86_ops->skip_emulated_instruction(vcpu); + return 1; diff --git a/queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch b/queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch new file mode 100644 index 00000000000..7bb6c340090 --- /dev/null +++ b/queue-2.6.32/kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch @@ -0,0 +1,512 @@ +From stefan.bader@canonical.com Wed Apr 7 14:42:11 2010 +From: Gleb Natapov +Date: Fri, 19 Mar 2010 15:47:31 +0100 +Subject: KVM: x86 emulator: fix memory access during x86 emulation +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-4-git-send-email-stefan.bader@canonical.com> + + +From: Gleb Natapov + +commit 1871c6020d7308afb99127bba51f04548e7ca84e upstream + +Currently when x86 emulator needs to access memory, page walk is done with +broadest permission possible, so if emulated instruction was executed +by userspace process it can still access kernel memory. Fix that by +providing correct memory access to page walker during emulation. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/kvm_emulate.h | 14 +++ + arch/x86/include/asm/kvm_host.h | 7 + + arch/x86/kvm/emulate.c | 6 - + arch/x86/kvm/mmu.c | 17 +--- + arch/x86/kvm/mmu.h | 6 + + arch/x86/kvm/paging_tmpl.h | 11 ++- + arch/x86/kvm/x86.c | 131 ++++++++++++++++++++++++++++--------- + 7 files changed, 142 insertions(+), 50 deletions(-) + +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -54,13 +54,23 @@ struct x86_emulate_ctxt; + struct x86_emulate_ops { + /* + * read_std: Read bytes of standard (non-emulated/special) memory. +- * Used for instruction fetch, stack operations, and others. ++ * Used for descriptor reading. + * @addr: [IN ] Linear address from which to read. + * @val: [OUT] Value read from memory, zero-extended to 'u_long'. + * @bytes: [IN ] Number of bytes to read from memory. + */ + int (*read_std)(unsigned long addr, void *val, +- unsigned int bytes, struct kvm_vcpu *vcpu); ++ unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error); ++ ++ /* ++ * fetch: Read bytes of standard (non-emulated/special) memory. ++ * Used for instruction fetch. ++ * @addr: [IN ] Linear address from which to read. ++ * @val: [OUT] Value read from memory, zero-extended to 'u_long'. ++ * @bytes: [IN ] Number of bytes to read from memory. ++ */ ++ int (*fetch)(unsigned long addr, void *val, ++ unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error); + + /* + * read_emulated: Read bytes from emulated/special memory area. +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -256,7 +256,8 @@ struct kvm_mmu { + void (*new_cr3)(struct kvm_vcpu *vcpu); + int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err); + void (*free)(struct kvm_vcpu *vcpu); +- gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva); ++ gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access, ++ u32 *error); + void (*prefetch_page)(struct kvm_vcpu *vcpu, + struct kvm_mmu_page *page); + int (*sync_page)(struct kvm_vcpu *vcpu, +@@ -645,6 +646,10 @@ void __kvm_mmu_free_some_pages(struct kv + int kvm_mmu_load(struct kvm_vcpu *vcpu); + void kvm_mmu_unload(struct kvm_vcpu *vcpu); + void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu); ++gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error); ++gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error); ++gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error); ++gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error); + + int kvm_emulate_hypercall(struct kvm_vcpu *vcpu); + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -612,7 +612,7 @@ static int do_fetch_insn_byte(struct x86 + + if (linear < fc->start || linear >= fc->end) { + size = min(15UL, PAGE_SIZE - offset_in_page(linear)); +- rc = ops->read_std(linear, fc->data, size, ctxt->vcpu); ++ rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL); + if (rc) + return rc; + fc->start = linear; +@@ -667,11 +667,11 @@ static int read_descriptor(struct x86_em + op_bytes = 3; + *address = 0; + rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, +- ctxt->vcpu); ++ ctxt->vcpu, NULL); + if (rc) + return rc; + rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, +- ctxt->vcpu); ++ ctxt->vcpu, NULL); + return rc; + } + +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -136,12 +136,6 @@ module_param(oos_shadow, bool, 0644); + #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \ + | PT64_NX_MASK) + +-#define PFERR_PRESENT_MASK (1U << 0) +-#define PFERR_WRITE_MASK (1U << 1) +-#define PFERR_USER_MASK (1U << 2) +-#define PFERR_RSVD_MASK (1U << 3) +-#define PFERR_FETCH_MASK (1U << 4) +- + #define PT_PDPE_LEVEL 3 + #define PT_DIRECTORY_LEVEL 2 + #define PT_PAGE_TABLE_LEVEL 1 +@@ -1639,7 +1633,7 @@ struct page *gva_to_page(struct kvm_vcpu + { + struct page *page; + +- gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); ++ gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); + + if (gpa == UNMAPPED_GVA) + return NULL; +@@ -2162,8 +2156,11 @@ void kvm_mmu_sync_roots(struct kvm_vcpu + spin_unlock(&vcpu->kvm->mmu_lock); + } + +-static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) ++static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr, ++ u32 access, u32 *error) + { ++ if (error) ++ *error = 0; + return vaddr; + } + +@@ -2747,7 +2744,7 @@ int kvm_mmu_unprotect_page_virt(struct k + if (tdp_enabled) + return 0; + +- gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); ++ gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); + + spin_lock(&vcpu->kvm->mmu_lock); + r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT); +@@ -3245,7 +3242,7 @@ static void audit_mappings_page(struct k + if (is_shadow_present_pte(ent) && !is_last_spte(ent, level)) + audit_mappings_page(vcpu, ent, va, level - 1); + else { +- gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va); ++ gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL); + gfn_t gfn = gpa >> PAGE_SHIFT; + pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn); + hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT; +--- a/arch/x86/kvm/mmu.h ++++ b/arch/x86/kvm/mmu.h +@@ -37,6 +37,12 @@ + #define PT32_ROOT_LEVEL 2 + #define PT32E_ROOT_LEVEL 3 + ++#define PFERR_PRESENT_MASK (1U << 0) ++#define PFERR_WRITE_MASK (1U << 1) ++#define PFERR_USER_MASK (1U << 2) ++#define PFERR_RSVD_MASK (1U << 3) ++#define PFERR_FETCH_MASK (1U << 4) ++ + int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]); + + static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) +--- a/arch/x86/kvm/paging_tmpl.h ++++ b/arch/x86/kvm/paging_tmpl.h +@@ -491,18 +491,23 @@ static void FNAME(invlpg)(struct kvm_vcp + spin_unlock(&vcpu->kvm->mmu_lock); + } + +-static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) ++static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access, ++ u32 *error) + { + struct guest_walker walker; + gpa_t gpa = UNMAPPED_GVA; + int r; + +- r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0); ++ r = FNAME(walk_addr)(&walker, vcpu, vaddr, ++ !!(access & PFERR_WRITE_MASK), ++ !!(access & PFERR_USER_MASK), ++ !!(access & PFERR_FETCH_MASK)); + + if (r) { + gpa = gfn_to_gpa(walker.gfn); + gpa |= vaddr & ~PAGE_MASK; +- } ++ } else if (error) ++ *error = walker.error_code; + + return gpa; + } +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -2505,14 +2505,41 @@ static int vcpu_mmio_read(struct kvm_vcp + return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v); + } + +-static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, +- struct kvm_vcpu *vcpu) ++gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error) ++{ ++ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; ++ return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error); ++} ++ ++ gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error) ++{ ++ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; ++ access |= PFERR_FETCH_MASK; ++ return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error); ++} ++ ++gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error) ++{ ++ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; ++ access |= PFERR_WRITE_MASK; ++ return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error); ++} ++ ++/* uses this to access any guest's mapped memory without checking CPL */ ++gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error) ++{ ++ return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, 0, error); ++} ++ ++static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes, ++ struct kvm_vcpu *vcpu, u32 access, ++ u32 *error) + { + void *data = val; + int r = X86EMUL_CONTINUE; + + while (bytes) { +- gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); ++ gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, access, error); + unsigned offset = addr & (PAGE_SIZE-1); + unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset); + int ret; +@@ -2535,14 +2562,37 @@ out: + return r; + } + ++/* used for instruction fetching */ ++static int kvm_fetch_guest_virt(gva_t addr, void *val, unsigned int bytes, ++ struct kvm_vcpu *vcpu, u32 *error) ++{ ++ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; ++ return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, ++ access | PFERR_FETCH_MASK, error); ++} ++ ++static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, ++ struct kvm_vcpu *vcpu, u32 *error) ++{ ++ u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; ++ return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, ++ error); ++} ++ ++static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes, ++ struct kvm_vcpu *vcpu, u32 *error) ++{ ++ return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error); ++} ++ + static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes, +- struct kvm_vcpu *vcpu) ++ struct kvm_vcpu *vcpu, u32 *error) + { + void *data = val; + int r = X86EMUL_CONTINUE; + + while (bytes) { +- gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); ++ gpa_t gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error); + unsigned offset = addr & (PAGE_SIZE-1); + unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset); + int ret; +@@ -2572,6 +2622,7 @@ static int emulator_read_emulated(unsign + struct kvm_vcpu *vcpu) + { + gpa_t gpa; ++ u32 error_code; + + if (vcpu->mmio_read_completed) { + memcpy(val, vcpu->mmio_data, bytes); +@@ -2581,17 +2632,20 @@ static int emulator_read_emulated(unsign + return X86EMUL_CONTINUE; + } + +- gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); ++ gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, &error_code); ++ ++ if (gpa == UNMAPPED_GVA) { ++ kvm_inject_page_fault(vcpu, addr, error_code); ++ return X86EMUL_PROPAGATE_FAULT; ++ } + + /* For APIC access vmexit */ + if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) + goto mmio; + +- if (kvm_read_guest_virt(addr, val, bytes, vcpu) ++ if (kvm_read_guest_virt(addr, val, bytes, vcpu, NULL) + == X86EMUL_CONTINUE) + return X86EMUL_CONTINUE; +- if (gpa == UNMAPPED_GVA) +- return X86EMUL_PROPAGATE_FAULT; + + mmio: + /* +@@ -2630,11 +2684,12 @@ static int emulator_write_emulated_onepa + struct kvm_vcpu *vcpu) + { + gpa_t gpa; ++ u32 error_code; + +- gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); ++ gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, &error_code); + + if (gpa == UNMAPPED_GVA) { +- kvm_inject_page_fault(vcpu, addr, 2); ++ kvm_inject_page_fault(vcpu, addr, error_code); + return X86EMUL_PROPAGATE_FAULT; + } + +@@ -2698,7 +2753,7 @@ static int emulator_cmpxchg_emulated(uns + char *kaddr; + u64 val; + +- gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); ++ gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL); + + if (gpa == UNMAPPED_GVA || + (gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) +@@ -2777,7 +2832,7 @@ void kvm_report_emulation_failure(struct + + rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS); + +- kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu); ++ kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu, NULL); + + printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n", + context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); +@@ -2785,7 +2840,8 @@ void kvm_report_emulation_failure(struct + EXPORT_SYMBOL_GPL(kvm_report_emulation_failure); + + static struct x86_emulate_ops emulate_ops = { +- .read_std = kvm_read_guest_virt, ++ .read_std = kvm_read_guest_virt_system, ++ .fetch = kvm_fetch_guest_virt, + .read_emulated = emulator_read_emulated, + .write_emulated = emulator_write_emulated, + .cmpxchg_emulated = emulator_cmpxchg_emulated, +@@ -2922,12 +2978,17 @@ static int pio_copy_data(struct kvm_vcpu + gva_t q = vcpu->arch.pio.guest_gva; + unsigned bytes; + int ret; ++ u32 error_code; + + bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count; + if (vcpu->arch.pio.in) +- ret = kvm_write_guest_virt(q, p, bytes, vcpu); ++ ret = kvm_write_guest_virt(q, p, bytes, vcpu, &error_code); + else +- ret = kvm_read_guest_virt(q, p, bytes, vcpu); ++ ret = kvm_read_guest_virt(q, p, bytes, vcpu, &error_code); ++ ++ if (ret == X86EMUL_PROPAGATE_FAULT) ++ kvm_inject_page_fault(vcpu, q, error_code); ++ + return ret; + } + +@@ -2948,7 +3009,7 @@ int complete_pio(struct kvm_vcpu *vcpu) + if (io->in) { + r = pio_copy_data(vcpu); + if (r) +- return r; ++ goto out; + } + + delta = 1; +@@ -2975,7 +3036,7 @@ int complete_pio(struct kvm_vcpu *vcpu) + kvm_register_write(vcpu, VCPU_REGS_RSI, val); + } + } +- ++out: + io->count -= io->cur_count; + io->cur_count = 0; + +@@ -3095,10 +3156,8 @@ int kvm_emulate_pio_string(struct kvm_vc + if (!vcpu->arch.pio.in) { + /* string PIO write */ + ret = pio_copy_data(vcpu); +- if (ret == X86EMUL_PROPAGATE_FAULT) { +- kvm_inject_gp(vcpu, 0); ++ if (ret == X86EMUL_PROPAGATE_FAULT) + return 1; +- } + if (ret == 0 && !pio_string_write(vcpu)) { + complete_pio(vcpu); + if (vcpu->arch.pio.count == 0) +@@ -4078,7 +4137,9 @@ static int load_guest_segment_descriptor + kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc); + return 1; + } +- return kvm_read_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu); ++ return kvm_read_guest_virt_system(dtable.base + index*8, ++ seg_desc, sizeof(*seg_desc), ++ vcpu, NULL); + } + + /* allowed just for 8 bytes segments */ +@@ -4092,15 +4153,23 @@ static int save_guest_segment_descriptor + + if (dtable.limit < index * 8 + 7) + return 1; +- return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu); ++ return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu, NULL); ++} ++ ++static gpa_t get_tss_base_addr_write(struct kvm_vcpu *vcpu, ++ struct desc_struct *seg_desc) ++{ ++ u32 base_addr = get_desc_base(seg_desc); ++ ++ return kvm_mmu_gva_to_gpa_write(vcpu, base_addr, NULL); + } + +-static gpa_t get_tss_base_addr(struct kvm_vcpu *vcpu, ++static gpa_t get_tss_base_addr_read(struct kvm_vcpu *vcpu, + struct desc_struct *seg_desc) + { + u32 base_addr = get_desc_base(seg_desc); + +- return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr); ++ return kvm_mmu_gva_to_gpa_read(vcpu, base_addr, NULL); + } + + static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg) +@@ -4303,7 +4372,7 @@ static int kvm_task_switch_16(struct kvm + sizeof tss_segment_16)) + goto out; + +- if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc), ++ if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc), + &tss_segment_16, sizeof tss_segment_16)) + goto out; + +@@ -4311,7 +4380,7 @@ static int kvm_task_switch_16(struct kvm + tss_segment_16.prev_task_link = old_tss_sel; + + if (kvm_write_guest(vcpu->kvm, +- get_tss_base_addr(vcpu, nseg_desc), ++ get_tss_base_addr_write(vcpu, nseg_desc), + &tss_segment_16.prev_task_link, + sizeof tss_segment_16.prev_task_link)) + goto out; +@@ -4342,7 +4411,7 @@ static int kvm_task_switch_32(struct kvm + sizeof tss_segment_32)) + goto out; + +- if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc), ++ if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc), + &tss_segment_32, sizeof tss_segment_32)) + goto out; + +@@ -4350,7 +4419,7 @@ static int kvm_task_switch_32(struct kvm + tss_segment_32.prev_task_link = old_tss_sel; + + if (kvm_write_guest(vcpu->kvm, +- get_tss_base_addr(vcpu, nseg_desc), ++ get_tss_base_addr_write(vcpu, nseg_desc), + &tss_segment_32.prev_task_link, + sizeof tss_segment_32.prev_task_link)) + goto out; +@@ -4373,7 +4442,7 @@ int kvm_task_switch(struct kvm_vcpu *vcp + u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR); + u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR); + +- old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base); ++ old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL); + + /* FIXME: Handle errors. Failure to read either TSS or their + * descriptors should generate a pagefault. +@@ -4582,7 +4651,7 @@ int kvm_arch_vcpu_ioctl_translate(struct + + vcpu_load(vcpu); + down_read(&vcpu->kvm->slots_lock); +- gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr); ++ gpa = kvm_mmu_gva_to_gpa_system(vcpu, vaddr, NULL); + up_read(&vcpu->kvm->slots_lock); + tr->physical_address = gpa; + tr->valid = gpa != UNMAPPED_GVA; diff --git a/queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch b/queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch new file mode 100644 index 00000000000..07d6ec48344 --- /dev/null +++ b/queue-2.6.32/kvm-x86-emulator-fix-popf-emulation.patch @@ -0,0 +1,107 @@ +From stefan.bader@canonical.com Wed Apr 7 14:42:41 2010 +From: Gleb Natapov +Date: Fri, 19 Mar 2010 15:47:33 +0100 +Subject: KVM: x86 emulator: Fix popf emulation +To: stable@kernel.org +Cc: Marcelo Tosatti , Avi Kivity , Gleb Natapov +Message-ID: <1269010059-25309-6-git-send-email-stefan.bader@canonical.com> + + +From: Gleb Natapov + +commit d4c6a1549c056f1d817e8f6f2f97d8b44933472f upstream + +POPF behaves differently depending on current CPU mode. Emulate correct +logic to prevent guest from changing flags that it can't change otherwise. + +Signed-off-by: Gleb Natapov +Signed-off-by: Avi Kivity +Signed-off-by: Stefan Bader +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/emulate.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 54 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -339,11 +339,18 @@ static u32 group2_table[] = { + }; + + /* EFLAGS bit definitions. */ ++#define EFLG_ID (1<<21) ++#define EFLG_VIP (1<<20) ++#define EFLG_VIF (1<<19) ++#define EFLG_AC (1<<18) + #define EFLG_VM (1<<17) + #define EFLG_RF (1<<16) ++#define EFLG_IOPL (3<<12) ++#define EFLG_NT (1<<14) + #define EFLG_OF (1<<11) + #define EFLG_DF (1<<10) + #define EFLG_IF (1<<9) ++#define EFLG_TF (1<<8) + #define EFLG_SF (1<<7) + #define EFLG_ZF (1<<6) + #define EFLG_AF (1<<4) +@@ -1205,6 +1212,49 @@ static int emulate_pop(struct x86_emulat + return rc; + } + ++static int emulate_popf(struct x86_emulate_ctxt *ctxt, ++ struct x86_emulate_ops *ops, ++ void *dest, int len) ++{ ++ int rc; ++ unsigned long val, change_mask; ++ int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT; ++ int cpl = kvm_x86_ops->get_cpl(ctxt->vcpu); ++ ++ rc = emulate_pop(ctxt, ops, &val, len); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; ++ ++ change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF ++ | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID; ++ ++ switch(ctxt->mode) { ++ case X86EMUL_MODE_PROT64: ++ case X86EMUL_MODE_PROT32: ++ case X86EMUL_MODE_PROT16: ++ if (cpl == 0) ++ change_mask |= EFLG_IOPL; ++ if (cpl <= iopl) ++ change_mask |= EFLG_IF; ++ break; ++ case X86EMUL_MODE_VM86: ++ if (iopl < 3) { ++ kvm_inject_gp(ctxt->vcpu, 0); ++ return X86EMUL_PROPAGATE_FAULT; ++ } ++ change_mask |= EFLG_IF; ++ break; ++ default: /* real mode */ ++ change_mask |= (EFLG_IOPL | EFLG_IF); ++ break; ++ } ++ ++ *(unsigned long *)dest = ++ (ctxt->eflags & ~change_mask) | (val & change_mask); ++ ++ return rc; ++} ++ + static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops) + { +@@ -1995,7 +2045,10 @@ special_insn: + c->dst.type = OP_REG; + c->dst.ptr = (unsigned long *) &ctxt->eflags; + c->dst.bytes = c->op_bytes; +- goto pop_instruction; ++ rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes); ++ if (rc != X86EMUL_CONTINUE) ++ goto done; ++ break; + case 0xa0 ... 0xa1: /* mov */ + c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; + c->dst.val = c->src.val; diff --git a/queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch b/queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch new file mode 100644 index 00000000000..00bbe2e27eb --- /dev/null +++ b/queue-2.6.32/libata-disable-ncq-on-crucial-c300-ssd.patch @@ -0,0 +1,55 @@ +From 68b0ddb289220b6d4d865be128939663be34959d Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Mon, 5 Apr 2010 10:51:26 +0900 +Subject: libata: disable NCQ on Crucial C300 SSD +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tejun Heo + +commit 68b0ddb289220b6d4d865be128939663be34959d upstream. + +Crucial said, + + Thank you for contacting us. We know that with our M225 line of SSDs + you sometimes need to disable NCQ (native command queuing) to avoid + just the type of errors you're seeing. Our recommendation for the + M225 is to add libata.force=noncq to your Linux kernel boot options, + under the kernel ATA library option. + + I have sent your feedback to the engineers working on the C300, and + asked them to please pass it on to the firmware team. I have been + notified that they are in the process of testing and finalizing a + new firmware version, that you can expect to see released around the + end of April. We’ll keep you posted as to when it will be available + for download. + +So, turn off NCQ on the drive w/ the current firmware revision. + +Reported in the following bug. + + https://bugzilla.kernel.org/show_bug.cgi?id=15573 + +Signed-off-by: Tejun Heo +Reported-by: lethalwp@scarlet.be +Reported-by: Luke Macken +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4348,6 +4348,9 @@ static const struct ata_blacklist_entry + { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, + { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, + ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */ ++ { "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, }, ++ + /* devices which puke on READ_NATIVE_MAX */ + { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, + { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, diff --git a/queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch b/queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch new file mode 100644 index 00000000000..9ab9b60af0b --- /dev/null +++ b/queue-2.6.32/libata-unlock-hpa-if-device-shrunk.patch @@ -0,0 +1,149 @@ +From 445d211b0da4e9a6e6d576edff85085c2aaf53df Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Mon, 5 Apr 2010 10:33:13 +0900 +Subject: libata: unlock HPA if device shrunk + +From: Tejun Heo + +commit 445d211b0da4e9a6e6d576edff85085c2aaf53df upstream. + +Some BIOSes don't configure HPA during boot but do so while resuming. +This causes harddrives to shrink during resume making libata detach +and reattach them. This can be worked around by unlocking HPA if old +size equals native size. + +Add ATA_DFLAG_UNLOCK_HPA so that HPA unlocking can be controlled +per-device and update ata_dev_revalidate() such that it sets +ATA_DFLAG_UNLOCK_HPA and fails with -EIO when the above condition is +detected. + +This patch fixes the following bug. + + https://bugzilla.kernel.org/show_bug.cgi?id=15396 + +Signed-off-by: Tejun Heo +Reported-by: Oleksandr Yermolenko +Signed-off-by: Jeff Garzik + +--- + drivers/ata/libata-core.c | 74 +++++++++++++++++++++++++++------------------- + include/linux/libata.h | 1 + 2 files changed, 46 insertions(+), 29 deletions(-) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -1493,6 +1493,7 @@ static int ata_hpa_resize(struct ata_dev + { + struct ata_eh_context *ehc = &dev->link->eh_context; + int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; ++ bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA; + u64 sectors = ata_id_n_sectors(dev->id); + u64 native_sectors; + int rc; +@@ -1509,7 +1510,7 @@ static int ata_hpa_resize(struct ata_dev + /* If device aborted the command or HPA isn't going to + * be unlocked, skip HPA resizing. + */ +- if (rc == -EACCES || !ata_ignore_hpa) { ++ if (rc == -EACCES || !unlock_hpa) { + ata_dev_printk(dev, KERN_WARNING, "HPA support seems " + "broken, skipping HPA handling\n"); + dev->horkage |= ATA_HORKAGE_BROKEN_HPA; +@@ -1524,7 +1525,7 @@ static int ata_hpa_resize(struct ata_dev + dev->n_native_sectors = native_sectors; + + /* nothing to do? */ +- if (native_sectors <= sectors || !ata_ignore_hpa) { ++ if (native_sectors <= sectors || !unlock_hpa) { + if (!print_info || native_sectors == sectors) + return 0; + +@@ -4180,36 +4181,51 @@ int ata_dev_revalidate(struct ata_device + goto fail; + + /* verify n_sectors hasn't changed */ +- if (dev->class == ATA_DEV_ATA && n_sectors && +- dev->n_sectors != n_sectors) { +- ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " +- "%llu != %llu\n", +- (unsigned long long)n_sectors, +- (unsigned long long)dev->n_sectors); +- /* +- * Something could have caused HPA to be unlocked +- * involuntarily. If n_native_sectors hasn't changed +- * and the new size matches it, keep the device. +- */ +- if (dev->n_native_sectors == n_native_sectors && +- dev->n_sectors > n_sectors && +- dev->n_sectors == n_native_sectors) { +- ata_dev_printk(dev, KERN_WARNING, +- "new n_sectors matches native, probably " +- "late HPA unlock, continuing\n"); +- /* keep using the old n_sectors */ +- dev->n_sectors = n_sectors; +- } else { +- /* restore original n_[native]_sectors and fail */ +- dev->n_native_sectors = n_native_sectors; +- dev->n_sectors = n_sectors; +- rc = -ENODEV; +- goto fail; +- } ++ if (dev->class != ATA_DEV_ATA || !n_sectors || ++ dev->n_sectors == n_sectors) ++ return 0; ++ ++ /* n_sectors has changed */ ++ ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n", ++ (unsigned long long)n_sectors, ++ (unsigned long long)dev->n_sectors); ++ ++ /* ++ * Something could have caused HPA to be unlocked ++ * involuntarily. If n_native_sectors hasn't changed and the ++ * new size matches it, keep the device. ++ */ ++ if (dev->n_native_sectors == n_native_sectors && ++ dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) { ++ ata_dev_printk(dev, KERN_WARNING, ++ "new n_sectors matches native, probably " ++ "late HPA unlock, continuing\n"); ++ /* keep using the old n_sectors */ ++ dev->n_sectors = n_sectors; ++ return 0; + } + +- return 0; ++ /* ++ * Some BIOSes boot w/o HPA but resume w/ HPA locked. Try ++ * unlocking HPA in those cases. ++ * ++ * https://bugzilla.kernel.org/show_bug.cgi?id=15396 ++ */ ++ if (dev->n_native_sectors == n_native_sectors && ++ dev->n_sectors < n_sectors && n_sectors == n_native_sectors && ++ !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) { ++ ata_dev_printk(dev, KERN_WARNING, ++ "old n_sectors matches native, probably " ++ "late HPA lock, will try to unlock HPA\n"); ++ /* try unlocking HPA */ ++ dev->flags |= ATA_DFLAG_UNLOCK_HPA; ++ rc = -EIO; ++ } else ++ rc = -ENODEV; + ++ /* restore original n_[native_]sectors and fail */ ++ dev->n_native_sectors = n_native_sectors; ++ dev->n_sectors = n_sectors; + fail: + ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); + return rc; +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -146,6 +146,7 @@ enum { + ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ + ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */ + ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ ++ ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ + ATA_DFLAG_INIT_MASK = (1 << 24) - 1, + + ATA_DFLAG_DETACH = (1 << 24), diff --git a/queue-2.6.32/pata_via-add-via-vx900-support.patch b/queue-2.6.32/pata_via-add-via-vx900-support.patch new file mode 100644 index 00000000000..f8e37c827c3 --- /dev/null +++ b/queue-2.6.32/pata_via-add-via-vx900-support.patch @@ -0,0 +1,27 @@ +From 4f1deba435ef75380c1d06fda860c7a15ea16fdf Mon Sep 17 00:00:00 2001 +From: JosephChan@via.com.tw +Date: Fri, 19 Mar 2010 14:08:11 +0800 +Subject: pata_via: Add VIA VX900 support + +From: JosephChan@via.com.tw + +commit 4f1deba435ef75380c1d06fda860c7a15ea16fdf upstream. + +Signed-off-by: Joseph Chan +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/pata_via.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/ata/pata_via.c ++++ b/drivers/ata/pata_via.c +@@ -661,6 +661,7 @@ static const struct pci_device_id via[] + { PCI_VDEVICE(VIA, 0x3164), }, + { PCI_VDEVICE(VIA, 0x5324), }, + { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE }, ++ { PCI_VDEVICE(VIA, 0x9001), VIA_IDFLAG_SINGLE }, + + { }, + }; diff --git a/queue-2.6.32/raw-fsync-method-is-now-required.patch b/queue-2.6.32/raw-fsync-method-is-now-required.patch new file mode 100644 index 00000000000..4b5ddfebb34 --- /dev/null +++ b/queue-2.6.32/raw-fsync-method-is-now-required.patch @@ -0,0 +1,89 @@ +From 55ab3a1ff843e3f0e24d2da44e71bffa5d853010 Mon Sep 17 00:00:00 2001 +From: Anton Blanchard +Date: Tue, 6 Apr 2010 14:34:58 -0700 +Subject: raw: fsync method is now required + +From: Anton Blanchard + +commit 55ab3a1ff843e3f0e24d2da44e71bffa5d853010 upstream. + +Commit 148f948ba877f4d3cdef036b1ff6d9f68986706a (vfs: Introduce new +helpers for syncing after writing to O_SYNC file or IS_SYNC inode) broke +the raw driver. + +We now call through generic_file_aio_write -> generic_write_sync -> +vfs_fsync_range. vfs_fsync_range has: + + if (!fop || !fop->fsync) { + ret = -EINVAL; + goto out; + } + +But drivers/char/raw.c doesn't set an fsync method. + +We have two options: fix it or remove the raw driver completely. I'm +happy to do either, the fact this has been broken for so long suggests it +is rarely used. + +The patch below adds an fsync method to the raw driver. My knowledge of +the block layer is pretty sketchy so this could do with a once over. + +If we instead decide to remove the raw driver, this patch might still be +useful as a backport to 2.6.33 and 2.6.32. + +Signed-off-by: Anton Blanchard +Reviewed-by: Jan Kara +Cc: Christoph Hellwig +Cc: Alexander Viro +Cc: Jens Axboe +Reviewed-by: Jeff Moyer +Tested-by: Jeff Moyer +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/raw.c | 1 + + fs/block_dev.c | 3 ++- + include/linux/fs.h | 1 + + 3 files changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/char/raw.c ++++ b/drivers/char/raw.c +@@ -247,6 +247,7 @@ static const struct file_operations raw_ + .aio_read = generic_file_aio_read, + .write = do_sync_write, + .aio_write = blkdev_aio_write, ++ .fsync = block_fsync, + .open = raw_open, + .release= raw_release, + .ioctl = raw_ioctl, +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -404,7 +404,7 @@ static loff_t block_llseek(struct file * + * NULL first argument is nfsd_sync_dir() and that's not a directory. + */ + +-static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) ++int block_fsync(struct file *filp, struct dentry *dentry, int datasync) + { + return sync_blockdev(I_BDEV(filp->f_mapping->host)); + } +@@ -423,6 +423,7 @@ static struct inode *bdev_alloc_inode(st + return NULL; + return &ei->vfs_inode; + } ++EXPORT_SYMBOL(block_fsync); + + static void bdev_destroy_inode(struct inode *inode) + { +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2225,6 +2225,7 @@ extern int generic_segment_checks(const + /* fs/block_dev.c */ + extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos); ++extern int block_fsync(struct file *filp, struct dentry *dentry, int datasync); + + /* fs/splice.c */ + extern ssize_t generic_file_splice_read(struct file *, loff_t *, diff --git a/queue-2.6.32/readahead-fix-null-filp-dereference.patch b/queue-2.6.32/readahead-fix-null-filp-dereference.patch new file mode 100644 index 00000000000..ffede33b903 --- /dev/null +++ b/queue-2.6.32/readahead-fix-null-filp-dereference.patch @@ -0,0 +1,37 @@ +From 70655c06bd3f25111312d63985888112aed15ac5 Mon Sep 17 00:00:00 2001 +From: Wu Fengguang +Date: Tue, 6 Apr 2010 14:34:53 -0700 +Subject: readahead: fix NULL filp dereference + +From: Wu Fengguang + +commit 70655c06bd3f25111312d63985888112aed15ac5 upstream. + +btrfs relocate_file_extent_cluster() calls us with NULL filp: + + [ 4005.426805] BUG: unable to handle kernel NULL pointer dereference at 00000021 + [ 4005.426818] IP: [] page_cache_sync_readahead+0x18/0x3e + +Signed-off-by: Wu Fengguang +Cc: Yan Zheng +Reported-by: Kirill A. Shutemov +Tested-by: Kirill A. Shutemov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/readahead.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -502,7 +502,7 @@ void page_cache_sync_readahead(struct ad + return; + + /* be dumb */ +- if (filp->f_mode & FMODE_RANDOM) { ++ if (filp && (filp->f_mode & FMODE_RANDOM)) { + force_page_cache_readahead(mapping, filp, offset, req_size); + return; + } diff --git a/queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch b/queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch new file mode 100644 index 00000000000..aa6ba5f50d8 --- /dev/null +++ b/queue-2.6.32/resource-move-kernel-function-inside-__kernel__.patch @@ -0,0 +1,76 @@ +From max@stro.at Wed Apr 7 14:36:07 2010 +From: Jiri Slaby +Date: Fri, 19 Mar 2010 02:51:56 +0100 +Subject: resource: move kernel function inside __KERNEL__ +To: Greg KH +Cc: stable@kernel.org, Jiri Slaby +Message-ID: <20100319015156.GC4424@stro.at> + +commit 96d07d211739fd2450ac54e81d00fa40fcd4b1bd upstream +From: Jiri Slaby + +resource: move kernel function inside __KERNEL__ + +It is an internal function. Move it inside __KERNEL__ ifdef, along +with task_struct declaration. + +Then we get: +#--- /usr/include/linux/resource.h 2009-09-14 15:09:29.000000000 +0200 +#+++ usr/include/linux/resource.h 2010-01-04 11:30:54.000000000 +0100 +#@@ -3,8 +3,6 @@ +# +##include +# +#-struct task_struct; +#- +#/* +#* Resource control/accounting header file for linux +#*/ +#@@ -70,6 +68,5 @@ +#*/ +##include +# +#-int getrusage(struct task_struct *p, int who, struct rusage *ru); +# +##endif +# +#*********** + +include/linux/Kbuild is untouched, since unifdef is run even on +headers-y nowadays. + +backport to 2.6.32 by maximilian attems +Patch commented out by gregkh due to quilt complaining. + +Signed-off-by: Jiri Slaby +Cc: maximilian attems +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/resource.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/include/linux/resource.h ++++ b/include/linux/resource.h +@@ -3,8 +3,6 @@ + + #include + +-struct task_struct; +- + /* + * Resource control/accounting header file for linux + */ +@@ -70,6 +68,12 @@ struct rlimit { + */ + #include + ++#ifdef __KERNEL__ ++ ++struct task_struct; ++ + int getrusage(struct task_struct *p, int who, struct rusage __user *ru); + ++#endif /* __KERNEL__ */ ++ + #endif diff --git a/queue-2.6.32/series b/queue-2.6.32/series index 9d4f7112977..3909603fffb 100644 --- a/queue-2.6.32/series +++ b/queue-2.6.32/series @@ -41,3 +41,42 @@ genirq-force-msi-irq-handlers-to-run-with-interrupts-disabled.patch tty-release_one_tty-forgets-to-put-pids.patch lis3-fix-show-rate-for-8-bits-chips.patch pata_ali-fix-regression-with-old-devices.patch +hid-fix-oops-in-gyration_event.patch +raw-fsync-method-is-now-required.patch +readahead-fix-null-filp-dereference.patch +alsa-mixart-range-checking-proc-file.patch +alsa-hda-fix-0-db-offset-for-lenovo-thinkpad-models-using-ad1981.patch +x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch +resource-move-kernel-function-inside-__kernel__.patch +backlight-mbp_nvidia_bl-add-five-more-macbook-variants.patch +kvm-x86-emulator-add-virtual-8086-mode-of-emulation.patch +kvm-x86-emulator-fix-memory-access-during-x86-emulation.patch +kvm-x86-emulator-check-iopl-level-during-io-instruction-emulation.patch +kvm-x86-emulator-fix-popf-emulation.patch +kvm-fix-segment-descriptor-loading.patch +kvm-vmx-update-instruction-length-on-intercepted-bp.patch +kvm-vmx-use-macros-instead-of-hex-value-on-cr0-initialization.patch +kvm-svm-reset-cr0-properly-on-vcpu-reset.patch +kvm-vmx-disable-unrestricted-guest-when-ept-disabled.patch +kvm-x86-disable-paravirt-mmu-reporting.patch +pata_via-add-via-vx900-support.patch +ext3-don-t-update-the-superblock-in-ext3_statfs.patch +ext3-journal-all-modifications-in-ext3_xattr_set_handle.patch +thinkpad-acpi-fix-some-version-quirks.patch +thinkpad-acpi-issue-backlight-class-events.patch +thinkpad-acpi-silence-bogus-complain-during-rmmod.patch +thinkpad-acpi-adopt-input-device.patch +thinkpad-acpi-expose-module-parameters.patch +thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch +thinkpad-acpi-use-input_set_capability.patch +thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch +thinkpad-acpi-log-initial-state-of-rfkill-switches.patch +thinkpad-acpi-convert-to-seq_file.patch +thinkpad-acpi-lock-down-video-output-state-access.patch +eeepc-laptop-disable-cpu-speed-control-on-eeepc-701.patch +eeepc-laptop-dmi-blacklist-to-disable-pci-hotplug-code.patch +eeepc-laptop-add-hotplug_disable-parameter.patch +eeepc-laptop-disable-wireless-hotplug-for-1201n.patch +eeepc-laptop-disable-wireless-hotplug-for-1005pe.patch +libata-disable-ncq-on-crucial-c300-ssd.patch +libata-unlock-hpa-if-device-shrunk.patch diff --git a/queue-2.6.32/thinkpad-acpi-adopt-input-device.patch b/queue-2.6.32/thinkpad-acpi-adopt-input-device.patch new file mode 100644 index 00000000000..5cac2091bbd --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-adopt-input-device.patch @@ -0,0 +1,31 @@ +From d112ef95d4ec1ee7fe7123e3f21e4aac0d57570c Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:26 +0000 +Subject: thinkpad-acpi: adopt input device + +From: Henrique de Moraes Holschuh + +commit d112ef95d4ec1ee7fe7123e3f21e4aac0d57570c upstream. + +Properly init the parent field of the input device. Thanks to Alan +Jenkins, who noted this problem in a different driver. + +Reported-by: Alan Jenkins +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -8385,6 +8385,7 @@ static int __init thinkpad_acpi_module_i + PCI_VENDOR_ID_IBM; + tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; + tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; ++ tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; + } + for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { + ret = ibm_init(&ibms_init[i]); diff --git a/queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch b/queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch new file mode 100644 index 00000000000..05dc51ac179 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-convert-to-seq_file.patch @@ -0,0 +1,648 @@ +From 887965e6576a78f71b9b98dec43fd1c73becd2e8 Mon Sep 17 00:00:00 2001 +From: Alexey Dobriyan +Date: Tue, 15 Dec 2009 21:51:12 -0200 +Subject: thinkpad-acpi: convert to seq_file + +From: Alexey Dobriyan + +commit 887965e6576a78f71b9b98dec43fd1c73becd2e8 upstream. + +(hmh@hmh.eng.br: Updated to apply to 2.6.32.y) + +Signed-off-by: Alexey Dobriyan +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 282 ++++++++++++++++------------------- + 1 file changed, 131 insertions(+), 151 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -61,6 +61,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -256,7 +257,7 @@ struct tp_acpi_drv_struct { + struct ibm_struct { + char *name; + +- int (*read) (char *); ++ int (*read) (struct seq_file *); + int (*write) (char *); + void (*exit) (void); + void (*resume) (void); +@@ -776,36 +777,25 @@ static int __init register_tpacpi_subdri + **************************************************************************** + ****************************************************************************/ + +-static int dispatch_procfs_read(char *page, char **start, off_t off, +- int count, int *eof, void *data) ++static int dispatch_proc_show(struct seq_file *m, void *v) + { +- struct ibm_struct *ibm = data; +- int len; ++ struct ibm_struct *ibm = m->private; + + if (!ibm || !ibm->read) + return -EINVAL; ++ return ibm->read(m); ++} + +- len = ibm->read(page); +- if (len < 0) +- return len; +- +- if (len <= off + count) +- *eof = 1; +- *start = page + off; +- len -= off; +- if (len > count) +- len = count; +- if (len < 0) +- len = 0; +- +- return len; ++static int dispatch_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dispatch_proc_show, PDE(inode)->data); + } + +-static int dispatch_procfs_write(struct file *file, ++static ssize_t dispatch_proc_write(struct file *file, + const char __user *userbuf, +- unsigned long count, void *data) ++ size_t count, loff_t *pos) + { +- struct ibm_struct *ibm = data; ++ struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data; + char *kernbuf; + int ret; + +@@ -834,6 +824,15 @@ static int dispatch_procfs_write(struct + return ret; + } + ++static const struct file_operations dispatch_proc_fops = { ++ .owner = THIS_MODULE, ++ .open = dispatch_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ .write = dispatch_proc_write, ++}; ++ + static char *next_cmd(char **cmds) + { + char *start = *cmds; +@@ -1388,12 +1387,11 @@ static ssize_t tpacpi_rfk_sysfs_enable_s + } + + /* procfs -------------------------------------------------------------- */ +-static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) ++static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, ++ struct seq_file *m) + { +- int len = 0; +- + if (id >= TPACPI_RFK_SW_MAX) +- len += sprintf(p + len, "status:\t\tnot supported\n"); ++ seq_printf(m, "status:\t\tnot supported\n"); + else { + int status; + +@@ -1407,13 +1405,13 @@ static int tpacpi_rfk_procfs_read(const + return status; + } + +- len += sprintf(p + len, "status:\t\t%s\n", ++ seq_printf(m, "status:\t\t%s\n", + (status == TPACPI_RFK_RADIO_ON) ? + "enabled" : "disabled"); +- len += sprintf(p + len, "commands:\tenable, disable\n"); ++ seq_printf(m, "commands:\tenable, disable\n"); + } + +- return len; ++ return 0; + } + + static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) +@@ -1891,14 +1889,11 @@ static int __init thinkpad_acpi_driver_i + return 0; + } + +-static int thinkpad_acpi_driver_read(char *p) ++static int thinkpad_acpi_driver_read(struct seq_file *m) + { +- int len = 0; +- +- len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC); +- len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION); +- +- return len; ++ seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC); ++ seq_printf(m, "version:\t%s\n", TPACPI_VERSION); ++ return 0; + } + + static struct ibm_struct thinkpad_acpi_driver_data = { +@@ -3754,14 +3749,13 @@ static void hotkey_resume(void) + } + + /* procfs -------------------------------------------------------------- */ +-static int hotkey_read(char *p) ++static int hotkey_read(struct seq_file *m) + { + int res, status; +- int len = 0; + + if (!tp_features.hotkey) { +- len += sprintf(p + len, "status:\t\tnot supported\n"); +- return len; ++ seq_printf(m, "status:\t\tnot supported\n"); ++ return 0; + } + + if (mutex_lock_killable(&hotkey_mutex)) +@@ -3773,17 +3767,16 @@ static int hotkey_read(char *p) + if (res) + return res; + +- len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); ++ seq_printf(m, "status:\t\t%s\n", enabled(status, 0)); + if (hotkey_all_mask) { +- len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask); +- len += sprintf(p + len, +- "commands:\tenable, disable, reset, \n"); ++ seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask); ++ seq_printf(m, "commands:\tenable, disable, reset, \n"); + } else { +- len += sprintf(p + len, "mask:\t\tnot supported\n"); +- len += sprintf(p + len, "commands:\tenable, disable, reset\n"); ++ seq_printf(m, "mask:\t\tnot supported\n"); ++ seq_printf(m, "commands:\tenable, disable, reset\n"); + } + +- return len; ++ return 0; + } + + static void hotkey_enabledisable_warn(bool enable) +@@ -4050,9 +4043,9 @@ static int __init bluetooth_init(struct + } + + /* procfs -------------------------------------------------------------- */ +-static int bluetooth_read(char *p) ++static int bluetooth_read(struct seq_file *m) + { +- return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); ++ return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m); + } + + static int bluetooth_write(char *buf) +@@ -4241,9 +4234,9 @@ static int __init wan_init(struct ibm_in + } + + /* procfs -------------------------------------------------------------- */ +-static int wan_read(char *p) ++static int wan_read(struct seq_file *m) + { +- return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); ++ return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m); + } + + static int wan_write(char *buf) +@@ -4618,14 +4611,13 @@ static int video_expand_toggle(void) + /* not reached */ + } + +-static int video_read(char *p) ++static int video_read(struct seq_file *m) + { + int status, autosw; +- int len = 0; + + if (video_supported == TPACPI_VIDEO_NONE) { +- len += sprintf(p + len, "status:\t\tnot supported\n"); +- return len; ++ seq_printf(m, "status:\t\tnot supported\n"); ++ return 0; + } + + status = video_outputsw_get(); +@@ -4636,20 +4628,20 @@ static int video_read(char *p) + if (autosw < 0) + return autosw; + +- len += sprintf(p + len, "status:\t\tsupported\n"); +- len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); +- len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); ++ seq_printf(m, "status:\t\tsupported\n"); ++ seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0)); ++ seq_printf(m, "crt:\t\t%s\n", enabled(status, 1)); + if (video_supported == TPACPI_VIDEO_NEW) +- len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3)); +- len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0)); +- len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n"); +- len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n"); ++ seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3)); ++ seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0)); ++ seq_printf(m, "commands:\tlcd_enable, lcd_disable\n"); ++ seq_printf(m, "commands:\tcrt_enable, crt_disable\n"); + if (video_supported == TPACPI_VIDEO_NEW) +- len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n"); +- len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n"); +- len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n"); ++ seq_printf(m, "commands:\tdvi_enable, dvi_disable\n"); ++ seq_printf(m, "commands:\tauto_enable, auto_disable\n"); ++ seq_printf(m, "commands:\tvideo_switch, expand_toggle\n"); + +- return len; ++ return 0; + } + + static int video_write(char *buf) +@@ -4841,25 +4833,24 @@ static void light_exit(void) + flush_workqueue(tpacpi_wq); + } + +-static int light_read(char *p) ++static int light_read(struct seq_file *m) + { +- int len = 0; + int status; + + if (!tp_features.light) { +- len += sprintf(p + len, "status:\t\tnot supported\n"); ++ seq_printf(m, "status:\t\tnot supported\n"); + } else if (!tp_features.light_status) { +- len += sprintf(p + len, "status:\t\tunknown\n"); +- len += sprintf(p + len, "commands:\ton, off\n"); ++ seq_printf(m, "status:\t\tunknown\n"); ++ seq_printf(m, "commands:\ton, off\n"); + } else { + status = light_get_status(); + if (status < 0) + return status; +- len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); +- len += sprintf(p + len, "commands:\ton, off\n"); ++ seq_printf(m, "status:\t\t%s\n", onoff(status, 0)); ++ seq_printf(m, "commands:\ton, off\n"); + } + +- return len; ++ return 0; + } + + static int light_write(char *buf) +@@ -4937,20 +4928,18 @@ static void cmos_exit(void) + device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); + } + +-static int cmos_read(char *p) ++static int cmos_read(struct seq_file *m) + { +- int len = 0; +- + /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, + R30, R31, T20-22, X20-21 */ + if (!cmos_handle) +- len += sprintf(p + len, "status:\t\tnot supported\n"); ++ seq_printf(m, "status:\t\tnot supported\n"); + else { +- len += sprintf(p + len, "status:\t\tsupported\n"); +- len += sprintf(p + len, "commands:\t ( is 0-21)\n"); ++ seq_printf(m, "status:\t\tsupported\n"); ++ seq_printf(m, "commands:\t ( is 0-21)\n"); + } + +- return len; ++ return 0; + } + + static int cmos_write(char *buf) +@@ -5325,15 +5314,13 @@ static int __init led_init(struct ibm_in + ((s) == TPACPI_LED_OFF ? "off" : \ + ((s) == TPACPI_LED_ON ? "on" : "blinking")) + +-static int led_read(char *p) ++static int led_read(struct seq_file *m) + { +- int len = 0; +- + if (!led_supported) { +- len += sprintf(p + len, "status:\t\tnot supported\n"); +- return len; ++ seq_printf(m, "status:\t\tnot supported\n"); ++ return 0; + } +- len += sprintf(p + len, "status:\t\tsupported\n"); ++ seq_printf(m, "status:\t\tsupported\n"); + + if (led_supported == TPACPI_LED_570) { + /* 570 */ +@@ -5342,15 +5329,15 @@ static int led_read(char *p) + status = led_get_status(i); + if (status < 0) + return -EIO; +- len += sprintf(p + len, "%d:\t\t%s\n", ++ seq_printf(m, "%d:\t\t%s\n", + i, str_led_status(status)); + } + } + +- len += sprintf(p + len, "commands:\t" ++ seq_printf(m, "commands:\t" + " on, off, blink ( is 0-15)\n"); + +- return len; ++ return 0; + } + + static int led_write(char *buf) +@@ -5423,18 +5410,16 @@ static int __init beep_init(struct ibm_i + return (beep_handle)? 0 : 1; + } + +-static int beep_read(char *p) ++static int beep_read(struct seq_file *m) + { +- int len = 0; +- + if (!beep_handle) +- len += sprintf(p + len, "status:\t\tnot supported\n"); ++ seq_printf(m, "status:\t\tnot supported\n"); + else { +- len += sprintf(p + len, "status:\t\tsupported\n"); +- len += sprintf(p + len, "commands:\t ( is 0-17)\n"); ++ seq_printf(m, "status:\t\tsupported\n"); ++ seq_printf(m, "commands:\t ( is 0-17)\n"); + } + +- return len; ++ return 0; + } + + static int beep_write(char *buf) +@@ -5795,9 +5780,8 @@ static void thermal_exit(void) + } + } + +-static int thermal_read(char *p) ++static int thermal_read(struct seq_file *m) + { +- int len = 0; + int n, i; + struct ibm_thermal_sensors_struct t; + +@@ -5805,16 +5789,16 @@ static int thermal_read(char *p) + if (unlikely(n < 0)) + return n; + +- len += sprintf(p + len, "temperatures:\t"); ++ seq_printf(m, "temperatures:\t"); + + if (n > 0) { + for (i = 0; i < (n - 1); i++) +- len += sprintf(p + len, "%d ", t.temp[i] / 1000); +- len += sprintf(p + len, "%d\n", t.temp[i] / 1000); ++ seq_printf(m, "%d ", t.temp[i] / 1000); ++ seq_printf(m, "%d\n", t.temp[i] / 1000); + } else +- len += sprintf(p + len, "not supported\n"); ++ seq_printf(m, "not supported\n"); + +- return len; ++ return 0; + } + + static struct ibm_struct thermal_driver_data = { +@@ -5829,39 +5813,38 @@ static struct ibm_struct thermal_driver_ + + static u8 ecdump_regs[256]; + +-static int ecdump_read(char *p) ++static int ecdump_read(struct seq_file *m) + { +- int len = 0; + int i, j; + u8 v; + +- len += sprintf(p + len, "EC " ++ seq_printf(m, "EC " + " +00 +01 +02 +03 +04 +05 +06 +07" + " +08 +09 +0a +0b +0c +0d +0e +0f\n"); + for (i = 0; i < 256; i += 16) { +- len += sprintf(p + len, "EC 0x%02x:", i); ++ seq_printf(m, "EC 0x%02x:", i); + for (j = 0; j < 16; j++) { + if (!acpi_ec_read(i + j, &v)) + break; + if (v != ecdump_regs[i + j]) +- len += sprintf(p + len, " *%02x", v); ++ seq_printf(m, " *%02x", v); + else +- len += sprintf(p + len, " %02x", v); ++ seq_printf(m, " %02x", v); + ecdump_regs[i + j] = v; + } +- len += sprintf(p + len, "\n"); ++ seq_putc(m, '\n'); + if (j != 16) + break; + } + + /* These are way too dangerous to advertise openly... */ + #if 0 +- len += sprintf(p + len, "commands:\t0x 0x" ++ seq_printf(m, "commands:\t0x 0x" + " ( is 00-ff, is 00-ff)\n"); +- len += sprintf(p + len, "commands:\t0x " ++ seq_printf(m, "commands:\t0x " + " ( is 00-ff, is 0-255)\n"); + #endif +- return len; ++ return 0; + } + + static int ecdump_write(char *buf) +@@ -6314,23 +6297,22 @@ static void brightness_exit(void) + tpacpi_brightness_checkpoint_nvram(); + } + +-static int brightness_read(char *p) ++static int brightness_read(struct seq_file *m) + { +- int len = 0; + int level; + + level = brightness_get(NULL); + if (level < 0) { +- len += sprintf(p + len, "level:\t\tunreadable\n"); ++ seq_printf(m, "level:\t\tunreadable\n"); + } else { +- len += sprintf(p + len, "level:\t\t%d\n", level); +- len += sprintf(p + len, "commands:\tup, down\n"); +- len += sprintf(p + len, "commands:\tlevel " ++ seq_printf(m, "level:\t\t%d\n", level); ++ seq_printf(m, "commands:\tup, down\n"); ++ seq_printf(m, "commands:\tlevel " + " ( is 0-%d)\n", + (tp_features.bright_16levels) ? 15 : 7); + } + +- return len; ++ return 0; + } + + static int brightness_write(char *buf) +@@ -6387,22 +6369,21 @@ static struct ibm_struct brightness_driv + + static int volume_offset = 0x30; + +-static int volume_read(char *p) ++static int volume_read(struct seq_file *m) + { +- int len = 0; + u8 level; + + if (!acpi_ec_read(volume_offset, &level)) { +- len += sprintf(p + len, "level:\t\tunreadable\n"); ++ seq_printf(m, "level:\t\tunreadable\n"); + } else { +- len += sprintf(p + len, "level:\t\t%d\n", level & 0xf); +- len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6)); +- len += sprintf(p + len, "commands:\tup, down, mute\n"); +- len += sprintf(p + len, "commands:\tlevel " ++ seq_printf(m, "level:\t\t%d\n", level & 0xf); ++ seq_printf(m, "mute:\t\t%s\n", onoff(level, 6)); ++ seq_printf(m, "commands:\tup, down, mute\n"); ++ seq_printf(m, "commands:\tlevel " + " ( is 0-15)\n"); + } + +- return len; ++ return 0; + } + + static int volume_write(char *buf) +@@ -7554,9 +7535,8 @@ static void fan_resume(void) + } + } + +-static int fan_read(char *p) ++static int fan_read(struct seq_file *m) + { +- int len = 0; + int rc; + u8 status; + unsigned int speed = 0; +@@ -7568,7 +7548,7 @@ static int fan_read(char *p) + if (rc < 0) + return rc; + +- len += sprintf(p + len, "status:\t\t%s\n" ++ seq_printf(m, "status:\t\t%s\n" + "level:\t\t%d\n", + (status != 0) ? "enabled" : "disabled", status); + break; +@@ -7579,54 +7559,54 @@ static int fan_read(char *p) + if (rc < 0) + return rc; + +- len += sprintf(p + len, "status:\t\t%s\n", ++ seq_printf(m, "status:\t\t%s\n", + (status != 0) ? "enabled" : "disabled"); + + rc = fan_get_speed(&speed); + if (rc < 0) + return rc; + +- len += sprintf(p + len, "speed:\t\t%d\n", speed); ++ seq_printf(m, "speed:\t\t%d\n", speed); + + if (status & TP_EC_FAN_FULLSPEED) + /* Disengaged mode takes precedence */ +- len += sprintf(p + len, "level:\t\tdisengaged\n"); ++ seq_printf(m, "level:\t\tdisengaged\n"); + else if (status & TP_EC_FAN_AUTO) +- len += sprintf(p + len, "level:\t\tauto\n"); ++ seq_printf(m, "level:\t\tauto\n"); + else +- len += sprintf(p + len, "level:\t\t%d\n", status); ++ seq_printf(m, "level:\t\t%d\n", status); + break; + + case TPACPI_FAN_NONE: + default: +- len += sprintf(p + len, "status:\t\tnot supported\n"); ++ seq_printf(m, "status:\t\tnot supported\n"); + } + + if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) { +- len += sprintf(p + len, "commands:\tlevel "); ++ seq_printf(m, "commands:\tlevel "); + + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_SFAN: +- len += sprintf(p + len, " ( is 0-7)\n"); ++ seq_printf(m, " ( is 0-7)\n"); + break; + + default: +- len += sprintf(p + len, " ( is 0-7, " ++ seq_printf(m, " ( is 0-7, " + "auto, disengaged, full-speed)\n"); + break; + } + } + + if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) +- len += sprintf(p + len, "commands:\tenable, disable\n" ++ seq_printf(m, "commands:\tenable, disable\n" + "commands:\twatchdog ( " + "is 0 (off), 1-120 (seconds))\n"); + + if (fan_control_commands & TPACPI_FAN_CMD_SPEED) +- len += sprintf(p + len, "commands:\tspeed " ++ seq_printf(m, "commands:\tspeed " + " ( is 0-65535)\n"); + +- return len; ++ return 0; + } + + static int fan_write_cmd_level(const char *cmd, int *rc) +@@ -7907,19 +7887,19 @@ static int __init ibm_init(struct ibm_in + "%s installed\n", ibm->name); + + if (ibm->read) { +- entry = create_proc_entry(ibm->name, +- S_IFREG | S_IRUGO | S_IWUSR, +- proc_dir); ++ mode_t mode; ++ ++ mode = S_IRUGO; ++ if (ibm->write) ++ mode |= S_IWUSR; ++ entry = proc_create_data(ibm->name, mode, proc_dir, ++ &dispatch_proc_fops, ibm); + if (!entry) { + printk(TPACPI_ERR "unable to create proc entry %s\n", + ibm->name); + ret = -ENODEV; + goto err_out; + } +- entry->data = ibm; +- entry->read_proc = &dispatch_procfs_read; +- if (ibm->write) +- entry->write_proc = &dispatch_procfs_write; + ibm->flags.proc_created = 1; + } + diff --git a/queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch b/queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch new file mode 100644 index 00000000000..d6720facaf6 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-expose-module-parameters.patch @@ -0,0 +1,95 @@ +From b09c72259e88cec3d602aef987a3209297f3a9c2 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:27 +0000 +Subject: thinkpad-acpi: expose module parameters + +From: Henrique de Moraes Holschuh + +commit b09c72259e88cec3d602aef987a3209297f3a9c2 upstream. + +Export the normal (non-command) module paramenters as mode 0444, so +that they will show up in sysfs. + +These parameters must not be changed at runtime as a rule, with very +few exceptions. + +Reported-by: Ferenc Wagner +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -8126,32 +8126,32 @@ static int __init set_ibm_param(const ch + return -EINVAL; + } + +-module_param(experimental, int, 0); ++module_param(experimental, int, 0444); + MODULE_PARM_DESC(experimental, + "Enables experimental features when non-zero"); + + module_param_named(debug, dbg_level, uint, 0); + MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); + +-module_param(force_load, bool, 0); ++module_param(force_load, bool, 0444); + MODULE_PARM_DESC(force_load, + "Attempts to load the driver even on a " + "mis-identified ThinkPad when true"); + +-module_param_named(fan_control, fan_control_allowed, bool, 0); ++module_param_named(fan_control, fan_control_allowed, bool, 0444); + MODULE_PARM_DESC(fan_control, + "Enables setting fan parameters features when true"); + +-module_param_named(brightness_mode, brightness_mode, uint, 0); ++module_param_named(brightness_mode, brightness_mode, uint, 0444); + MODULE_PARM_DESC(brightness_mode, + "Selects brightness control strategy: " + "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); + +-module_param(brightness_enable, uint, 0); ++module_param(brightness_enable, uint, 0444); + MODULE_PARM_DESC(brightness_enable, + "Enables backlight control when 1, disables when 0"); + +-module_param(hotkey_report_mode, uint, 0); ++module_param(hotkey_report_mode, uint, 0444); + MODULE_PARM_DESC(hotkey_report_mode, + "used for backwards compatibility with userspace, " + "see documentation"); +@@ -8174,25 +8174,25 @@ TPACPI_PARAM(volume); + TPACPI_PARAM(fan); + + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES +-module_param(dbg_wlswemul, uint, 0); ++module_param(dbg_wlswemul, uint, 0444); + MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); + module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); + MODULE_PARM_DESC(wlsw_state, + "Initial state of the emulated WLSW switch"); + +-module_param(dbg_bluetoothemul, uint, 0); ++module_param(dbg_bluetoothemul, uint, 0444); + MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); + module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); + MODULE_PARM_DESC(bluetooth_state, + "Initial state of the emulated bluetooth switch"); + +-module_param(dbg_wwanemul, uint, 0); ++module_param(dbg_wwanemul, uint, 0444); + MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); + module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); + MODULE_PARM_DESC(wwan_state, + "Initial state of the emulated WWAN switch"); + +-module_param(dbg_uwbemul, uint, 0); ++module_param(dbg_uwbemul, uint, 0444); + MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation"); + module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0); + MODULE_PARM_DESC(uwb_state, diff --git a/queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch b/queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch new file mode 100644 index 00000000000..a818b312b7b --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-fix-some-version-quirks.patch @@ -0,0 +1,41 @@ +From 90765c6aee568137521ba19347c744b5abde8161 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:23 +0000 +Subject: thinkpad-acpi: fix some version quirks + +From: Henrique de Moraes Holschuh + +commit 90765c6aee568137521ba19347c744b5abde8161 upstream. + +Update some of the BIOS/EC version quirks. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -1779,7 +1779,7 @@ static const struct tpacpi_quirk tpacpi_ + + TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ + TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ +- TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ ++ TPV_QL1('7', 'E', 'D', '0', '1', '5'), /* R60e, R60i */ + + /* BIOS FW BIOS VERS EC FW EC VERS */ + TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ +@@ -1795,8 +1795,8 @@ static const struct tpacpi_quirk tpacpi_ + TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ + TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ + +- TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ +- TPV_QL0('7', 'J', '3', '0'), /* X60t */ ++ TPV_QL1('7', 'B', 'D', '7', '4', '0'), /* X60/s */ ++ TPV_QL1('7', 'J', '3', '0', '1', '3'), /* X60t */ + + /* (0) - older versions lack DMI EC fw string and functionality */ + /* (1) - older versions known to lack functionality */ diff --git a/queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch b/queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch new file mode 100644 index 00000000000..87004ed9ceb --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-issue-backlight-class-events.patch @@ -0,0 +1,158 @@ +From 347a26860e2293b1347996876d3550499c7bb31f Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:24 +0000 +Subject: thinkpad-acpi: issue backlight class events + +From: Henrique de Moraes Holschuh + +commit 347a26860e2293b1347996876d3550499c7bb31f upstream. + +Take advantage of the new events capabilities of the backlight class to +notify userspace of backlight changes. + +This depends on "backlight: Allow drivers to update the core, and +generate events on changes", by Matthew Garrett. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Matthew Garrett +Cc: Richard Purdie +Signed-off-by: Len Brown + +--- + Documentation/laptops/thinkpad-acpi.txt | 51 +++++++------------------------- + drivers/platform/x86/thinkpad_acpi.c | 24 ++++++++++++++- + 2 files changed, 35 insertions(+), 40 deletions(-) + +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -460,6 +460,8 @@ event code Key Notes + For Lenovo ThinkPads with a new + BIOS, it has to be handled either + by the ACPI OSI, or by userspace. ++ The driver does the right thing, ++ never mess with this. + 0x1011 0x10 FN+END Brightness down. See brightness + up for details. + +@@ -582,46 +584,15 @@ with hotkey_report_mode. + + Brightness hotkey notes: + +-These are the current sane choices for brightness key mapping in +-thinkpad-acpi: ++Don't mess with the brightness hotkeys in a Thinkpad. If you want ++notifications for OSD, use the sysfs backlight class event support. + +-For IBM and Lenovo models *without* ACPI backlight control (the ones on +-which thinkpad-acpi will autoload its backlight interface by default, +-and on which ACPI video does not export a backlight interface): +- +-1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as +- these older firmware versions unfortunately won't respect the hotkey +- mask for brightness keys anyway, and always reacts to them. This +- usually work fine, unless X.org drivers are doing something to block +- the BIOS. In that case, use (3) below. This is the default mode of +- operation. +- +-2. Enable the hotkeys, but map them to something else that is NOT +- KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause +- userspace to try to change the backlight level, and use that as an +- on-screen-display hint. +- +-3. IF AND ONLY IF X.org drivers find a way to block the firmware from +- automatically changing the brightness, enable the hotkeys and map +- them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to +- something that calls xbacklight. thinkpad-acpi will not be able to +- change brightness in that case either, so you should disable its +- backlight interface. +- +-For Lenovo models *with* ACPI backlight control: +- +-1. Load up ACPI video and use that. ACPI video will report ACPI +- events for brightness change keys. Do not mess with thinkpad-acpi +- defaults in this case. thinkpad-acpi should not have anything to do +- with backlight events in a scenario where ACPI video is loaded: +- brightness hotkeys must be disabled, and the backlight interface is +- to be kept disabled as well. This is the default mode of operation. +- +-2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi, +- and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process +- these keys on userspace somehow (e.g. by calling xbacklight). +- The driver will do this automatically if it detects that ACPI video +- has been disabled. ++The driver will issue KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN events ++automatically for the cases were userspace has to do something to ++implement brightness changes. When you override these events, you will ++either fail to handle properly the ThinkPads that require explicit ++action to change backlight brightness, or the ThinkPads that require ++that no action be taken to work properly. + + + Bluetooth +@@ -1465,3 +1436,5 @@ Sysfs interface changelog: + and it is always able to disable hot keys. Very old + thinkpads are properly supported. hotkey_bios_mask + is deprecated and marked for removal. ++ ++0x020600: Marker for backlight change event support. +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -22,7 +22,7 @@ + */ + + #define TPACPI_VERSION "0.23" +-#define TPACPI_SYSFS_VERSION 0x020500 ++#define TPACPI_SYSFS_VERSION 0x020600 + + /* + * Changelog: +@@ -6083,6 +6083,12 @@ static int brightness_get(struct backlig + return status & TP_EC_BACKLIGHT_LVLMSK; + } + ++static void tpacpi_brightness_notify_change(void) ++{ ++ backlight_force_update(ibm_backlight_device, ++ BACKLIGHT_UPDATE_HOTKEY); ++} ++ + static struct backlight_ops ibm_backlight_data = { + .get_brightness = brightness_get, + .update_status = brightness_update_status, +@@ -6237,6 +6243,12 @@ static int __init brightness_init(struct + ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; + backlight_update_status(ibm_backlight_device); + ++ vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, ++ "brightness: registering brightness hotkeys " ++ "as change notification\n"); ++ tpacpi_hotkey_driver_mask_set(hotkey_driver_mask ++ | TP_ACPI_HKEY_BRGHTUP_MASK ++ | TP_ACPI_HKEY_BRGHTDWN_MASK);; + return 0; + } + +@@ -6313,6 +6325,9 @@ static int brightness_write(char *buf) + * Doing it this way makes the syscall restartable in case of EINTR + */ + rc = brightness_set(level); ++ if (!rc && ibm_backlight_device) ++ backlight_force_update(ibm_backlight_device, ++ BACKLIGHT_UPDATE_SYSFS); + return (rc == -EINTR)? -ERESTARTSYS : rc; + } + +@@ -7712,6 +7727,13 @@ static struct ibm_struct fan_driver_data + */ + static void tpacpi_driver_event(const unsigned int hkey_event) + { ++ if (ibm_backlight_device) { ++ switch (hkey_event) { ++ case TP_HKEY_EV_BRGHT_UP: ++ case TP_HKEY_EV_BRGHT_DOWN: ++ tpacpi_brightness_notify_change(); ++ } ++ } + } + + diff --git a/queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch b/queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch new file mode 100644 index 00000000000..620846a82b4 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-lock-down-video-output-state-access.patch @@ -0,0 +1,117 @@ +From b525c06cdbd8a3963f0173ccd23f9147d4c384b5 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Thu, 25 Feb 2010 22:22:22 -0300 +Subject: thinkpad-acpi: lock down video output state access + +From: Henrique de Moraes Holschuh + +commit b525c06cdbd8a3963f0173ccd23f9147d4c384b5 upstream. + +Given the right combination of ThinkPad and X.org, just reading the +video output control state is enough to hard-crash X.org. + +Until the day I somehow find out a model or BIOS cut date to not +provide this feature to ThinkPads that can do video switching through +X RandR, change permissions so that only processes with CAP_SYS_ADMIN +can access any sort of video output control state. + +This bug could be considered a local DoS I suppose, as it allows any +non-privledged local user to cause some versions of X.org to +hard-crash some ThinkPads. + +Reported-by: Jidanni +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/laptops/thinkpad-acpi.txt | 4 ++++ + drivers/platform/x86/Kconfig | 10 ++++++++-- + drivers/platform/x86/thinkpad_acpi.c | 15 +++++++++++++-- + 3 files changed, 25 insertions(+), 4 deletions(-) + +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -650,6 +650,10 @@ LCD, CRT or DVI (if available). The foll + echo expand_toggle > /proc/acpi/ibm/video + echo video_switch > /proc/acpi/ibm/video + ++NOTE: Access to this feature is restricted to processes owning the ++CAP_SYS_ADMIN capability for safety reasons, as it can interact badly ++enough with some versions of X.org to crash it. ++ + Each video output device can be enabled or disabled individually. + Reading /proc/acpi/ibm/video shows the status of each device. + +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -291,9 +291,15 @@ config THINKPAD_ACPI_VIDEO + server running, phase of the moon, and the current mood of + Schroedinger's cat. If you can use X.org's RandR to control + your ThinkPad's video output ports instead of this feature, +- don't think twice: do it and say N here to save some memory. ++ don't think twice: do it and say N here to save memory and avoid ++ bad interactions with X.org. + +- If you are not sure, say Y here. ++ NOTE: access to this feature is limited to processes with the ++ CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms ++ where it interacts badly with X.org. ++ ++ If you are not sure, say Y here but do try to check if you could ++ be using X.org RandR instead. + + config THINKPAD_ACPI_HOTKEY_POLL + bool "Support NVRAM polling for hot keys" +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -281,6 +281,7 @@ struct ibm_init_struct { + char param[32]; + + int (*init) (struct ibm_init_struct *); ++ mode_t base_procfs_mode; + struct ibm_struct *data; + }; + +@@ -4620,6 +4621,10 @@ static int video_read(struct seq_file *m + return 0; + } + ++ /* Even reads can crash X.org, so... */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + status = video_outputsw_get(); + if (status < 0) + return status; +@@ -4653,6 +4658,10 @@ static int video_write(char *buf) + if (video_supported == TPACPI_VIDEO_NONE) + return -ENODEV; + ++ /* Even reads can crash X.org, let alone writes... */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + enable = 0; + disable = 0; + +@@ -7887,9 +7896,10 @@ static int __init ibm_init(struct ibm_in + "%s installed\n", ibm->name); + + if (ibm->read) { +- mode_t mode; ++ mode_t mode = iibm->base_procfs_mode; + +- mode = S_IRUGO; ++ if (!mode) ++ mode = S_IRUGO; + if (ibm->write) + mode |= S_IWUSR; + entry = proc_create_data(ibm->name, mode, proc_dir, +@@ -8080,6 +8090,7 @@ static struct ibm_init_struct ibms_init[ + #ifdef CONFIG_THINKPAD_ACPI_VIDEO + { + .init = video_init, ++ .base_procfs_mode = S_IRUSR, + .data = &video_driver_data, + }, + #endif diff --git a/queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch b/queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch new file mode 100644 index 00000000000..7a60056dd4b --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-log-initial-state-of-rfkill-switches.patch @@ -0,0 +1,51 @@ +From 5451a923bbdcff6ae665947e120af7238b21a9d2 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 15 Dec 2009 21:51:07 -0200 +Subject: thinkpad-acpi: log initial state of rfkill switches + +From: Henrique de Moraes Holschuh + +commit 5451a923bbdcff6ae665947e120af7238b21a9d2 upstream. + +We already log the initial state of the hardware rfkill switch (WLSW), +might as well log the state of the softswitches as well. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Josip Rodin +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -1264,6 +1264,7 @@ static int __init tpacpi_new_rfkill(cons + struct tpacpi_rfk *atp_rfk; + int res; + bool sw_state = false; ++ bool hw_state; + int sw_status; + + BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); +@@ -1298,7 +1299,8 @@ static int __init tpacpi_new_rfkill(cons + rfkill_init_sw_state(atp_rfk->rfkill, sw_state); + } + } +- rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); ++ hw_state = tpacpi_rfk_check_hwblock_state(); ++ rfkill_set_hw_state(atp_rfk->rfkill, hw_state); + + res = rfkill_register(atp_rfk->rfkill); + if (res < 0) { +@@ -1311,6 +1313,9 @@ static int __init tpacpi_new_rfkill(cons + } + + tpacpi_rfkill_switches[id] = atp_rfk; ++ ++ printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n", ++ name, (sw_state || hw_state) ? "" : "un"); + return 0; + } + diff --git a/queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch b/queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch new file mode 100644 index 00000000000..0f27641c745 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-log-temperatures-on-termal-alarm-v2.patch @@ -0,0 +1,142 @@ +From 9ebd9e833648745fa5ac6998b9e0153ccd3ba839 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:28 +0000 +Subject: thinkpad-acpi: log temperatures on termal alarm (v2) + +From: Henrique de Moraes Holschuh + +commit 9ebd9e833648745fa5ac6998b9e0153ccd3ba839 upstream. + +Log temperatures on any of the EC thermal alarms. It could be +useful to help tracking down what is happening... + +Signed-off-by: Henrique de Moraes Holschuh +Acked-by: Pavel Machek +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 57 +++++++++++++++++++++++++++-------- + 1 file changed, 45 insertions(+), 12 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -3548,49 +3548,57 @@ static bool hotkey_notify_usrevent(const + } + } + ++static void thermal_dump_all_sensors(void); ++ + static bool hotkey_notify_thermal(const u32 hkey, + bool *send_acpi_ev, + bool *ignore_acpi_ev) + { ++ bool known = true; ++ + /* 0x6000-0x6FFF: thermal alarms */ + *send_acpi_ev = true; + *ignore_acpi_ev = false; + + switch (hkey) { ++ case TP_HKEY_EV_THM_TABLE_CHANGED: ++ printk(TPACPI_INFO ++ "EC reports that Thermal Table has changed\n"); ++ /* recommended action: do nothing, we don't have ++ * Lenovo ATM information */ ++ return true; + case TP_HKEY_EV_ALARM_BAT_HOT: + printk(TPACPI_CRIT + "THERMAL ALARM: battery is too hot!\n"); + /* recommended action: warn user through gui */ +- return true; ++ break; + case TP_HKEY_EV_ALARM_BAT_XHOT: + printk(TPACPI_ALERT + "THERMAL EMERGENCY: battery is extremely hot!\n"); + /* recommended action: immediate sleep/hibernate */ +- return true; ++ break; + case TP_HKEY_EV_ALARM_SENSOR_HOT: + printk(TPACPI_CRIT + "THERMAL ALARM: " + "a sensor reports something is too hot!\n"); + /* recommended action: warn user through gui, that */ + /* some internal component is too hot */ +- return true; ++ break; + case TP_HKEY_EV_ALARM_SENSOR_XHOT: + printk(TPACPI_ALERT + "THERMAL EMERGENCY: " + "a sensor reports something is extremely hot!\n"); + /* recommended action: immediate sleep/hibernate */ +- return true; +- case TP_HKEY_EV_THM_TABLE_CHANGED: +- printk(TPACPI_INFO +- "EC reports that Thermal Table has changed\n"); +- /* recommended action: do nothing, we don't have +- * Lenovo ATM information */ +- return true; ++ break; + default: + printk(TPACPI_ALERT + "THERMAL ALERT: unknown thermal alarm received\n"); +- return false; ++ known = false; + } ++ ++ thermal_dump_all_sensors(); ++ ++ return known; + } + + static void hotkey_notify(struct ibm_struct *ibm, u32 event) +@@ -5472,8 +5480,11 @@ enum { /* TPACPI_THERMAL_TPEC_* */ + TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ + TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ + TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ ++ ++ TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */ + }; + ++ + #define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ + struct ibm_thermal_sensors_struct { + s32 temp[TPACPI_MAX_THERMAL_SENSORS]; +@@ -5563,6 +5574,28 @@ static int thermal_get_sensors(struct ib + return n; + } + ++static void thermal_dump_all_sensors(void) ++{ ++ int n, i; ++ struct ibm_thermal_sensors_struct t; ++ ++ n = thermal_get_sensors(&t); ++ if (n <= 0) ++ return; ++ ++ printk(TPACPI_NOTICE ++ "temperatures (Celsius):"); ++ ++ for (i = 0; i < n; i++) { ++ if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA) ++ printk(KERN_CONT " %d", (int)(t.temp[i] / 1000)); ++ else ++ printk(KERN_CONT " N/A"); ++ } ++ ++ printk(KERN_CONT "\n"); ++} ++ + /* sysfs temp##_input -------------------------------------------------- */ + + static ssize_t thermal_temp_input_show(struct device *dev, +@@ -5578,7 +5611,7 @@ static ssize_t thermal_temp_input_show(s + res = thermal_get_sensor(idx, &value); + if (res) + return res; +- if (value == TP_EC_THERMAL_TMP_NA * 1000) ++ if (value == TPACPI_THERMAL_SENSOR_NA) + return -ENXIO; + + return snprintf(buf, PAGE_SIZE, "%d\n", value); diff --git a/queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch b/queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch new file mode 100644 index 00000000000..94a510bd640 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-silence-bogus-complain-during-rmmod.patch @@ -0,0 +1,34 @@ +From 6b30eb7d211840ba1a03f855d9e7b80a921368f2 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:25 +0000 +Subject: thinkpad-acpi: silence bogus complain during rmmod + +From: Henrique de Moraes Holschuh + +commit 6b30eb7d211840ba1a03f855d9e7b80a921368f2 upstream. + +Fix this bogus warning during module shutdown, when +backlight event reporting is enabled: + +"thinkpad_acpi: required events 0x00018000 not enabled!" + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -2190,7 +2190,8 @@ static int hotkey_mask_set(u32 mask) + fwmask, hotkey_acpi_mask); + } + +- hotkey_mask_warn_incomplete_mask(); ++ if (tpacpi_lifecycle != TPACPI_LIFE_EXITING) ++ hotkey_mask_warn_incomplete_mask(); + + return rc; + } diff --git a/queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch b/queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch new file mode 100644 index 00000000000..b897300f10e --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-sync-input-device-ev_sw-initial-state.patch @@ -0,0 +1,92 @@ +From d89a727aff649f6768f7a34ee57f031ebf8bab4c Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 15 Dec 2009 21:51:06 -0200 +Subject: thinkpad-acpi: sync input device EV_SW initial state + +From: Henrique de Moraes Holschuh + +commit d89a727aff649f6768f7a34ee57f031ebf8bab4c upstream. + +Before we register the input device, sync the input layer EV_SW state +through a call to input_report_switch(), to avoid issuing a gratuitous +event for the initial state of these switches. + +This fixes some annoyances caused by the interaction with rfkill and +EV_SW SW_RFKILL_ALL events. + +Reported-by: Kevin Locke +Signed-off-by: Henrique de Moraes Holschuh +Cc: Alan Jenkins +Cc: Johannes Berg +Cc: Dmitry Torokhov +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -3188,6 +3188,8 @@ static int __init hotkey_init(struct ibm + int res, i; + int status; + int hkeyv; ++ bool radiosw_state = false; ++ bool tabletsw_state = false; + + unsigned long quirks; + +@@ -3293,6 +3295,7 @@ static int __init hotkey_init(struct ibm + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES + if (dbg_wlswemul) { + tp_features.hotkey_wlsw = 1; ++ radiosw_state = !!tpacpi_wlsw_emulstate; + printk(TPACPI_INFO + "radio switch emulation enabled\n"); + } else +@@ -3300,6 +3303,7 @@ static int __init hotkey_init(struct ibm + /* Not all thinkpads have a hardware radio switch */ + if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { + tp_features.hotkey_wlsw = 1; ++ radiosw_state = !!status; + printk(TPACPI_INFO + "radio switch found; radios are %s\n", + enabled(status, 0)); +@@ -3311,11 +3315,11 @@ static int __init hotkey_init(struct ibm + /* For X41t, X60t, X61t Tablets... */ + if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { + tp_features.hotkey_tablet = 1; ++ tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK); + printk(TPACPI_INFO + "possible tablet mode switch found; " + "ThinkPad in %s mode\n", +- (status & TP_HOTKEY_TABLET_MASK)? +- "tablet" : "laptop"); ++ (tabletsw_state) ? "tablet" : "laptop"); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_tablet_mode.attr); + } +@@ -3366,9 +3370,13 @@ static int __init hotkey_init(struct ibm + + if (tp_features.hotkey_wlsw) { + input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL); ++ input_report_switch(tpacpi_inputdev, ++ SW_RFKILL_ALL, radiosw_state); + } + if (tp_features.hotkey_tablet) { + input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE); ++ input_report_switch(tpacpi_inputdev, ++ SW_TABLET_MODE, tabletsw_state); + } + + /* Do not issue duplicate brightness change events to +@@ -3435,8 +3443,6 @@ static int __init hotkey_init(struct ibm + tpacpi_inputdev->close = &hotkey_inputdev_close; + + hotkey_poll_setup_safe(true); +- tpacpi_send_radiosw_update(); +- tpacpi_input_send_tabletsw(); + + return 0; + diff --git a/queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch b/queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch new file mode 100644 index 00000000000..704e22187b6 --- /dev/null +++ b/queue-2.6.32/thinkpad-acpi-use-input_set_capability.patch @@ -0,0 +1,57 @@ +From 792979c8032b8f5adb77ea986db7082fff04c8e7 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Wed, 9 Dec 2009 01:36:29 +0000 +Subject: thinkpad-acpi: use input_set_capability + +From: Henrique de Moraes Holschuh + +commit 792979c8032b8f5adb77ea986db7082fff04c8e7 upstream. + +Use input_set_capability() instead of set_bit. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Dmitry Torokhov +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/thinkpad_acpi.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -3350,16 +3350,14 @@ static int __init hotkey_init(struct ibm + TPACPI_HOTKEY_MAP_SIZE); + } + +- set_bit(EV_KEY, tpacpi_inputdev->evbit); +- set_bit(EV_MSC, tpacpi_inputdev->evbit); +- set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); ++ input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); + tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; + tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; + tpacpi_inputdev->keycode = hotkey_keycode_map; + for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { + if (hotkey_keycode_map[i] != KEY_RESERVED) { +- set_bit(hotkey_keycode_map[i], +- tpacpi_inputdev->keybit); ++ input_set_capability(tpacpi_inputdev, EV_KEY, ++ hotkey_keycode_map[i]); + } else { + if (i < sizeof(hotkey_reserved_mask)*8) + hotkey_reserved_mask |= 1 << i; +@@ -3367,12 +3365,10 @@ static int __init hotkey_init(struct ibm + } + + if (tp_features.hotkey_wlsw) { +- set_bit(EV_SW, tpacpi_inputdev->evbit); +- set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); ++ input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL); + } + if (tp_features.hotkey_tablet) { +- set_bit(EV_SW, tpacpi_inputdev->evbit); +- set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); ++ input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE); + } + + /* Do not issue duplicate brightness change events to diff --git a/queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch b/queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch new file mode 100644 index 00000000000..f0fed9e496a --- /dev/null +++ b/queue-2.6.32/x86-amd-get-multi-node-cpu-info-from-nodeid-msr-instead-of-pci-config-space.patch @@ -0,0 +1,119 @@ +From 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 Mon Sep 17 00:00:00 2001 +From: Andreas Herrmann +Date: Wed, 16 Dec 2009 15:43:55 +0100 +Subject: x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config space + +From: Andreas Herrmann + +commit 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 upstream. + +Use NodeId MSR to get NodeId and number of nodes per processor. + +Signed-off-by: Andreas Herrmann +LKML-Reference: <20091216144355.GB28798@alberich.amd.com> +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/msr-index.h | 1 + arch/x86/kernel/cpu/amd.c | 53 ++++++++++---------------------------- + 3 files changed, 17 insertions(+), 38 deletions(-) + +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -153,6 +153,7 @@ + #define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ + #define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ + #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ ++#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ + + /* + * Auxiliary flags: Linux defined - For features scattered in various +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -125,6 +125,7 @@ + #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 + #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff + #define FAM10H_MMIO_CONF_BASE_SHIFT 20 ++#define MSR_FAM10H_NODE_ID 0xc001100c + + /* K8 MSRs */ + #define MSR_K8_TOP_MEM1 0xc001001a +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -254,59 +254,36 @@ static int __cpuinit nearby_node(int api + + /* + * Fixup core topology information for AMD multi-node processors. +- * Assumption 1: Number of cores in each internal node is the same. +- * Assumption 2: Mixed systems with both single-node and dual-node +- * processors are not supported. ++ * Assumption: Number of cores in each internal node is the same. + */ + #ifdef CONFIG_X86_HT + static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c) + { +-#ifdef CONFIG_PCI +- u32 t, cpn; +- u8 n, n_id; ++ unsigned long long value; ++ u32 nodes, cores_per_node; + int cpu = smp_processor_id(); + ++ if (!cpu_has(c, X86_FEATURE_NODEID_MSR)) ++ return; ++ + /* fixup topology information only once for a core */ + if (cpu_has(c, X86_FEATURE_AMD_DCM)) + return; + +- /* check for multi-node processor on boot cpu */ +- t = read_pci_config(0, 24, 3, 0xe8); +- if (!(t & (1 << 29))) ++ rdmsrl(MSR_FAM10H_NODE_ID, value); ++ ++ nodes = ((value >> 3) & 7) + 1; ++ if (nodes == 1) + return; + + set_cpu_cap(c, X86_FEATURE_AMD_DCM); ++ cores_per_node = c->x86_max_cores / nodes; + +- /* cores per node: each internal node has half the number of cores */ +- cpn = c->x86_max_cores >> 1; +- +- /* even-numbered NB_id of this dual-node processor */ +- n = c->phys_proc_id << 1; ++ /* store NodeID, use llc_shared_map to store sibling info */ ++ per_cpu(cpu_llc_id, cpu) = value & 7; + +- /* +- * determine internal node id and assign cores fifty-fifty to +- * each node of the dual-node processor +- */ +- t = read_pci_config(0, 24 + n, 3, 0xe8); +- n = (t>>30) & 0x3; +- if (n == 0) { +- if (c->cpu_core_id < cpn) +- n_id = 0; +- else +- n_id = 1; +- } else { +- if (c->cpu_core_id < cpn) +- n_id = 1; +- else +- n_id = 0; +- } +- +- /* compute entire NodeID, use llc_shared_map to store sibling info */ +- per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id; +- +- /* fixup core id to be in range from 0 to cpn */ +- c->cpu_core_id = c->cpu_core_id % cpn; +-#endif ++ /* fixup core id to be in range from 0 to (cores_per_node - 1) */ ++ c->cpu_core_id = c->cpu_core_id % cores_per_node; + } + #endif + -- 2.47.3