提交 f5f6cbb6 编写于 作者: B Benjamin Herrenschmidt

powerpc: Don't Oops when accessing /proc/powerpc/lparcfg without hypervisor

/proc/powerpc/lparcfg is an ancient facility (though still actively used)
which allows access to some informations relative to the partition when
running underneath a PAPR compliant hypervisor.

It makes no sense on non-pseries machines. However, currently, not only
can it be created on these if the kernel has pseries support, but accessing
it on such a machine will crash due to trying to do hypervisor calls.

In fact, it should also not do HV calls on older pseries that didn't have
an hypervisor either.

Finally, it has the plumbing to be a module but is a "bool" Kconfig option.

This fixes the whole lot by turning it into a machine_device_initcall
that is only created on pseries, and adding the necessary hypervisor
check before calling the H_GET_EM_PARMS hypercall

CC: <stable@vger.kernel.org>
Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
上级 28e61cc4
...@@ -35,7 +35,13 @@ ...@@ -35,7 +35,13 @@
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/machdep.h>
/*
* This isn't a module but we expose that to userspace
* via /proc so leave the definitions here
*/
#define MODULE_VERS "1.9" #define MODULE_VERS "1.9"
#define MODULE_NAME "lparcfg" #define MODULE_NAME "lparcfg"
...@@ -418,7 +424,8 @@ static void parse_em_data(struct seq_file *m) ...@@ -418,7 +424,8 @@ static void parse_em_data(struct seq_file *m)
{ {
unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
if (plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS) if (firmware_has_feature(FW_FEATURE_LPAR) &&
plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]); seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
} }
...@@ -677,7 +684,6 @@ static int lparcfg_open(struct inode *inode, struct file *file) ...@@ -677,7 +684,6 @@ static int lparcfg_open(struct inode *inode, struct file *file)
} }
static const struct file_operations lparcfg_fops = { static const struct file_operations lparcfg_fops = {
.owner = THIS_MODULE,
.read = seq_read, .read = seq_read,
.write = lparcfg_write, .write = lparcfg_write,
.open = lparcfg_open, .open = lparcfg_open,
...@@ -699,14 +705,4 @@ static int __init lparcfg_init(void) ...@@ -699,14 +705,4 @@ static int __init lparcfg_init(void)
} }
return 0; return 0;
} }
machine_device_initcall(pseries, lparcfg_init);
static void __exit lparcfg_cleanup(void)
{
remove_proc_subtree("powerpc/lparcfg", NULL);
}
module_init(lparcfg_init);
module_exit(lparcfg_cleanup);
MODULE_DESCRIPTION("Interface for LPAR configuration data");
MODULE_AUTHOR("Dave Engebretsen");
MODULE_LICENSE("GPL");
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册