diff options
author | Denis V. Lunev <den@openvz.org> | 2009-06-05 07:13:08 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2009-06-18 03:31:44 -0400 |
commit | de8cd9a3067e25a860c225f794e6b249b73aa6b1 (patch) | |
tree | 48dd6f028d03fd4595ee3551e57eae35f73cc671 | |
parent | e73a780272a46e897bd94a4870fd6b6a8655d2d4 (diff) |
[WATCHDOG] iTCO_wdt: fix memory corruption when RCBA is disabled by hardware
According to 9.1.33 on p.343 of ICH8.pdf RCBA can be disabled by
hardware if bit 0 of RCBA register is not set.
Perform correct check for this to prevent memory corruption under
some virtual machines where this feature is disabled.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Vasily Averin <vvs@openvz.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 6284961eff5b..6a51edde6ea7 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -666,6 +666,11 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
666 | GCS = RCBA + ICH6_GCS(0x3410). */ | 666 | GCS = RCBA + ICH6_GCS(0x3410). */ |
667 | if (iTCO_wdt_private.iTCO_version == 2) { | 667 | if (iTCO_wdt_private.iTCO_version == 2) { |
668 | pci_read_config_dword(pdev, 0xf0, &base_address); | 668 | pci_read_config_dword(pdev, 0xf0, &base_address); |
669 | if ((base_address & 1) == 0) { | ||
670 | printk(KERN_ERR PFX "RCBA is disabled by harddware\n"); | ||
671 | ret = -ENODEV; | ||
672 | goto out; | ||
673 | } | ||
669 | RCBA = base_address & 0xffffc000; | 674 | RCBA = base_address & 0xffffc000; |
670 | iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); | 675 | iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); |
671 | } | 676 | } |
@@ -675,7 +680,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
675 | printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " | 680 | printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " |
676 | "reboot disabled by hardware\n"); | 681 | "reboot disabled by hardware\n"); |
677 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ | 682 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ |
678 | goto out; | 683 | goto out_unmap; |
679 | } | 684 | } |
680 | 685 | ||
681 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | 686 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ |
@@ -686,7 +691,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
686 | printk(KERN_ERR PFX | 691 | printk(KERN_ERR PFX |
687 | "I/O address 0x%04lx already in use\n", SMI_EN); | 692 | "I/O address 0x%04lx already in use\n", SMI_EN); |
688 | ret = -EIO; | 693 | ret = -EIO; |
689 | goto out; | 694 | goto out_unmap; |
690 | } | 695 | } |
691 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ | 696 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ |
692 | val32 = inl(SMI_EN); | 697 | val32 = inl(SMI_EN); |
@@ -742,9 +747,10 @@ unreg_region: | |||
742 | release_region(TCOBASE, 0x20); | 747 | release_region(TCOBASE, 0x20); |
743 | unreg_smi_en: | 748 | unreg_smi_en: |
744 | release_region(SMI_EN, 4); | 749 | release_region(SMI_EN, 4); |
745 | out: | 750 | out_unmap: |
746 | if (iTCO_wdt_private.iTCO_version == 2) | 751 | if (iTCO_wdt_private.iTCO_version == 2) |
747 | iounmap(iTCO_wdt_private.gcs); | 752 | iounmap(iTCO_wdt_private.gcs); |
753 | out: | ||
748 | pci_dev_put(iTCO_wdt_private.pdev); | 754 | pci_dev_put(iTCO_wdt_private.pdev); |
749 | iTCO_wdt_private.ACPIBASE = 0; | 755 | iTCO_wdt_private.ACPIBASE = 0; |
750 | return ret; | 756 | return ret; |