Commit 0961d658 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.infradead.org/iommu-2.6

* git://git.infradead.org/iommu-2.6:
  intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables
  intel-iommu: Combine the BIOS DMAR table warning messages
  panic: Add taint flag TAINT_FIRMWARE_WORKAROUND ('I')
  panic: Allow warnings to set different taint flags
  intel-iommu: intel_iommu_map_range failed at very end of address space
  intel-iommu: errors with smaller iommu widths
  intel-iommu: Fix boot inside 64bit virtualbox with io-apic disabled
  intel-iommu: use physfn to search drhd for VF
  intel-iommu: Print out iommu seq_id
  intel-iommu: Don't complain that ACPI_DMAR_SCOPE_TYPE_IOAPIC is not supported
  intel-iommu: Avoid global flushes with caching mode.
  intel-iommu: Use correct domain ID when caching mode is enabled
  intel-iommu mistakenly uses offset_pfn when caching mode is enabled
  intel-iommu: use for_each_set_bit()
  intel-iommu: Fix section mismatch dmar_ir_support() uses dmar_tbl.
parents 1756ac3d fd0c8894
...@@ -256,9 +256,13 @@ characters, each representing a particular tainted value. ...@@ -256,9 +256,13 @@ characters, each representing a particular tainted value.
9: 'A' if the ACPI table has been overridden. 9: 'A' if the ACPI table has been overridden.
10: 'W' if a warning has previously been issued by the kernel. 10: 'W' if a warning has previously been issued by the kernel.
(Though some warnings may set more specific taint flags.)
11: 'C' if a staging driver has been loaded. 11: 'C' if a staging driver has been loaded.
12: 'I' if the kernel is working around a severe bug in the platform
firmware (BIOS or similar).
The primary reason for the 'Tainted: ' string is to tell kernel The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is occurred. Tainting is permanent: even if an offending module is
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#endif #endif
#ifdef CONFIG_DEBUG_BUGVERBOSE #ifdef CONFIG_DEBUG_BUGVERBOSE
#define __WARN() \ #define __WARN_TAINT(taint) \
do { \ do { \
asm volatile("\n" \ asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \
...@@ -54,11 +54,11 @@ ...@@ -54,11 +54,11 @@
"\t.org 2b+%c3\n" \ "\t.org 2b+%c3\n" \
"\t.popsection" \ "\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \ : : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \ "i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry)) ); \ "i" (sizeof(struct bug_entry)) ); \
} while(0) } while(0)
#else #else
#define __WARN() \ #define __WARN_TAINT(taint) \
do { \ do { \
asm volatile("\n" \ asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
"\t.short %c0\n" \ "\t.short %c0\n" \
"\t.org 2b+%c1\n" \ "\t.org 2b+%c1\n" \
"\t.popsection" \ "\t.popsection" \
: : "i" (BUGFLAG_WARNING), \ : : "i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry)) ); \ "i" (sizeof(struct bug_entry)) ); \
} while(0) } while(0)
#endif #endif
......
...@@ -85,12 +85,12 @@ ...@@ -85,12 +85,12 @@
} \ } \
} while (0) } while (0)
#define __WARN() do { \ #define __WARN_TAINT(taint) do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: twi 31,0,0\n" \ "1: twi 31,0,0\n" \
_EMIT_BUG_ENTRY \ _EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \ : : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \ "i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry))); \ "i" (sizeof(struct bug_entry))); \
} while (0) } while (0)
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
"1: "PPC_TLNEI" %4,0\n" \ "1: "PPC_TLNEI" %4,0\n" \
_EMIT_BUG_ENTRY \ _EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \ : : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \ "i" (BUGFLAG_TAINT(TAINT_WARN)), \
"i" (sizeof(struct bug_entry)), \ "i" (sizeof(struct bug_entry)), \
"r" (__ret_warn_on)); \ "r" (__ret_warn_on)); \
} \ } \
......
...@@ -46,18 +46,18 @@ ...@@ -46,18 +46,18 @@
unreachable(); \ unreachable(); \
} while (0) } while (0)
#define __WARN() do { \ #define __WARN_TAINT(taint) do { \
__EMIT_BUG(BUGFLAG_WARNING); \ __EMIT_BUG(BUGFLAG_TAINT(taint)); \
} while (0) } while (0)
#define WARN_ON(x) ({ \ #define WARN_ON(x) ({ \
int __ret_warn_on = !!(x); \ int __ret_warn_on = !!(x); \
if (__builtin_constant_p(__ret_warn_on)) { \ if (__builtin_constant_p(__ret_warn_on)) { \
if (__ret_warn_on) \ if (__ret_warn_on) \
__EMIT_BUG(BUGFLAG_WARNING); \ __WARN(); \
} else { \ } else { \
if (unlikely(__ret_warn_on)) \ if (unlikely(__ret_warn_on)) \
__EMIT_BUG(BUGFLAG_WARNING); \ __WARN(); \
} \ } \
unlikely(__ret_warn_on); \ unlikely(__ret_warn_on); \
}) })
......
...@@ -48,7 +48,7 @@ do { \ ...@@ -48,7 +48,7 @@ do { \
"i" (sizeof(struct bug_entry))); \ "i" (sizeof(struct bug_entry))); \
} while (0) } while (0)
#define __WARN() \ #define __WARN_TAINT(taint) \
do { \ do { \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
"1:\t.short %O0\n" \ "1:\t.short %O0\n" \
...@@ -57,7 +57,7 @@ do { \ ...@@ -57,7 +57,7 @@ do { \
: "n" (TRAPA_BUG_OPCODE), \ : "n" (TRAPA_BUG_OPCODE), \
"i" (__FILE__), \ "i" (__FILE__), \
"i" (__LINE__), \ "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \ "i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry))); \ "i" (sizeof(struct bug_entry))); \
} while (0) } while (0)
......
...@@ -131,9 +131,10 @@ static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, ...@@ -131,9 +131,10 @@ static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
(*cnt)++; (*cnt)++;
else else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
printk(KERN_WARNING PREFIX printk(KERN_WARNING PREFIX
"Unsupported device scope\n"); "Unsupported device scope\n");
}
start += scope->length; start += scope->length;
} }
if (*cnt == 0) if (*cnt == 0)
...@@ -309,6 +310,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) ...@@ -309,6 +310,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
struct acpi_dmar_atsr *atsr; struct acpi_dmar_atsr *atsr;
struct dmar_atsr_unit *atsru; struct dmar_atsr_unit *atsru;
dev = pci_physfn(dev);
list_for_each_entry(atsru, &dmar_atsr_units, list) { list_for_each_entry(atsru, &dmar_atsr_units, list) {
atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
if (atsr->segment == pci_domain_nr(dev->bus)) if (atsr->segment == pci_domain_nr(dev->bus))
...@@ -358,7 +361,9 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header) ...@@ -358,7 +361,9 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header)
return 0; return 0;
} }
} }
WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" WARN_TAINT(
1, TAINT_FIRMWARE_WORKAROUND,
"Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n", "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
drhd->reg_base_addr, drhd->reg_base_addr,
dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VENDOR),
...@@ -507,7 +512,7 @@ parse_dmar_table(void) ...@@ -507,7 +512,7 @@ parse_dmar_table(void)
return ret; return ret;
} }
int dmar_pci_device_match(struct pci_dev *devices[], int cnt, static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
struct pci_dev *dev) struct pci_dev *dev)
{ {
int index; int index;
...@@ -530,6 +535,8 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) ...@@ -530,6 +535,8 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
struct dmar_drhd_unit *dmaru = NULL; struct dmar_drhd_unit *dmaru = NULL;
struct acpi_dmar_hardware_unit *drhd; struct acpi_dmar_hardware_unit *drhd;
dev = pci_physfn(dev);
list_for_each_entry(dmaru, &dmar_drhd_units, list) { list_for_each_entry(dmaru, &dmar_drhd_units, list) {
drhd = container_of(dmaru->hdr, drhd = container_of(dmaru->hdr,
struct acpi_dmar_hardware_unit, struct acpi_dmar_hardware_unit,
...@@ -614,7 +621,17 @@ int __init dmar_table_init(void) ...@@ -614,7 +621,17 @@ int __init dmar_table_init(void)
return 0; return 0;
} }
static int bios_warned; static void warn_invalid_dmar(u64 addr, const char *message)
{
WARN_TAINT_ONCE(
1, TAINT_FIRMWARE_WORKAROUND,
"Your BIOS is broken; DMAR reported at address %llx%s!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
addr, message,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
}
int __init check_zero_address(void) int __init check_zero_address(void)
{ {
...@@ -640,13 +657,7 @@ int __init check_zero_address(void) ...@@ -640,13 +657,7 @@ int __init check_zero_address(void)
drhd = (void *)entry_header; drhd = (void *)entry_header;
if (!drhd->address) { if (!drhd->address) {
/* Promote an attitude of violence to a BIOS engineer today */ warn_invalid_dmar(0, "");
WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
bios_warned = 1;
goto failed; goto failed;
} }
...@@ -659,14 +670,8 @@ int __init check_zero_address(void) ...@@ -659,14 +670,8 @@ int __init check_zero_address(void)
ecap = dmar_readq(addr + DMAR_ECAP_REG); ecap = dmar_readq(addr + DMAR_ECAP_REG);
early_iounmap(addr, VTD_PAGE_SIZE); early_iounmap(addr, VTD_PAGE_SIZE);
if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
/* Promote an attitude of violence to a BIOS engineer today */ warn_invalid_dmar(drhd->address,
WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" " returns all ones");
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
drhd->address,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
bios_warned = 1;
goto failed; goto failed;
} }
} }
...@@ -731,14 +736,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) ...@@ -731,14 +736,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
int msagaw = 0; int msagaw = 0;
if (!drhd->reg_base_addr) { if (!drhd->reg_base_addr) {
if (!bios_warned) { warn_invalid_dmar(0, "");
WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
bios_warned = 1;
}
return -EINVAL; return -EINVAL;
} }
...@@ -758,16 +756,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) ...@@ -758,16 +756,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
if (!bios_warned) { warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
/* Promote an attitude of violence to a BIOS engineer today */
WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
drhd->reg_base_addr,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
bios_warned = 1;
}
goto err_unmap; goto err_unmap;
} }
...@@ -806,7 +795,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) ...@@ -806,7 +795,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
} }
ver = readl(iommu->reg + DMAR_VER_REG); ver = readl(iommu->reg + DMAR_VER_REG);
pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
iommu->seq_id,
(unsigned long long)drhd->reg_base_addr, (unsigned long long)drhd->reg_base_addr,
DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
(unsigned long long)iommu->cap, (unsigned long long)iommu->cap,
...@@ -1457,9 +1447,11 @@ int dmar_reenable_qi(struct intel_iommu *iommu) ...@@ -1457,9 +1447,11 @@ int dmar_reenable_qi(struct intel_iommu *iommu)
/* /*
* Check interrupt remapping support in DMAR table description. * Check interrupt remapping support in DMAR table description.
*/ */
int dmar_ir_support(void) int __init dmar_ir_support(void)
{ {
struct acpi_table_dmar *dmar; struct acpi_table_dmar *dmar;
dmar = (struct acpi_table_dmar *)dmar_tbl; dmar = (struct acpi_table_dmar *)dmar_tbl;
if (!dmar)
return 0;
return dmar->flags & 0x1; return dmar->flags & 0x1;
} }
This diff is collapsed.
...@@ -832,9 +832,9 @@ static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header, ...@@ -832,9 +832,9 @@ static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
return -1; return -1;
} }
printk(KERN_INFO "IOAPIC id %d under DRHD base" printk(KERN_INFO "IOAPIC id %d under DRHD base "
" 0x%Lx\n", scope->enumeration_id, " 0x%Lx IOMMU %d\n", scope->enumeration_id,
drhd->address); drhd->address, iommu->seq_id);
ir_parse_one_ioapic_scope(scope, iommu); ir_parse_one_ioapic_scope(scope, iommu);
} else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) { } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
......
...@@ -25,7 +25,10 @@ struct bug_entry { ...@@ -25,7 +25,10 @@ struct bug_entry {
}; };
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#define BUGFLAG_WARNING (1<<0) #define BUGFLAG_WARNING (1 << 0)
#define BUGFLAG_TAINT(taint) (BUGFLAG_WARNING | ((taint) << 8))
#define BUG_GET_TAINT(bug) ((bug)->flags >> 8)
#endif /* CONFIG_GENERIC_BUG */ #endif /* CONFIG_GENERIC_BUG */
/* /*
...@@ -56,17 +59,25 @@ struct bug_entry { ...@@ -56,17 +59,25 @@ struct bug_entry {
* appear at runtime. Use the versions with printk format strings * appear at runtime. Use the versions with printk format strings
* to provide better diagnostics. * to provide better diagnostics.
*/ */
#ifndef __WARN #ifndef __WARN_TAINT
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern void warn_slowpath_fmt(const char *file, const int line, extern void warn_slowpath_fmt(const char *file, const int line,
const char *fmt, ...) __attribute__((format(printf, 3, 4))); const char *fmt, ...) __attribute__((format(printf, 3, 4)));
extern void warn_slowpath_fmt_taint(const char *file, const int line,
unsigned taint, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
extern void warn_slowpath_null(const char *file, const int line); extern void warn_slowpath_null(const char *file, const int line);
#define WANT_WARN_ON_SLOWPATH #define WANT_WARN_ON_SLOWPATH
#endif #endif
#define __WARN() warn_slowpath_null(__FILE__, __LINE__) #define __WARN() warn_slowpath_null(__FILE__, __LINE__)
#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg) #define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
#define __WARN_printf_taint(taint, arg...) \
warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg)
#else #else
#define __WARN() __WARN_TAINT(TAINT_WARN)
#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) #define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
#define __WARN_printf_taint(taint, arg...) \
do { printk(arg); __WARN_TAINT(taint); } while (0)
#endif #endif
#ifndef WARN_ON #ifndef WARN_ON
...@@ -87,6 +98,13 @@ extern void warn_slowpath_null(const char *file, const int line); ...@@ -87,6 +98,13 @@ extern void warn_slowpath_null(const char *file, const int line);
}) })
#endif #endif
#define WARN_TAINT(condition, taint, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf_taint(taint, format); \
unlikely(__ret_warn_on); \
})
#else /* !CONFIG_BUG */ #else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG #ifndef HAVE_ARCH_BUG
#define BUG() do {} while(0) #define BUG() do {} while(0)
...@@ -110,6 +128,8 @@ extern void warn_slowpath_null(const char *file, const int line); ...@@ -110,6 +128,8 @@ extern void warn_slowpath_null(const char *file, const int line);
}) })
#endif #endif
#define WARN_TAINT(condition, taint, format...) WARN_ON(condition)
#endif #endif
#define WARN_ON_ONCE(condition) ({ \ #define WARN_ON_ONCE(condition) ({ \
...@@ -132,6 +152,16 @@ extern void warn_slowpath_null(const char *file, const int line); ...@@ -132,6 +152,16 @@ extern void warn_slowpath_null(const char *file, const int line);
unlikely(__ret_warn_once); \ unlikely(__ret_warn_once); \
}) })
#define WARN_TAINT_ONCE(condition, taint, format...) ({ \
static bool __warned; \
int __ret_warn_once = !!(condition); \
\
if (unlikely(__ret_warn_once)) \
if (WARN_TAINT(!__warned, taint, format)) \
__warned = true; \
unlikely(__ret_warn_once); \
})
#define WARN_ON_RATELIMIT(condition, state) \ #define WARN_ON_RATELIMIT(condition, state) \
WARN_ON((condition) && __ratelimit(state)) WARN_ON((condition) && __ratelimit(state))
......
...@@ -346,6 +346,7 @@ extern enum system_states { ...@@ -346,6 +346,7 @@ extern enum system_states {
#define TAINT_OVERRIDDEN_ACPI_TABLE 8 #define TAINT_OVERRIDDEN_ACPI_TABLE 8
#define TAINT_WARN 9 #define TAINT_WARN 9
#define TAINT_CRAP 10 #define TAINT_CRAP 10
#define TAINT_FIRMWARE_WORKAROUND 11
extern void dump_stack(void) __cold; extern void dump_stack(void) __cold;
......
...@@ -334,6 +334,16 @@ struct pci_dev { ...@@ -334,6 +334,16 @@ struct pci_dev {
#endif #endif
}; };
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
{
#ifdef CONFIG_PCI_IOV
if (dev->is_virtfn)
dev = dev->physfn;
#endif
return dev;
}
extern struct pci_dev *alloc_pci_dev(void); extern struct pci_dev *alloc_pci_dev(void);
#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
......
...@@ -178,6 +178,7 @@ static const struct tnt tnts[] = { ...@@ -178,6 +178,7 @@ static const struct tnt tnts[] = {
{ TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' }, { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
{ TAINT_WARN, 'W', ' ' }, { TAINT_WARN, 'W', ' ' },
{ TAINT_CRAP, 'C', ' ' }, { TAINT_CRAP, 'C', ' ' },
{ TAINT_FIRMWARE_WORKAROUND, 'I', ' ' },
}; };
/** /**
...@@ -194,6 +195,7 @@ static const struct tnt tnts[] = { ...@@ -194,6 +195,7 @@ static const struct tnt tnts[] = {
* 'A' - ACPI table overridden. * 'A' - ACPI table overridden.
* 'W' - Taint on warning. * 'W' - Taint on warning.
* 'C' - modules from drivers/staging are loaded. * 'C' - modules from drivers/staging are loaded.
* 'I' - Working around severe firmware bug.
* *
* The string is overwritten by the next call to print_tainted(). * The string is overwritten by the next call to print_tainted().
*/ */
...@@ -365,7 +367,8 @@ struct slowpath_args { ...@@ -365,7 +367,8 @@ struct slowpath_args {
va_list args; va_list args;
}; };
static void warn_slowpath_common(const char *file, int line, void *caller, struct slowpath_args *args) static void warn_slowpath_common(const char *file, int line, void *caller,
unsigned taint, struct slowpath_args *args)
{ {
const char *board; const char *board;
...@@ -381,7 +384,7 @@ static void warn_slowpath_common(const char *file, int line, void *caller, struc ...@@ -381,7 +384,7 @@ static void warn_slowpath_common(const char *file, int line, void *caller, struc
print_modules(); print_modules();
dump_stack(); dump_stack();
print_oops_end_marker(); print_oops_end_marker();
add_taint(TAINT_WARN); add_taint(taint);
} }
void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
...@@ -390,14 +393,29 @@ void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) ...@@ -390,14 +393,29 @@ void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
args.fmt = fmt; args.fmt = fmt;
va_start(args.args, fmt); va_start(args.args, fmt);
warn_slowpath_common(file, line, __builtin_return_address(0), &args); warn_slowpath_common(file, line, __builtin_return_address(0),
TAINT_WARN, &args);
va_end(args.args); va_end(args.args);
} }
EXPORT_SYMBOL(warn_slowpath_fmt); EXPORT_SYMBOL(warn_slowpath_fmt);
void warn_slowpath_fmt_taint(const char *file, int line,
unsigned taint, const char *fmt, ...)
{
struct slowpath_args args;
args.fmt = fmt;
va_start(args.args, fmt);
warn_slowpath_common(file, line, __builtin_return_address(0),
taint, &args);
va_end(args.args);
}
EXPORT_SYMBOL(warn_slowpath_fmt_taint);
void warn_slowpath_null(const char *file, int line) void warn_slowpath_null(const char *file, int line)
{ {
warn_slowpath_common(file, line, __builtin_return_address(0), NULL); warn_slowpath_common(file, line, __builtin_return_address(0),
TAINT_WARN, NULL);
} }
EXPORT_SYMBOL(warn_slowpath_null); EXPORT_SYMBOL(warn_slowpath_null);
#endif #endif
......
...@@ -165,7 +165,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) ...@@ -165,7 +165,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
(void *)bugaddr); (void *)bugaddr);
show_regs(regs); show_regs(regs);
add_taint(TAINT_WARN); add_taint(BUG_GET_TAINT(bug));
return BUG_TRAP_TYPE_WARN; return BUG_TRAP_TYPE_WARN;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment