Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754888AbaDON7b (ORCPT ); Tue, 15 Apr 2014 09:59:31 -0400 Received: from mga09.intel.com ([134.134.136.24]:26688 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754423AbaDON70 (ORCPT ); Tue, 15 Apr 2014 09:59:26 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,864,1389772800"; d="scan'208";a="513522952" From: Rui Wang To: bhelgaas@google.com, tony.luck@intel.com, rafael.j.wysocki@intel.com Cc: ruiv.wang@gmail.com, chaohong.guo@intel.com, dave.hansen@intel.com, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Rui Wang Subject: [PATCH v3 4/5] I/O Hook: Override MSRs while triggering MCEs Date: Tue, 15 Apr 2014 21:48:10 +0800 Message-Id: <1397569691-24691-5-git-send-email-rui.y.wang@intel.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1397569691-24691-1-git-send-email-rui.y.wang@intel.com> References: <1397569691-24691-1-git-send-email-rui.y.wang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org MSRs can be overriden by specifying a cpu id and an MSR number. bash# echo "0:17a-8[4/4]ro" > msr would override MSR 0x17a on cpu0. Use 'all' as the cpu id to override the MSR on all CPUs. e.g. "all:17a-8[4/4]ro" When specifying the interrupt to be triggered, a positive number denotes an IRQ and a negative number denotes a vector, thus bash# echo -18 > irq specifies that a machine check exception (int 18) will be triggered. Signed-off-by: Rui Wang --- Documentation/PCI/iohook.txt | 31 ++++++-- arch/x86/include/asm/msr.h | 100 ++++++++++++++++++++- arch/x86/lib/msr-smp.c | 31 +++++++ drivers/misc/iohook/iohook.c | 195 +++++++++++++++++++++++++++++++++++++++--- include/linux/reg_ovrd.h | 1 + 5 files changed, 335 insertions(+), 23 deletions(-) diff --git a/Documentation/PCI/iohook.txt b/Documentation/PCI/iohook.txt index ae9b4ad..9b3f232 100644 --- a/Documentation/PCI/iohook.txt +++ b/Documentation/PCI/iohook.txt @@ -52,11 +52,12 @@ a directory subtree is created under /sys/kernel/debug/iohook bash# cd /sys/kernel/debug/iohook bash# ls -io irq mem pciconf trigger +io irq mem msr pciconf trigger Each file is used to manage a type of resource. 'io' is used to add/show Register Overrides in IO port space. 'mem' is used to add/show Register Overrides in memory space. +'msr' is used to add/show Register Overrides in MSR space. 'pciconf' is used to add/show Register Overrides in pci config space. 'irq' is used to set the desired IRQ to be triggered via IPI. 'trigger' is used to turn on/off the I/O Hook. @@ -74,8 +75,15 @@ for a Register Override in PCI config space, it's specified as: domain|bus:dev.func+offset-length[value/mask]attribute +for a Register Override in MSR space, it's specified as: + + cpuid:regnum-length[value/mask]attribute + where address - the 64bit address of the h/w register to be overridden + cpuid - the cpu on which the MSR specified by regnum is to be + overriden. Use 'all' as the cpuid to specify all cpus. + regnum - the MSR to be overriden. length - the number of bytes affected. Affected here means that at least one bit in that byte is overridden. For 'length' @@ -124,24 +132,35 @@ The syntax is "domain|bus:dev.func+offset-length[value/mask]attribute" The first register overrides only bit0 and the second register overrides the first 2 bytes (mask == 0xffff), with an initial value of 0x0500. +As another example, MSRs can be overriden by specifying a cpu id and an MSR +number: + +bash# echo "0:17a-8[4/4]ro" > msr +The above specifies that bit2 of MSR 0x17a on cpu0 is overriden as 1 (bit set). + Register Overrides are disabled when added. They can be enabled by using the 'trigger' file. See below. 2.3 Add IRQ and enable the Register Overrides -To specify an IRQ to be triggered via IPI, just echo the IRQ number in decimal -to the 'irq' file. For example: +To specify an interrupt to be triggered via IPI, just echo the IRQ or vector +number in decimal to the 'irq' file. A positive number denotes an IRQ and a +negative number denotes a vector. For example: bash# cd /sys/kernel/debug/iohook bash# echo 9 > irq This specifies that IRQ9 be triggered after the Register Overrides are enabled. -To enable the Register Overrides in the kernel: +bash# echo -18 > irq +specifies that a machine check exception(vector 18) will be triggered. + +Register Overrides are disabled after added. Use the 'trigger' file to enabled +them all: bash# echo 1 > trigger -This immediately enables all the Register Overrides and if an IRQ number was -specified, generate the IPI. +This immediately enables all the Register Overrides and if an IRQ (or vector) +number was specified, generate the IPI. To disable the Register Overrides in the kernel: diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index de36f22..cfbfc91 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -57,7 +57,69 @@ static inline unsigned long long native_read_tscp(unsigned int *aux) #define EAX_EDX_RET(val, low, high) "=A" (val) #endif -static inline unsigned long long native_read_msr(unsigned int msr) +#if !defined(NO_IO_HOOK) && defined(CONFIG_IO_HOOK) +#ifndef CC_HAVE_ASM_GOTO +#error "gcc 4.5 feature CC_HAVE_ASM_GOTO is required" +#endif +struct static_key; +#include +#include + +#define msr_read_ovrd(addr) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled) \ + && !read_ovrd_common(OVRD_SPACE_MSR, (u64)addr, \ + sizeof(u64), &val, NULL)) \ + return val; \ +} + +#define msr_read_ovrd_safe(addr, err) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled)) { \ + struct msr_regs_info rv; \ + /* Use rv.reg to tell from *_safe_regs() */ \ + rv.regs = NULL; \ + if (!read_ovrd_common(OVRD_SPACE_MSR, (u64)addr,\ + sizeof(u64), &val, &rv)) { \ + *err = rv.err; \ + return val; \ + } \ + } \ +} +#define msr_write_ovrd_safe(addr, low, high) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled)) { \ + struct msr_regs_info rv; \ + /* Use rv.reg to tell from *_safe_regs() */ \ + rv.regs = NULL; \ + val = (low) | ((u64)(high) << 32); \ + if (!write_ovrd_common(OVRD_SPACE_MSR, addr, \ + sizeof(u64), &val, &rv)) \ + return rv.err; \ + } \ +} + +#define msr_write_ovrd(addr, low, high) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled)) { \ + val = (low) | ((u64)(high) << 32); \ + if (!write_ovrd_common(OVRD_SPACE_MSR, addr, \ + sizeof(u64), &val, NULL)) \ + return; \ + } \ +} +#else /* CONFIG_IO_HOOK */ +#define msr_read_ovrd(addr) +#define msr_read_ovrd_safe(addr, err) +#define msr_write_ovrd(addr, low, high) +#define msr_write_ovrd_safe(addr, low, high) +#endif /* CONFIG_IO_HOOK */ + +static inline unsigned long long native_do_read_msr(unsigned int msr) { DECLARE_ARGS(val, low, high); @@ -65,7 +127,14 @@ static inline unsigned long long native_read_msr(unsigned int msr) return EAX_EDX_VAL(val, low, high); } -static inline unsigned long long native_read_msr_safe(unsigned int msr, +static inline unsigned long long native_read_msr(unsigned int msr) +{ + + msr_read_ovrd(msr); + return native_do_read_msr(msr); +} + +static inline unsigned long long native_do_read_msr_safe(unsigned int msr, int *err) { DECLARE_ARGS(val, low, high); @@ -81,14 +150,27 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, return EAX_EDX_VAL(val, low, high); } -static inline void native_write_msr(unsigned int msr, +static inline unsigned long long native_read_msr_safe(unsigned int msr, + int *err) +{ + msr_read_ovrd_safe(msr, err); + return native_do_read_msr_safe(msr, err); +} + +static inline void native_do_write_msr(unsigned int msr, unsigned low, unsigned high) { asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); } -/* Can be uninlined because referenced by paravirt */ -notrace static inline int native_write_msr_safe(unsigned int msr, +static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) +{ + msr_write_ovrd(msr, low, high); + native_do_write_msr(msr, low, high); +} + +static inline int native_do_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int err; @@ -105,6 +187,14 @@ notrace static inline int native_write_msr_safe(unsigned int msr, return err; } +/* Can be uninlined because referenced by paravirt */ +static inline int native_write_msr_safe(unsigned int msr, + unsigned low, unsigned high) +{ + msr_write_ovrd_safe(msr, low, high); + return native_do_write_msr_safe(msr, low, high); +} + extern unsigned long long native_read_tsc(void); extern int rdmsr_safe_regs(u32 regs[8]); diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c index 518532e..6a5f177 100644 --- a/arch/x86/lib/msr-smp.c +++ b/arch/x86/lib/msr-smp.c @@ -128,6 +128,33 @@ void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) } EXPORT_SYMBOL(rdmsr_on_cpus); +#if !defined(NO_IO_HOOK) && defined(CONFIG_IO_HOOK) + +#define rdmsr_safe_regs_ovrd(rv) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled)) { \ + if (!read_ovrd_common(OVRD_SPACE_MSR, 0, \ + sizeof(u64), &val, rv)) \ + return; \ + } \ +} + +#define wrmsr_safe_regs_ovrd(rv) \ +{ \ + u64 val;\ + if (arch_static_branch(&ovrdhw_enabled)) { \ + if (!write_ovrd_common(OVRD_SPACE_MSR, 0, \ + sizeof(u64), &val, rv)) \ + return; \ + } \ +} + +#else +#define rdmsr_safe_regs_ovrd(rv) +#define wrmsr_safe_regs_ovrd(rv) +#endif + /* * wrmsr on a bunch of CPUs * @@ -229,6 +256,8 @@ static void __rdmsr_safe_regs_on_cpu(void *info) { struct msr_regs_info *rv = info; + rdmsr_safe_regs_ovrd(rv); + rv->err = rdmsr_safe_regs(rv->regs); } @@ -236,6 +265,8 @@ static void __wrmsr_safe_regs_on_cpu(void *info) { struct msr_regs_info *rv = info; + wrmsr_safe_regs_ovrd(rv); + rv->err = wrmsr_safe_regs(rv->regs); } diff --git a/drivers/misc/iohook/iohook.c b/drivers/misc/iohook/iohook.c index 5584eb7..f81f553 100644 --- a/drivers/misc/iohook/iohook.c +++ b/drivers/misc/iohook/iohook.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "iohook.h" MODULE_LICENSE("GPL"); @@ -35,6 +36,7 @@ static DEFINE_RAW_SPINLOCK(engine_lock); LIST_HEAD(ovrd_io_reg_map); LIST_HEAD(ovrd_mem_reg_map); LIST_HEAD(ovrd_pci_conf_reg_map); +LIST_HEAD(ovrd_msr_map); struct static_key ovrdhw_enabled = STATIC_KEY_INIT_FALSE; EXPORT_SYMBOL(ovrdhw_enabled); @@ -52,8 +54,10 @@ struct reg_ovrd *iohook_query_ovrd(int spaceid, int idx) reg_ovrd = &ovrd_mem_reg_map; else if (spaceid == OVRD_SPACE_IO) reg_ovrd = &ovrd_io_reg_map; - else + else if (spaceid == OVRD_SPACE_PCICONF) reg_ovrd = &ovrd_pci_conf_reg_map; + else + reg_ovrd = &ovrd_msr_map; regentry = NULL; raw_spin_lock_irqsave(&io_hook_lock, lock_flags); @@ -80,8 +84,10 @@ void iohook_cleanup_ovrd(int spaceid) ovrd_list = &ovrd_mem_reg_map; else if (spaceid == OVRD_SPACE_IO) ovrd_list = &ovrd_io_reg_map; - else + else if (spaceid == OVRD_SPACE_PCICONF) ovrd_list = &ovrd_pci_conf_reg_map; + else + ovrd_list = &ovrd_msr_map; list_for_each_safe(tmp, next, ovrd_list) { struct reg_ovrd *ovrdreg = @@ -103,8 +109,10 @@ void iohook_add_ovrd(int spaceid, u64 address, u64 value, u64 mask, reg_ovrd = &ovrd_mem_reg_map; else if (spaceid == OVRD_SPACE_IO) reg_ovrd = &ovrd_io_reg_map; - else + else if (spaceid == OVRD_SPACE_PCICONF) reg_ovrd = &ovrd_pci_conf_reg_map; + else + reg_ovrd = &ovrd_msr_map; raw_spin_lock_irqsave(&io_hook_lock, lock_flags); list_for_each_entry(ovrdreg, reg_ovrd, node) { @@ -353,6 +361,20 @@ int read_ovrd_common(int spaceid, u64 address, int len, void *value, void *bus) devfn = PCI_DECODE_DEVFN(address); pos = PCI_DECODE_POS(address); ovrd_list = &ovrd_pci_conf_reg_map; + } else if (spaceid == OVRD_SPACE_MSR) { + unsigned int cpuid; + + ovrd_list = &ovrd_msr_map; + cpuid = smp_processor_id(); + + /* + * MSRs are 64bit wide, so x8 to form a contiguous + * address space + */ + address *= 8; + + /* upper 32bits contain the cpu id */ + address |= (u64)cpuid << 32; } else { return ret; } @@ -392,6 +414,29 @@ int read_ovrd_common(int spaceid, u64 address, int len, void *value, void *bus) res = pcib->ops->read(pcib, devfn, pos, len, (u32 *)&data); raw_spin_unlock_irqrestore(&pci_lock, flags); + } else if (spaceid == OVRD_SPACE_MSR) { + struct msr_regs_info *rv; + unsigned int msr; + + rv = (struct msr_regs_info *)bus; + msr = address & 0xffffffff; + if (rv && rv->regs) { /* rdmsr_safe_regs() */ + u32 low, high; + + rv->err = rdmsr_safe_regs(rv->regs); + low = rv->regs[0]; /* eax */ + high = rv->regs[2]; /* edx */ + data = low | ((u64)high << 32); + res = rv->err; + } else if (rv) { /* rv->regs == NULL */ + data = native_do_read_msr_safe(msr, + &rv->err); + res = rv->err; + } else { /* rv == NULL */ + data = native_do_read_msr(msr); + res = 0; + } + } else goto out; @@ -486,6 +531,20 @@ int write_ovrd_common(int spaceid, u64 address, int len, void *data, void *bus) devfn = PCI_DECODE_DEVFN(address); pos = PCI_DECODE_POS(address); ovrd_list = &ovrd_pci_conf_reg_map; + } else if (spaceid == OVRD_SPACE_MSR) { + unsigned int cpuid; + + cpuid = smp_processor_id(); + + /* + * MSRs are 64bit wide, so x8 to form a contiguous + * address space + */ + address *= 8; + + /* upper 32bits contain the cpu id */ + address |= (u64)cpuid << 32; + ovrd_list = &ovrd_msr_map; } else { return ret; } @@ -525,6 +584,23 @@ int write_ovrd_common(int spaceid, u64 address, int len, void *data, void *bus) raw_spin_unlock_irqrestore(&pci_lock, flags); raw_spin_lock_irqsave(&io_hook_lock, lock_flags); + } else if (spaceid == OVRD_SPACE_MSR) { + struct msr_regs_info *rv; + unsigned int msr, low, high; + + rv = (struct msr_regs_info *)bus; + msr = address & 0xffffffff; + low = value & 0xffffffff; + high = value >> 32; + + if (rv && rv->regs) { /* wrmsr_safe_regs() */ + rv->err = wrmsr_safe_regs(rv->regs); + } else if (rv) { /* rv->regs == NULL */ + rv->err = native_do_write_msr_safe(msr, + low, high); + } else { /* rv == NULL */ + native_do_write_msr(msr, low, high); + } } else break; } @@ -566,12 +642,22 @@ int write_ovrd_common(int spaceid, u64 address, int len, void *data, void *bus) } EXPORT_SYMBOL(write_ovrd_common); -static void trigger_irq_by_ipi(unsigned long irqnum) +static void trigger_irq_by_ipi(long irqnum) { struct irq_desc *desc; struct irq_data *data; struct irq_chip *chip; + if (irqnum < 0) { /* vector number */ + pr_info("sending IPI to vector:%ld\n", -irqnum); + if (-irqnum == 18) + apic->send_IPI_all(-irqnum); + else + apic->send_IPI_self(-irqnum); + pr_info("Returned from sending IPI to vector:%ld\n", -irqnum); + return; + } + desc = irq_to_desc(irqnum); data = irq_desc_get_irq_data(desc); chip = irq_data_get_irq_chip(data); @@ -637,7 +723,11 @@ ssize_t hook_irq_read(struct file *file, char __user *ubuf, size_t cnt, char buf[64]; /* big enough to hold a number */ int r; - r = sprintf(buf, "%u\n", g_irq_num); + if (g_irq_num >= 0) + r = sprintf(buf, "irq:%u\n", g_irq_num); + else + r = sprintf(buf, "vector:%u\n", -g_irq_num); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } @@ -645,7 +735,7 @@ static ssize_t hook_irq_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { char *irq = NULL; - unsigned long irqnum, ret; + long irqnum, ret; irq = kmalloc(count+1, GFP_ATOMIC); if (!irq) { @@ -655,13 +745,19 @@ static ssize_t hook_irq_write(struct file *file, const char __user *user_buf, irq[count] = '\0'; if (copy_from_user(irq, user_buf, count)) goto end; - ret = kstrtoul(irq, 10, &irqnum); + + ret = kstrtol(irq, 10, &irqnum); if (ret) { - pr_err("bogus irq number? %s\n", irq); + pr_err("bogus irq/vector number? %s\n", irq); goto end; } - if (irqnum > NR_IRQS) { - pr_err("irq num too big: %lu\n", irqnum); + + /* + * if irqnum < 0 it's a vector number + * if irqnum > 0 it's a IRQ number + */ + if (irqnum <= -NR_VECTORS || irqnum >= NR_IRQS) { + pr_err("irq/vector num too big: %ld\n", irqnum); goto end; } @@ -733,6 +829,13 @@ hook_seq_show(struct seq_file *s, void *it) regmap->address, regmap->length, regmap->val, regmap->bit_mask, hook_attrib(regmap->attrib)); break; + case OVRD_SPACE_MSR: + seq_printf(s, + "cpu%d msr: 0x%x length: 0x%x value: 0x%llx mask: 0x%llx attrib: %s\n", + (u32)(regmap->address >> 32), (u32)(regmap->address)/8, + regmap->length, regmap->val, regmap->bit_mask, + hook_attrib(regmap->attrib)); + break; case OVRD_SPACE_PCICONF: seq_printf(s, "pciconf: 0x%04x|%02x:%02x.%02x offset: 0x%x lenght: 0x%x value: 0x%llx mask: 0x%llx attrib: %s\n", @@ -772,6 +875,19 @@ hook_io_open(struct inode *inode, struct file *file) } static int +hook_msr_open(struct inode *inode, struct file *file) +{ + struct hook_iter *iter; + + iter = __seq_open_private(file, &hook_seq_ops, + sizeof(struct hook_iter)); + if (iter) + iter->spaceid = OVRD_SPACE_MSR; + + return iter ? 0 : -ENOMEM; +} + +static int hook_mem_open(struct inode *inode, struct file *file) { struct hook_iter *iter; @@ -817,12 +933,12 @@ hook_parse_entry(char *entry, int spaceid) { char *field; u64 address, length, value, mask; - unsigned long domain, bus, dev, func; + unsigned long domain, bus, dev, func, cpu; int attrib, ret; u16 cval; if (spaceid != OVRD_SPACE_PCICONF) - goto mem_io; + goto msr; field = strsep(&entry, "|"); ret = kstrtoul(field, 16, &domain); @@ -843,6 +959,20 @@ hook_parse_entry(char *entry, int spaceid) ret = kstrtoul(field, 16, &func); if (ret || !entry) return -1; +msr: + if (spaceid != OVRD_SPACE_MSR) + goto mem_io; + field = strsep(&entry, ":"); + if (strcasecmp(field, "all") == 0) { + /* All cpus */ + cpu = (unsigned long)-1; + ret = 0; + } else { + ret = kstrtoul(field, 16, &cpu); + } + pr_info("parse_hook_entry() cpu=0x%lx\n", cpu); + if (ret || !entry) + return -1; mem_io: field = strsep(&entry, "-"); @@ -850,6 +980,13 @@ mem_io: if (ret || !entry) return -1; + /* + * MSRs are 64bit wide, so x8 to form a contiguous + * address space + */ + if (spaceid == OVRD_SPACE_MSR) + address *= 8; + pr_info("parse_hook_entry() address=0x%llx\n", address); field = strsep(&entry, "["); @@ -888,6 +1025,17 @@ mem_io: if (spaceid == OVRD_SPACE_PCICONF) { address = PCI_ENCODE_ADDR(domain, bus, PCI_DEVFN(dev, func), address); + } else if (spaceid == OVRD_SPACE_MSR) { + if (cpu == (unsigned long)-1) { /* all cpus */ + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { + address &= 0xffffffff; + address |= cpu << 32; + iohook_add_ovrd(spaceid, address, value, mask, + length, attrib); + } + return 0; + } + address |= cpu << 32; } iohook_add_ovrd(spaceid, address, value, mask, length, attrib); @@ -945,6 +1093,14 @@ hook_io_write(struct file *file, const char __user *user_buf, } static ssize_t +hook_msr_write(struct file *file, const char __user *user_buf, + size_t user_len, loff_t *offset) +{ + + return hook_write(file, user_buf, user_len, offset, OVRD_SPACE_MSR); +} + +static ssize_t hook_mem_write(struct file *file, const char __user *user_buf, size_t user_len, loff_t *offset) { @@ -968,6 +1124,14 @@ static const struct file_operations hook_io_fops = { .write = hook_io_write, }; +static const struct file_operations hook_msr_fops = { + .open = hook_msr_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, + .write = hook_msr_write, +}; + static const struct file_operations hook_mem_fops = { .open = hook_mem_open, .read = seq_read, @@ -1007,11 +1171,18 @@ static int __init iohook_init(void) if (hook_irq_dentry == NULL) return -ENODEV; +#ifdef CONFIG_X86 hook_reg_dentry = debugfs_create_file("io", S_IWUSR, root, NULL, &hook_io_fops); if (hook_reg_dentry == NULL) return -ENODEV; + hook_reg_dentry = debugfs_create_file("msr", S_IWUSR, + root, NULL, &hook_msr_fops); + if (hook_reg_dentry == NULL) + return -ENODEV; +#endif + hook_reg_dentry = debugfs_create_file("mem", S_IWUSR, root, NULL, &hook_mem_fops); if (hook_reg_dentry == NULL) diff --git a/include/linux/reg_ovrd.h b/include/linux/reg_ovrd.h index 2707d6c..ce655fe 100644 --- a/include/linux/reg_ovrd.h +++ b/include/linux/reg_ovrd.h @@ -37,6 +37,7 @@ struct reg_ovrd { #define OVRD_SPACE_IO 0 #define OVRD_SPACE_MEM 1 #define OVRD_SPACE_PCICONF 2 +#define OVRD_SPACE_MSR 3 #define PCI_ENCODE_ADDR(domain, bus, devfn, pos) \ (((u64)(domain))<<32|(bus)<<20|(devfn)<<12|(pos)) -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/