* [RFC PATCH 00/10] OPAL V4
@ 2020-05-02 11:19 Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 01/10] kallsyms: architecture specific symbol lookups Nicholas Piggin
` (9 more replies)
0 siblings, 10 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
"OPAL V4" is a proposed new approach to running and calling PowerNV
OPAL firmware.
OPAL calls use the caller's (kernel) stack, which vastly simplifies
re-entrancy concerns around doing things like idle and machine check
OPAL drivers.
The OS can get at symbol and assert metadata to help with debugging
firmware.
OPAL may be called (and will run in) virtual mode in its own address
space.
And the operating system provides some services to the firmware,
message logging, for example.
This fairly close to the point where we could run OPAL in user-mode
with a few services (scv could be used to call back to the OS) for
privileged instructions, we may yet do this, but one thing that's
stopped me is it would require a slower API. As it is now with LE
skiboot and LE Linux, the OPAL call is basically a shared-library
function call, which is fast enough that it's feasible to
implement a performant CPU idle driver, which is a significant
motivation.
Anyway this is up and running, coming together pretty well just needs
a bit of polishing and more documentation. I'll post the skiboot
patches on the skiboot list.
Nicholas Piggin (10):
kallsyms: architecture specific symbol lookups
powerpc/powernv: Wire up OPAL address lookups
powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts
from OPAL
powerpc/powernv: avoid polling in opal_get_chars
powerpc/powernv: Don't translate kernel addresses to real addresses
for OPAL
powerpc/powernv: opal use new opal call entry point if it exists
powerpc/powernv: Add OPAL_FIND_VM_AREA API
powerpc/powernv: Set up an mm context to call OPAL in
powerpc/powernv: OPAL V4 OS services
powerpc/powernv: OPAL V4 Implement vm_map/unmap service
arch/powerpc/Kconfig | 1 +
arch/powerpc/boot/opal.c | 5 +
arch/powerpc/include/asm/opal-api.h | 29 +-
arch/powerpc/include/asm/opal.h | 8 +
arch/powerpc/kernel/traps.c | 39 ++-
arch/powerpc/perf/imc-pmu.c | 4 +-
arch/powerpc/platforms/powernv/npu-dma.c | 2 +-
arch/powerpc/platforms/powernv/opal-call.c | 58 ++++
arch/powerpc/platforms/powernv/opal-dump.c | 2 +-
arch/powerpc/platforms/powernv/opal-elog.c | 4 +-
arch/powerpc/platforms/powernv/opal-flash.c | 6 +-
arch/powerpc/platforms/powernv/opal-hmi.c | 2 +-
arch/powerpc/platforms/powernv/opal-nvram.c | 4 +-
.../powerpc/platforms/powernv/opal-powercap.c | 2 +-
arch/powerpc/platforms/powernv/opal-psr.c | 2 +-
arch/powerpc/platforms/powernv/opal-xscom.c | 2 +-
arch/powerpc/platforms/powernv/opal.c | 289 ++++++++++++++++--
arch/powerpc/platforms/powernv/pci-ioda.c | 2 +-
arch/powerpc/sysdev/xive/native.c | 2 +-
drivers/char/powernv-op-panel.c | 3 +-
drivers/i2c/busses/i2c-opal.c | 12 +-
drivers/mtd/devices/powernv_flash.c | 4 +-
include/linux/kallsyms.h | 20 ++
kernel/kallsyms.c | 13 +-
lib/Kconfig | 3 +
25 files changed, 461 insertions(+), 57 deletions(-)
--
2.23.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH 01/10] kallsyms: architecture specific symbol lookups
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 02/10] powerpc/powernv: Wire up OPAL address lookups Nicholas Piggin
` (8 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
Provide CONFIG_ARCH_HAS_SYMBOL_LOOKUP which allows architectures to
do their own symbol/address lookup if kernel and module lookups miss.
powerpc will use this to deal with firmware symbols.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/linux/kallsyms.h | 20 ++++++++++++++++++++
kernel/kallsyms.c | 13 ++++++++++++-
lib/Kconfig | 3 +++
3 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 657a83b943f0..e17c1e7c01c0 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -83,6 +83,26 @@ extern int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset);
+#ifdef CONFIG_ARCH_HAS_SYMBOL_LOOKUP
+const char *arch_symbol_lookup_address(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname, char *namebuf);
+unsigned long arch_symbol_lookup_name(const char *name);
+#else
+static inline const char *arch_symbol_lookup_address(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname, char *namebuf)
+{
+ return NULL;
+}
+static inline unsigned long arch_symbol_lookup_name(const char *name)
+{
+ return 0;
+}
+#endif
+
/* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 16c8c605f4b0..1e403e616126 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -164,6 +164,7 @@ static unsigned long kallsyms_sym_address(int idx)
unsigned long kallsyms_lookup_name(const char *name)
{
char namebuf[KSYM_NAME_LEN];
+ unsigned long ret;
unsigned long i;
unsigned int off;
@@ -173,7 +174,12 @@ unsigned long kallsyms_lookup_name(const char *name)
if (strcmp(namebuf, name) == 0)
return kallsyms_sym_address(i);
}
- return module_kallsyms_lookup_name(name);
+
+ ret = module_kallsyms_lookup_name(name);
+ if (ret)
+ return ret;
+
+ return arch_symbol_lookup_name(name);
}
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
@@ -309,6 +315,11 @@ const char *kallsyms_lookup(unsigned long addr,
if (!ret)
ret = ftrace_mod_address_lookup(addr, symbolsize,
offset, modname, namebuf);
+
+ if (!ret)
+ ret = arch_symbol_lookup_address(addr, symbolsize,
+ offset, modname, namebuf);
+
return ret;
}
diff --git a/lib/Kconfig b/lib/Kconfig
index 5d53f9609c25..9f86f649a712 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -80,6 +80,9 @@ config ARCH_USE_CMPXCHG_LOCKREF
config ARCH_HAS_FAST_MULTIPLIER
bool
+config ARCH_HAS_SYMBOL_LOOKUP
+ bool
+
config INDIRECT_PIO
bool "Access I/O in non-MMIO mode"
depends on ARM64
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 02/10] powerpc/powernv: Wire up OPAL address lookups
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 01/10] kallsyms: architecture specific symbol lookups Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL Nicholas Piggin
` (7 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
Use ARCH_HAS_SYMBOL_LOOKUP to look up the opal symbol table. This
allows crashes and xmon debugging to print firmware symbols.
Oops: System Reset, sig: 6 [#1]
LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV
Modules linked in:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.0-rc2-dirty #903
NIP: 0000000030020434 LR: 000000003000378c CTR: 0000000030020414
REGS: c0000000fffc3d70 TRAP: 0100 Not tainted (5.6.0-rc2-dirty)
MSR: 9000000002101002 <SF,HV,VEC,ME,RI> CR: 28022284 XER: 20040000
CFAR: 0000000030003788 IRQMASK: 3
GPR00: 000000003000378c 0000000031c13c90 0000000030136200 c0000000012cfa10
GPR04: c0000000012cfa10 0000000000000010 0000000000000000 0000000031c10060
GPR08: c0000000012cfaaf 0000000030003640 0000000000000000 0000000000000001
GPR12: 00000000300e0000 c000000001490000 0000000000000000 c00000000139c588
GPR16: 0000000031c10000 c00000000125a900 0000000000000000 c0000000012076a8
GPR20: c0000000012a3950 0000000000000001 0000000031c10060 c0000000012cfaaf
GPR24: 0000000000000019 0000000030003640 0000000000000000 0000000000000000
GPR28: 0000000000000010 c0000000012cfa10 0000000000000000 0000000000000000
NIP [0000000030020434] .dummy_console_write_buffer_space+0x20/0x64 [OPAL]
LR [000000003000378c] opal_entry+0x14c/0x17c [OPAL]
This won't unwind the firmware stack (or its Linux caller) properly if
firmware and kernel endians don't match, but that problem could be solved
in powerpc's unwinder.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/opal-api.h | 4 ++-
arch/powerpc/include/asm/opal.h | 3 ++
arch/powerpc/platforms/powernv/opal-call.c | 2 ++
arch/powerpc/platforms/powernv/opal.c | 40 ++++++++++++++++++++++
5 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 924c541a9260..0be717291e38 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -115,6 +115,7 @@ config PPC
# Please keep this list sorted alphabetically.
#
select ARCH_32BIT_OFF_T if PPC32
+ select ARCH_HAS_SYMBOL_LOOKUP if PPC_POWERNV
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 1dffa3cb16ba..8eb31b9aeb27 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -214,7 +214,9 @@
#define OPAL_SECVAR_GET 176
#define OPAL_SECVAR_GET_NEXT 177
#define OPAL_SECVAR_ENQUEUE_UPDATE 178
-#define OPAL_LAST 178
+#define OPAL_ADDR_TO_SYM 181
+#define OPAL_SYM_TO_ADDR 182
+#define OPAL_LAST 182
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9986ac34b8e2..56b6994aefb7 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -312,6 +312,9 @@ s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
s64 opal_signal_system_reset(s32 cpu);
s64 opal_quiesce(u64 shutdown_type, s32 cpu);
+int64_t opal_addr_to_sym(uint64_t addr, __be64 *symaddr, __be64 *symsize, char *namebuf, uint64_t buflen);
+int64_t opal_sym_to_addr(const char *name, __be64 *symaddr, __be64 *symsize);
+
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
int depth, void *data);
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 5cd0f52d258f..2233a58924cb 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -293,3 +293,5 @@ OPAL_CALL(opal_mpipl_query_tag, OPAL_MPIPL_QUERY_TAG);
OPAL_CALL(opal_secvar_get, OPAL_SECVAR_GET);
OPAL_CALL(opal_secvar_get_next, OPAL_SECVAR_GET_NEXT);
OPAL_CALL(opal_secvar_enqueue_update, OPAL_SECVAR_ENQUEUE_UPDATE);
+OPAL_CALL(opal_addr_to_sym, OPAL_ADDR_TO_SYM);
+OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 2b3dfd0b6cdd..1bf2e0b31ecf 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -107,6 +107,46 @@ void opal_configure_cores(void)
cur_cpu_spec->cpu_restore();
}
+const char *arch_symbol_lookup_address(unsigned long addr,
+ unsigned long *symbolsize,
+ unsigned long *offset,
+ char **modname, char *namebuf)
+{
+ __be64 symaddr;
+ __be64 symsize;
+
+ if (!firmware_has_feature(FW_FEATURE_OPAL))
+ return NULL;
+
+ if (opal_addr_to_sym(addr, &symaddr, &symsize, namebuf,
+ cpu_to_be64(KSYM_NAME_LEN)) != OPAL_SUCCESS)
+ return NULL;
+
+ *symbolsize = be64_to_cpu(symsize);
+ *offset = addr - be64_to_cpu(symaddr);
+ *modname = "OPAL";
+
+ return namebuf;
+}
+
+unsigned long arch_symbol_lookup_name(const char *name)
+{
+ __be64 addr;
+ __be64 size;
+
+ if (!firmware_has_feature(FW_FEATURE_OPAL))
+ return 0;
+
+ /* opal: prefix allows lookup of symbols that clash with kernel */
+ if (!strncasecmp(name, "opal:", strlen("opal:")))
+ name += strlen("opal:");
+
+ if (opal_sym_to_addr(name, &addr, &size) != OPAL_SUCCESS)
+ return 0;
+
+ return be64_to_cpu(addr);
+}
+
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 01/10] kallsyms: architecture specific symbol lookups Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 02/10] powerpc/powernv: Wire up OPAL address lookups Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 14:30 ` kbuild test robot
2020-05-02 11:19 ` [RFC PATCH 04/10] powerpc/powernv: avoid polling in opal_get_chars Nicholas Piggin
` (6 subsequent siblings)
9 siblings, 1 reply; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This isn't used yet, because OPAL is nice enough not to cause unexpected
program check interrupts to the OS. A future patch will allow OPAL to
start using traps. Like so.
[OPAL] < assert failed at core/opal.c:814 >
[OPAL] .
[OPAL] .
[OPAL] .
[OPAL] OO__)
[OPAL] <"__/
[OPAL] ^ ^
cpu 0x0: Vector: 700 (Program Check) at [c000000080287770]
pc: 000000003002f360: opal_poll_events+0x54/0x174 [OPAL]
lr: 000000003002f344: opal_poll_events+0x38/0x174 [OPAL]
sp: c000000080287a00
msr: 9000000000021033
current = 0xc0000000016fa100
paca = 0xc0000000012c0000^I irqmask: 0x03^I irq_happened: 0x01
pid = 19, comm = kopald
Linux version 5.7.0-rc3-00053-g2d9c3c965178-dirty
enter ? for help
[c000000080287a80] 000000003002e6b8 opal_v4_le_entry+0x224/0x29c [OPAL]
[c000000080287b50] c000000000096ce8 opal_call+0x1c8/0x580
[c000000080287c90] c000000000097448 opal_poll_events+0x28/0x40
[c000000080287d00] c0000000000a26e0 opal_handle_events+0x70/0x140
[c000000080287d50] c00000000009a198 kopald+0x98/0x140
[c000000080287db0] c00000000012139c kthread+0x18c/0x1a0
[c000000080287e20] c00000000000cc28 ret_from_kernel_thread+0x5c/0x74
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/opal-api.h | 7 +++-
arch/powerpc/include/asm/opal.h | 2 ++
arch/powerpc/kernel/traps.c | 39 ++++++++++++++++------
arch/powerpc/platforms/powernv/opal-call.c | 1 +
4 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 8eb31b9aeb27..018d4734c323 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -216,7 +216,8 @@
#define OPAL_SECVAR_ENQUEUE_UPDATE 178
#define OPAL_ADDR_TO_SYM 181
#define OPAL_SYM_TO_ADDR 182
-#define OPAL_LAST 182
+#define OPAL_REPORT_TRAP 183
+#define OPAL_LAST 183
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1184,6 +1185,10 @@ struct opal_mpipl_fadump {
struct opal_mpipl_region region[];
} __packed;
+#define OPAL_TRAP_FATAL 1
+#define OPAL_TRAP_WARN 2
+#define OPAL_TRAP_PANIC 3
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 56b6994aefb7..dc77c2d5e036 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -314,6 +314,8 @@ s64 opal_quiesce(u64 shutdown_type, s32 cpu);
int64_t opal_addr_to_sym(uint64_t addr, __be64 *symaddr, __be64 *symsize, char *namebuf, uint64_t buflen);
int64_t opal_sym_to_addr(const char *name, __be64 *symaddr, __be64 *symsize);
+int64_t opal_report_trap(uint64_t nip);
+
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3fca22276bb1..0274ae7b8a03 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -52,6 +52,7 @@
#endif
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
+#include <asm/opal.h>
#include <asm/processor.h>
#include <asm/tm.h>
#endif
@@ -1471,7 +1472,6 @@ void program_check_exception(struct pt_regs *regs)
goto bail;
}
if (reason & REASON_TRAP) {
- unsigned long bugaddr;
/* Debugger is first in line to stop recursive faults in
* rcu_lock, notify_die, or atomic_notifier_call_chain */
if (debugger_bpt(regs))
@@ -1485,18 +1485,35 @@ void program_check_exception(struct pt_regs *regs)
== NOTIFY_STOP)
goto bail;
- bugaddr = regs->nip;
- /*
- * Fixup bugaddr for BUG_ON() in real mode
- */
- if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
- bugaddr += PAGE_OFFSET;
+ if (!(regs->msr & MSR_PR)) { /* not user-mode */
+ unsigned long bugaddr;
+ enum bug_trap_type t;
+
+ /*
+ * Fixup bugaddr for BUG_ON() in real mode
+ */
+ bugaddr = regs->nip;
+ if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
+ bugaddr += PAGE_OFFSET;
+ t = report_bug(bugaddr, regs);
+ if (t == BUG_TRAP_TYPE_WARN) {
+ regs->nip += 4;
+ goto bail;
+ }
+ if (t == BUG_TRAP_TYPE_BUG)
+ goto bug;
- if (!(regs->msr & MSR_PR) && /* not user-mode */
- report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
- regs->nip += 4;
- goto bail;
+ if (firmware_has_feature(FW_FEATURE_OPAL)) {
+ int64_t ret;
+
+ ret = opal_report_trap(regs->nip);
+ if (ret == OPAL_TRAP_WARN) {
+ regs->nip += 4;
+ goto bail;
+ }
+ }
}
+bug:
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
goto bail;
}
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 2233a58924cb..506b1798081a 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -295,3 +295,4 @@ OPAL_CALL(opal_secvar_get_next, OPAL_SECVAR_GET_NEXT);
OPAL_CALL(opal_secvar_enqueue_update, OPAL_SECVAR_ENQUEUE_UPDATE);
OPAL_CALL(opal_addr_to_sym, OPAL_ADDR_TO_SYM);
OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
+OPAL_CALL(opal_report_trap, OPAL_REPORT_TRAP);
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 04/10] powerpc/powernv: avoid polling in opal_get_chars
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (2 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 05/10] powerpc/powernv: Don't translate kernel addresses to real addresses for OPAL Nicholas Piggin
` (5 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
OPAL console IO should avoid locks and complexity where possible, to
maximise the chance of it working if there are crashes or bugs. This
poll is not necessary, opal_console_read can handle no input.
In a future patch, Linux will provide a console service to OPAL via the
OPAL console, so it must avoid using any other OPAL calls in this path.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/powernv/opal.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 1bf2e0b31ecf..e8eba210a92d 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -467,13 +467,10 @@ static int __init opal_message_init(struct device_node *opal_node)
int opal_get_chars(uint32_t vtermno, char *buf, int count)
{
s64 rc;
- __be64 evt, len;
+ __be64 len;
if (!opal.entry)
return -ENODEV;
- opal_poll_events(&evt);
- if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0)
- return 0;
len = cpu_to_be64(count);
rc = opal_console_read(vtermno, &len, buf);
if (rc == OPAL_SUCCESS)
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 05/10] powerpc/powernv: Don't translate kernel addresses to real addresses for OPAL
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (3 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 04/10] powerpc/powernv: avoid polling in opal_get_chars Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists Nicholas Piggin
` (4 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
A random assortment of OPAL callers use __pa() on pointers (others don't).
This is not required because __pa() behaves the same as __va() when
translation is off. In order to run OPAL with translation on, the
effective addresses have to be used.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/perf/imc-pmu.c | 4 ++--
arch/powerpc/platforms/powernv/npu-dma.c | 2 +-
arch/powerpc/platforms/powernv/opal-dump.c | 2 +-
arch/powerpc/platforms/powernv/opal-elog.c | 4 ++--
arch/powerpc/platforms/powernv/opal-flash.c | 6 +++---
arch/powerpc/platforms/powernv/opal-hmi.c | 2 +-
arch/powerpc/platforms/powernv/opal-nvram.c | 4 ++--
arch/powerpc/platforms/powernv/opal-powercap.c | 2 +-
arch/powerpc/platforms/powernv/opal-psr.c | 2 +-
arch/powerpc/platforms/powernv/opal-xscom.c | 2 +-
arch/powerpc/platforms/powernv/opal.c | 6 +++---
arch/powerpc/platforms/powernv/pci-ioda.c | 2 +-
arch/powerpc/sysdev/xive/native.c | 2 +-
drivers/char/powernv-op-panel.c | 3 +--
drivers/i2c/busses/i2c-opal.c | 12 ++++++------
drivers/mtd/devices/powernv_flash.c | 4 ++--
16 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index eb82dda884e5..332c7a3398f3 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -610,7 +610,7 @@ static int core_imc_mem_init(int cpu, int size)
mutex_init(&core_imc_refc[core_id].lock);
rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_CORE,
- __pa((void *)mem_info->vbase),
+ (u64)mem_info->vbase,
get_hard_smp_processor_id(cpu));
if (rc) {
free_pages((u64)mem_info->vbase, get_order(size));
@@ -1209,7 +1209,7 @@ static int trace_imc_mem_alloc(int cpu_id, int size)
per_cpu(trace_imc_mem, cpu_id) = local_mem;
/* Initialise the counters for trace mode */
- rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_TRACE, __pa((void *)local_mem),
+ rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_TRACE, (u64)local_mem,
get_hard_smp_processor_id(cpu_id));
if (rc) {
pr_info("IMC:opal init failed for trace imc\n");
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
index b95b9e3c4c98..9d38a30cc27e 100644
--- a/arch/powerpc/platforms/powernv/npu-dma.c
+++ b/arch/powerpc/platforms/powernv/npu-dma.c
@@ -149,7 +149,7 @@ static long pnv_npu_set_window(struct iommu_table_group *table_group, int num,
npe->pe_number,
npe->pe_number,
tbl->it_indirect_levels + 1,
- __pa(tbl->it_base),
+ __pa(tbl->it_base), /* XXX? */
size << 3,
IOMMU_PAGE_SIZE(tbl));
if (rc) {
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index 543c816fa99e..94d5fb716a32 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -256,7 +256,7 @@ static int64_t dump_read_data(struct dump_obj *dump)
}
/* First entry address */
- addr = __pa(list);
+ addr = (u64)list;
/* Fetch data */
rc = OPAL_BUSY_EVENT;
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
index 62ef7ad995da..6af5ff892195 100644
--- a/arch/powerpc/platforms/powernv/opal-elog.c
+++ b/arch/powerpc/platforms/powernv/opal-elog.c
@@ -163,7 +163,7 @@ static ssize_t raw_attr_read(struct file *filep, struct kobject *kobj,
if (!elog->buffer)
return -EIO;
- opal_rc = opal_read_elog(__pa(elog->buffer),
+ opal_rc = opal_read_elog((u64)elog->buffer,
elog->size, elog->id);
if (opal_rc != OPAL_SUCCESS) {
pr_err("ELOG: log read failed for log-id=%llx\n",
@@ -206,7 +206,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
elog->buffer = kzalloc(elog->size, GFP_KERNEL);
if (elog->buffer) {
- rc = opal_read_elog(__pa(elog->buffer),
+ rc = opal_read_elog((u64)elog->buffer,
elog->size, elog->id);
if (rc != OPAL_SUCCESS) {
pr_err("ELOG: log read failed for log-id=%llx\n",
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c
index 7e7d38b17420..46f02279d36a 100644
--- a/arch/powerpc/platforms/powernv/opal-flash.c
+++ b/arch/powerpc/platforms/powernv/opal-flash.c
@@ -130,11 +130,11 @@ static DEFINE_MUTEX(image_data_mutex);
static inline void opal_flash_validate(void)
{
long ret;
- void *buf = validate_flash_data.buf;
+ u64 buf = (u64)validate_flash_data.buf;
__be32 size = cpu_to_be32(validate_flash_data.buf_size);
__be32 result;
- ret = opal_validate_flash(__pa(buf), &size, &result);
+ ret = opal_validate_flash(buf, &size, &result);
validate_flash_data.status = ret;
validate_flash_data.buf_size = be32_to_cpu(size);
@@ -290,7 +290,7 @@ static int opal_flash_update(int op)
goto invalid_img;
/* First entry address */
- addr = __pa(list);
+ addr = (u64)list;
flash:
rc = opal_update_flash(addr);
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c
index 3e1f064a18db..7c51baeb62ff 100644
--- a/arch/powerpc/platforms/powernv/opal-hmi.c
+++ b/arch/powerpc/platforms/powernv/opal-hmi.c
@@ -298,7 +298,7 @@ static void hmi_event_handler(struct work_struct *work)
if (unrecoverable) {
/* Pull all HMI events from OPAL before we panic. */
- while (opal_get_msg(__pa(&msg), sizeof(msg)) == OPAL_SUCCESS) {
+ while (opal_get_msg((u64)&msg, sizeof(msg)) == OPAL_SUCCESS) {
u32 type;
type = be32_to_cpu(msg.msg_type);
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
index 380bc2d7ebbf..a7924dffee2b 100644
--- a/arch/powerpc/platforms/powernv/opal-nvram.c
+++ b/arch/powerpc/platforms/powernv/opal-nvram.c
@@ -33,7 +33,7 @@ static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
off = *index;
if ((off + count) > nvram_size)
count = nvram_size - off;
- rc = opal_read_nvram(__pa(buf), count, off);
+ rc = opal_read_nvram((unsigned long)buf, count, off);
if (rc != OPAL_SUCCESS)
return -EIO;
*index += count;
@@ -56,7 +56,7 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
count = nvram_size - off;
while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
- rc = opal_write_nvram(__pa(buf), count, off);
+ rc = opal_write_nvram((unsigned long)buf, count, off);
if (rc == OPAL_BUSY_EVENT) {
if (in_interrupt() || irqs_disabled())
mdelay(OPAL_BUSY_DELAY_MS);
diff --git a/arch/powerpc/platforms/powernv/opal-powercap.c b/arch/powerpc/platforms/powernv/opal-powercap.c
index c16d44f6f1d1..a1167ecf9e43 100644
--- a/arch/powerpc/platforms/powernv/opal-powercap.c
+++ b/arch/powerpc/platforms/powernv/opal-powercap.c
@@ -46,7 +46,7 @@ static ssize_t powercap_show(struct kobject *kobj, struct kobj_attribute *attr,
if (ret)
goto out_token;
- ret = opal_get_powercap(pcap_attr->handle, token, (u32 *)__pa(&pcap));
+ ret = opal_get_powercap(pcap_attr->handle, token, &pcap);
switch (ret) {
case OPAL_ASYNC_COMPLETION:
ret = opal_async_wait_response(token, &msg);
diff --git a/arch/powerpc/platforms/powernv/opal-psr.c b/arch/powerpc/platforms/powernv/opal-psr.c
index 69d7e75950d1..a3a68f53b1f8 100644
--- a/arch/powerpc/platforms/powernv/opal-psr.c
+++ b/arch/powerpc/platforms/powernv/opal-psr.c
@@ -40,7 +40,7 @@ static ssize_t psr_show(struct kobject *kobj, struct kobj_attribute *attr,
goto out_token;
ret = opal_get_power_shift_ratio(psr_attr->handle, token,
- (u32 *)__pa(&psr));
+ (u32 *)&psr);
switch (ret) {
case OPAL_ASYNC_COMPLETION:
ret = opal_async_wait_response(token, &msg);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
index fd510d961b8c..aef596997ad4 100644
--- a/arch/powerpc/platforms/powernv/opal-xscom.c
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -58,7 +58,7 @@ static int opal_scom_read(uint32_t chip, uint64_t addr, u64 reg, u64 *value)
__be64 v;
reg = opal_scom_unmangle(addr + reg);
- rc = opal_xscom_read(chip, reg, (__be64 *)__pa(&v));
+ rc = opal_xscom_read(chip, reg, &v);
if (rc) {
*value = 0xfffffffffffffffful;
return -EIO;
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index e8eba210a92d..a0e9808237b2 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -397,7 +397,7 @@ static void opal_handle_message(void)
s64 ret;
u32 type;
- ret = opal_get_msg(__pa(opal_msg), opal_msg_size);
+ ret = opal_get_msg((u64)opal_msg, opal_msg_size);
/* No opal message pending. */
if (ret == OPAL_RESOURCE)
return;
@@ -961,7 +961,7 @@ static void __init opal_dump_region_init(void)
return;
rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF,
- __pa(addr), size);
+ (u64)addr, size);
/* Don't warn if this is just an older OPAL that doesn't
* know about that call
*/
@@ -1197,7 +1197,7 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
sg->length = cpu_to_be64(
i * sizeof(struct opal_sg_entry) + 16);
i = 0;
- sg->next = cpu_to_be64(__pa(next));
+ sg->next = cpu_to_be64(next);
sg = next;
}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 57d3a6af1d52..dc6caec7cb46 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1844,7 +1844,7 @@ static int pnv_pci_ioda_dma_64bit_bypass(struct pnv_ioda_pe *pe)
/* reconfigure window 0 */
(pe->pe_number << 1) + 0,
1,
- __pa(tces),
+ __pa(tces), /* XXX? */
table_size,
1 << tce_order);
if (rc == OPAL_SUCCESS) {
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 5218fdc4b29a..a80960829bf0 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -647,7 +647,7 @@ static bool xive_native_provision_pages(void)
pr_err("Failed to allocate provisioning page\n");
return false;
}
- opal_xive_donate_page(chip, __pa(p));
+ opal_xive_donate_page(chip, (u64)p);
}
return true;
}
diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c
index 027484ecfb0d..e7569f5025ef 100644
--- a/drivers/char/powernv-op-panel.c
+++ b/drivers/char/powernv-op-panel.c
@@ -175,8 +175,7 @@ static int oppanel_probe(struct platform_device *pdev)
memset(oppanel_data, ' ', oppanel_size);
for (i = 0; i < num_lines; i++) {
oppanel_lines[i].line_len = cpu_to_be64(line_len);
- oppanel_lines[i].line = cpu_to_be64(__pa(&oppanel_data[i *
- line_len]));
+ oppanel_lines[i].line = cpu_to_be64(&oppanel_data[i * line_len]);
}
rc = misc_register(&oppanel_dev);
diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c
index 1c4c9bb06a0b..a2ea1e36d9aa 100644
--- a/drivers/i2c/busses/i2c-opal.c
+++ b/drivers/i2c/busses/i2c-opal.c
@@ -87,7 +87,7 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
req.addr = cpu_to_be16(msgs[0].addr);
req.size = cpu_to_be32(msgs[0].len);
- req.buffer_ra = cpu_to_be64(__pa(msgs[0].buf));
+ req.buffer_ra = cpu_to_be64(msgs[0].buf);
break;
case 2:
req.type = (msgs[1].flags & I2C_M_RD) ?
@@ -98,7 +98,7 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
req.subaddr = (req.subaddr << 8) | msgs[0].buf[i];
req.subaddr = cpu_to_be32(req.subaddr);
req.size = cpu_to_be32(msgs[1].len);
- req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
+ req.buffer_ra = cpu_to_be64(msgs[1].buf);
break;
}
@@ -123,7 +123,7 @@ static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
req.addr = cpu_to_be16(addr);
switch (size) {
case I2C_SMBUS_BYTE:
- req.buffer_ra = cpu_to_be64(__pa(&data->byte));
+ req.buffer_ra = cpu_to_be64(&data->byte);
req.size = cpu_to_be32(1);
/* Fall through */
case I2C_SMBUS_QUICK:
@@ -131,7 +131,7 @@ static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
break;
case I2C_SMBUS_BYTE_DATA:
- req.buffer_ra = cpu_to_be64(__pa(&data->byte));
+ req.buffer_ra = cpu_to_be64(&data->byte);
req.size = cpu_to_be32(1);
req.subaddr = cpu_to_be32(command);
req.subaddr_sz = 1;
@@ -143,7 +143,7 @@ static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
local[0] = data->word & 0xff;
local[1] = (data->word >> 8) & 0xff;
}
- req.buffer_ra = cpu_to_be64(__pa(local));
+ req.buffer_ra = cpu_to_be64(local);
req.size = cpu_to_be32(2);
req.subaddr = cpu_to_be32(command);
req.subaddr_sz = 1;
@@ -151,7 +151,7 @@ static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- req.buffer_ra = cpu_to_be64(__pa(&data->block[1]));
+ req.buffer_ra = cpu_to_be64(&data->block[1]);
req.size = cpu_to_be32(data->block[0]);
req.subaddr = cpu_to_be32(command);
req.subaddr_sz = 1;
diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c
index 0b757d9ba2f6..86dbaae8808f 100644
--- a/drivers/mtd/devices/powernv_flash.c
+++ b/drivers/mtd/devices/powernv_flash.c
@@ -66,10 +66,10 @@ static int powernv_flash_async_op(struct mtd_info *mtd, enum flash_op op,
switch (op) {
case FLASH_OP_READ:
- rc = opal_flash_read(info->id, offset, __pa(buf), len, token);
+ rc = opal_flash_read(info->id, offset, (u64)buf, len, token);
break;
case FLASH_OP_WRITE:
- rc = opal_flash_write(info->id, offset, __pa(buf), len, token);
+ rc = opal_flash_write(info->id, offset, (u64)buf, len, token);
break;
case FLASH_OP_ERASE:
rc = opal_flash_erase(info->id, offset, len, token);
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (4 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 05/10] powerpc/powernv: Don't translate kernel addresses to real addresses for OPAL Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 16:25 ` kbuild test robot
2020-05-06 7:02 ` Gautham R Shenoy
2020-05-02 11:19 ` [RFC PATCH 07/10] powerpc/powernv: Add OPAL_FIND_VM_AREA API Nicholas Piggin
` (3 subsequent siblings)
9 siblings, 2 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
OPAL may advertise new endian-specific entry point which has different
calling conventions including using the caller's stack, but otherwise
provides the standard OPAL call API without any changes required to
the OS.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/boot/opal.c | 5 +++
arch/powerpc/platforms/powernv/opal-call.c | 36 ++++++++++++++++++++++
arch/powerpc/platforms/powernv/opal.c | 30 +++++++++++-------
3 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c
index b69818ce592b..8b006a0282ac 100644
--- a/arch/powerpc/boot/opal.c
+++ b/arch/powerpc/boot/opal.c
@@ -13,6 +13,7 @@
struct opal {
u64 base;
u64 entry;
+ u64 v4_le_entry;
} opal;
static u32 opal_con_id;
@@ -75,6 +76,10 @@ static void opal_init(void)
if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0)
return;
opal.entry = be64_to_cpu(opal.entry);
+
+ if (getprop(opal_node, "opal-v4-le-entry-address", &opal.v4_le_entry, sizeof(u64)) < 0)
+ return;
+ opal.v4_le_entry = be64_to_cpu(opal.v4_le_entry);
}
int opal_console_init(void *devp, struct serial_console_data *scdp)
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 506b1798081a..32857254d268 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -92,6 +92,18 @@ static s64 __opal_call_trace(s64 a0, s64 a1, s64 a2, s64 a3,
#define DO_TRACE false
#endif /* CONFIG_TRACEPOINTS */
+struct opal {
+ u64 base;
+ u64 entry;
+ u64 size;
+ u64 v4_le_entry;
+};
+extern struct opal opal;
+
+typedef int64_t (*opal_v4_le_entry_fn)(uint64_t r3, uint64_t r4, uint64_t r5,
+ uint64_t r6, uint64_t r7, uint64_t r8,
+ uint64_t r9, uint64_t r10);
+
static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
int64_t a4, int64_t a5, int64_t a6, int64_t a7, int64_t opcode)
{
@@ -99,6 +111,30 @@ static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
unsigned long msr = mfmsr();
bool mmu = (msr & (MSR_IR|MSR_DR));
int64_t ret;
+ opal_v4_le_entry_fn fn;
+
+ if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
+ fn = (opal_v4_le_entry_fn)(opal.v4_le_entry);
+
+ if (fn) {
+ if (!mmu) {
+ BUG_ON(msr & MSR_EE);
+ ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
+ return ret;
+ }
+
+ local_irq_save(flags);
+ hard_irq_disable(); /* XXX r13 */
+ msr &= ~MSR_EE;
+ mtmsr(msr & ~(MSR_IR|MSR_DR));
+
+ ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
+
+ mtmsr(msr);
+ local_irq_restore(flags);
+
+ return ret;
+ }
msr &= ~MSR_EE;
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index a0e9808237b2..d00772d40680 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -46,13 +46,14 @@ static DEFINE_SPINLOCK(msg_list_lock);
static LIST_HEAD(msg_list);
/* /sys/firmware/opal */
-struct kobject *opal_kobj;
+struct kobject *opal_kobj __read_mostly;
struct opal {
u64 base;
u64 entry;
u64 size;
-} opal;
+ u64 v4_le_entry;
+} opal __read_mostly;
struct mcheck_recoverable_range {
u64 start_addr;
@@ -150,14 +151,15 @@ unsigned long arch_symbol_lookup_name(const char *name)
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
- const void *basep, *entryp, *sizep;
- int basesz, entrysz, runtimesz;
+ const void *basep, *entryp, *v4_le_entryp, *sizep;
+ int basesz, entrysz, v4_le_entrysz, runtimesz;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+ v4_le_entryp = of_get_flat_dt_prop(node, "opal-v4-le-entry-address", &v4_le_entrysz);
sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz);
if (!basep || !entryp || !sizep)
@@ -166,19 +168,25 @@ int __init early_init_dt_scan_opal(unsigned long node,
opal.base = of_read_number(basep, basesz/4);
opal.entry = of_read_number(entryp, entrysz/4);
opal.size = of_read_number(sizep, runtimesz/4);
+ opal.v4_le_entry = of_read_number(v4_le_entryp, v4_le_entrysz/4);
+
+ if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
+ powerpc_firmware_features |= FW_FEATURE_OPAL;
+ pr_debug("OPAL detected !\n");
+ } else {
+ panic("OPAL v3 compatible firmware not detected, can not continue.\n");
+ }
pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n",
opal.base, basep, basesz);
- pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%d)\n",
+ pr_debug("OPAL Entry = 0x%llx (entryp=%p entrysz=%d)\n",
opal.entry, entryp, entrysz);
- pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n",
+ pr_debug("OPAL Size = 0x%llx (sizep=%p runtimesz=%d)\n",
opal.size, sizep, runtimesz);
+ if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) && v4_le_entryp) {
- if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
- powerpc_firmware_features |= FW_FEATURE_OPAL;
- pr_debug("OPAL detected !\n");
- } else {
- panic("OPAL != V3 detected, no longer supported.\n");
+ pr_debug("OPAL v4 Entry = 0x%llx (v4_le_entryp=%p v4_le_entrysz=%d)\n",
+ opal.v4_le_entry, v4_le_entryp, v4_le_entrysz);
}
return 1;
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 07/10] powerpc/powernv: Add OPAL_FIND_VM_AREA API
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (5 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 08/10] powerpc/powernv: Set up an mm context to call OPAL in Nicholas Piggin
` (2 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This will be used in the next patch.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/opal-api.h | 15 ++++++++++++++-
arch/powerpc/include/asm/opal.h | 2 ++
arch/powerpc/platforms/powernv/opal-call.c | 1 +
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 018d4734c323..0be5ff4e51b5 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -217,7 +217,8 @@
#define OPAL_ADDR_TO_SYM 181
#define OPAL_SYM_TO_ADDR 182
#define OPAL_REPORT_TRAP 183
-#define OPAL_LAST 183
+#define OPAL_FIND_VM_AREA 184
+#define OPAL_LAST 184
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1189,6 +1190,18 @@ struct opal_mpipl_fadump {
#define OPAL_TRAP_WARN 2
#define OPAL_TRAP_PANIC 3
+#define OS_VM_FLAG_READ 0x1
+#define OS_VM_FLAG_WRITE 0x2
+#define OS_VM_FLAG_EXECUTE 0x4
+#define OS_VM_FLAG_CI 0x8
+
+struct opal_vm_area {
+ __be64 address;
+ __be64 length;
+ __be64 pa;
+ __be64 vm_flags;
+};
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index dc77c2d5e036..199b5582b700 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -405,6 +405,8 @@ void opal_powercap_init(void);
void opal_psr_init(void);
void opal_sensor_groups_init(void);
+int64_t opal_find_vm_area(uint64_t addr, struct opal_vm_area *opal_vm_area);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 32857254d268..e62a74dfb3d0 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -332,3 +332,4 @@ OPAL_CALL(opal_secvar_enqueue_update, OPAL_SECVAR_ENQUEUE_UPDATE);
OPAL_CALL(opal_addr_to_sym, OPAL_ADDR_TO_SYM);
OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
OPAL_CALL(opal_report_trap, OPAL_REPORT_TRAP);
+OPAL_CALL(opal_find_vm_area, OPAL_FIND_VM_AREA);
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 08/10] powerpc/powernv: Set up an mm context to call OPAL in
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (6 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 07/10] powerpc/powernv: Add OPAL_FIND_VM_AREA API Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 09/10] powerpc/powernv: OPAL V4 OS services Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 10/10] powerpc/powernv: OPAL V4 Implement vm_map/unmap service Nicholas Piggin
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This creates an mm context to be used for OPAL V4 calls, which
is populated with ptes according to querying OPAL_FIND_VM_AREA.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/powernv/opal-call.c | 21 +++-
arch/powerpc/platforms/powernv/opal.c | 119 ++++++++++++++++++++-
2 files changed, 137 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index e62a74dfb3d0..4bdad3d2fa18 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -104,6 +104,9 @@ typedef int64_t (*opal_v4_le_entry_fn)(uint64_t r3, uint64_t r4, uint64_t r5,
uint64_t r6, uint64_t r7, uint64_t r8,
uint64_t r9, uint64_t r10);
+extern struct mm_struct *opal_mm;
+extern bool opal_mm_enabled;
+
static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
int64_t a4, int64_t a5, int64_t a6, int64_t a7, int64_t opcode)
{
@@ -117,6 +120,8 @@ static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
fn = (opal_v4_le_entry_fn)(opal.v4_le_entry);
if (fn) {
+ struct mm_struct *old_mm = current->active_mm;
+
if (!mmu) {
BUG_ON(msr & MSR_EE);
ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
@@ -126,11 +131,23 @@ static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
local_irq_save(flags);
hard_irq_disable(); /* XXX r13 */
msr &= ~MSR_EE;
- mtmsr(msr & ~(MSR_IR|MSR_DR));
+ if (!opal_mm_enabled)
+ mtmsr(msr & ~(MSR_IR|MSR_DR));
+
+ if (opal_mm_enabled && old_mm != opal_mm) {
+ current->active_mm = opal_mm;
+ switch_mm_irqs_off(NULL, opal_mm, current);
+ }
ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
- mtmsr(msr);
+ if (opal_mm_enabled && old_mm != opal_mm) {
+ current->active_mm = old_mm;
+ switch_mm_irqs_off(NULL, old_mm, current);
+ }
+
+ if (!opal_mm_enabled)
+ mtmsr(msr);
local_irq_restore(flags);
return ret;
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index d00772d40680..98d6d7fc5411 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -45,6 +45,10 @@ struct opal_msg_node {
static DEFINE_SPINLOCK(msg_list_lock);
static LIST_HEAD(msg_list);
+struct mm_struct *opal_mm __read_mostly;
+bool opal_v4_present __read_mostly;
+bool opal_mm_enabled __read_mostly;
+
/* /sys/firmware/opal */
struct kobject *opal_kobj __read_mostly;
@@ -172,7 +176,12 @@ int __init early_init_dt_scan_opal(unsigned long node,
if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
powerpc_firmware_features |= FW_FEATURE_OPAL;
- pr_debug("OPAL detected !\n");
+ if (of_flat_dt_is_compatible(node, "ibm,opal-v4")) {
+ opal_v4_present = true;
+ pr_debug("OPAL v4 runtime firmware\n");
+ } else {
+ pr_debug("OPAL detected !\n");
+ }
} else {
panic("OPAL v3 compatible firmware not detected, can not continue.\n");
}
@@ -187,6 +196,9 @@ int __init early_init_dt_scan_opal(unsigned long node,
pr_debug("OPAL v4 Entry = 0x%llx (v4_le_entryp=%p v4_le_entrysz=%d)\n",
opal.v4_le_entry, v4_le_entryp, v4_le_entrysz);
+ } else {
+ /* Can't use v4 entry */
+ opal_v4_present = false;
}
return 1;
@@ -1033,6 +1045,111 @@ static void opal_init_heartbeat(void)
kopald_tsk = kthread_run(kopald, NULL, "kopald");
}
+static pgprot_t opal_vm_flags_to_prot(uint64_t flags)
+{
+ pgprot_t prot;
+
+ BUG_ON(!flags);
+ if (flags & OS_VM_FLAG_EXECUTE) {
+ if (flags & OS_VM_FLAG_CI)
+ BUG();
+ if (flags & OS_VM_FLAG_WRITE)
+ prot = PAGE_KERNEL_X;
+ else
+ prot = PAGE_KERNEL_X /* XXX!? PAGE_KERNEL_ROX */;
+ } else {
+ if (flags & OS_VM_FLAG_WRITE)
+ prot = PAGE_KERNEL;
+ else if (flags & OS_VM_FLAG_READ)
+ prot = PAGE_KERNEL_RO;
+ else
+ BUG();
+ if (flags & OS_VM_FLAG_CI)
+ prot = pgprot_noncached(prot);
+ }
+ return prot;
+}
+
+static int __init opal_init_mm(void)
+{
+ struct mm_struct *mm;
+ unsigned long addr;
+ struct opal_vm_area vm_area;
+
+ mm = copy_init_mm();
+ if (!mm)
+ return -ENOMEM;
+
+ /* Set up initial mappings for OPAL. */
+ addr = 0;
+ while (opal_find_vm_area(addr, &vm_area) == OPAL_SUCCESS) {
+ unsigned long length;
+ unsigned long pa;
+ unsigned long flags;
+ unsigned long end;
+ pgprot_t prot;
+
+ addr = be64_to_cpu(vm_area.address);
+ length = be64_to_cpu(vm_area.length);
+ pa = be64_to_cpu(vm_area.pa);
+ flags = be64_to_cpu(vm_area.vm_flags);
+
+ if (flags == 0) {
+ /* flags == 0 is a special case */
+ BUG_ON(pa != 0);
+ } else {
+ /* Don't support non-linear (yet?) */
+ BUG_ON(addr != pa);
+ prot = opal_vm_flags_to_prot(flags);
+ }
+
+ /* Align to PAGE_SIZE */
+ end = (addr + length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ addr &= ~(PAGE_SIZE - 1);
+
+ while (addr < end) {
+ spinlock_t *ptl;
+ pte_t pte, *ptep;
+
+ ptep = get_locked_pte(mm, addr, &ptl);
+ if (flags) {
+ pte = pfn_pte(addr >> PAGE_SHIFT, prot);
+ set_pte_at(mm, addr, ptep, pte);
+ } else {
+ pte_clear(mm, addr, ptep);
+ }
+ pte_unmap_unlock(ptep, ptl);
+
+ addr += PAGE_SIZE;
+ }
+ }
+
+ printk("OPAL Virtual Memory Runtime Enabled, using PID=0x%04x\n", (unsigned int)mm->context.id);
+
+ opal_mm = mm;
+ opal_mm_enabled = true;
+
+ return 0;
+}
+
+static int __init opal_init_early(void)
+{
+ int rc;
+
+ if (opal_v4_present) {
+ if (radix_enabled()) {
+ /* Hash can't resolve SLB faults to the switched mm */
+ rc = opal_init_mm();
+ if (rc) {
+ pr_warn("OPAL virtual memory init failed, firmware will run in real-mode.\n");
+ }
+ }
+ }
+
+ return 0;
+}
+machine_early_initcall(powernv, opal_init_early);
+
static int __init opal_init(void)
{
struct device_node *np, *consoles, *leds;
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 09/10] powerpc/powernv: OPAL V4 OS services
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (7 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 08/10] powerpc/powernv: Set up an mm context to call OPAL in Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 10/10] powerpc/powernv: OPAL V4 Implement vm_map/unmap service Nicholas Piggin
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This implements OPAL_REGISTER_OS_OPS and implements the printf
service.
When this API is called, OPAL switches to V4 mode which requires
the OS to subsequently handle its program interrupts and printf
calls.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/opal-api.h | 7 ++++-
arch/powerpc/include/asm/opal.h | 1 +
arch/powerpc/platforms/powernv/opal-call.c | 1 +
arch/powerpc/platforms/powernv/opal.c | 36 ++++++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 0be5ff4e51b5..1b2f176677fc 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -218,7 +218,8 @@
#define OPAL_SYM_TO_ADDR 182
#define OPAL_REPORT_TRAP 183
#define OPAL_FIND_VM_AREA 184
-#define OPAL_LAST 184
+#define OPAL_REGISTER_OS_OPS 185
+#define OPAL_LAST 185
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1202,6 +1203,10 @@ struct opal_vm_area {
__be64 vm_flags;
};
+struct opal_os_ops {
+ __be64 os_printf; /* void printf(int32_t level, const char *str) */
+};
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 199b5582b700..09985b7718b3 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -406,6 +406,7 @@ void opal_psr_init(void);
void opal_sensor_groups_init(void);
int64_t opal_find_vm_area(uint64_t addr, struct opal_vm_area *opal_vm_area);
+int64_t opal_register_os_ops(struct opal_os_ops *ops, uint64_t size);
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 4bdad3d2fa18..11f419e76059 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -350,3 +350,4 @@ OPAL_CALL(opal_addr_to_sym, OPAL_ADDR_TO_SYM);
OPAL_CALL(opal_sym_to_addr, OPAL_SYM_TO_ADDR);
OPAL_CALL(opal_report_trap, OPAL_REPORT_TRAP);
OPAL_CALL(opal_find_vm_area, OPAL_FIND_VM_AREA);
+OPAL_CALL(opal_register_os_ops, OPAL_REGISTER_OS_OPS);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 98d6d7fc5411..0fbfcd088c58 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -47,6 +47,7 @@ static LIST_HEAD(msg_list);
struct mm_struct *opal_mm __read_mostly;
bool opal_v4_present __read_mostly;
+bool opal_v4_enabled __read_mostly;
bool opal_mm_enabled __read_mostly;
/* /sys/firmware/opal */
@@ -152,6 +153,8 @@ unsigned long arch_symbol_lookup_name(const char *name)
return be64_to_cpu(addr);
}
+static void os_printf(int32_t level, const char *str);
+
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
@@ -1045,6 +1048,28 @@ static void opal_init_heartbeat(void)
kopald_tsk = kthread_run(kopald, NULL, "kopald");
}
+static void os_printf(int32_t level, const char *str)
+{
+ const char *l;
+
+ /* Assuming printk does not work in real mode */
+ if (WARN_ON_ONCE(!(mfmsr() & (MSR_IR|MSR_DR))))
+ return;
+
+ switch (level) {
+ case 0: l = KERN_EMERG; break;
+ case 1: l = KERN_ALERT; break;
+ case 2: l = KERN_CRIT; break;
+ case 3: l = KERN_ERR; break;
+ case 4: l = KERN_WARNING; break;
+ case 5: l = KERN_NOTICE; break;
+ case 6: l = KERN_INFO; break;
+ case 7: l = KERN_DEBUG; break;
+ default: l = KERN_ERR;
+ }
+ printk("%s[OPAL] %s", l, str);
+}
+
static pgprot_t opal_vm_flags_to_prot(uint64_t flags)
{
pgprot_t prot;
@@ -1137,6 +1162,8 @@ static int __init opal_init_early(void)
int rc;
if (opal_v4_present) {
+ struct opal_os_ops opal_os_ops;
+
if (radix_enabled()) {
/* Hash can't resolve SLB faults to the switched mm */
rc = opal_init_mm();
@@ -1144,6 +1171,15 @@ static int __init opal_init_early(void)
pr_warn("OPAL virtual memory init failed, firmware will run in real-mode.\n");
}
}
+
+ memset(&opal_os_ops, 0, sizeof(opal_os_ops));
+ opal_os_ops.os_printf = cpu_to_be64(&os_printf);
+ if (opal_register_os_ops(&opal_os_ops, sizeof(opal_os_ops))) {
+ pr_warn("OPAL register OS ops failed, firmware will run in v3 mode.\n");
+ } else {
+ opal_v4_enabled = true;
+ pr_warn("OPAL running in v4 mode!\n");
+ }
}
return 0;
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 10/10] powerpc/powernv: OPAL V4 Implement vm_map/unmap service
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
` (8 preceding siblings ...)
2020-05-02 11:19 ` [RFC PATCH 09/10] powerpc/powernv: OPAL V4 OS services Nicholas Piggin
@ 2020-05-02 11:19 ` Nicholas Piggin
9 siblings, 0 replies; 14+ messages in thread
From: Nicholas Piggin @ 2020-05-02 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This implements os_vm_map, os_vm_unmap. OPAL uses EA regions that
is specifies in OPAL_FIND_VM_AREA for these mappings, so provided
the page tables are allocated at init-time and not freed, these
services can be provided without memory allocation / blocking.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/opal-api.h | 2 +
arch/powerpc/platforms/powernv/opal.c | 57 +++++++++++++++++++++++++++
2 files changed, 59 insertions(+)
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 1b2f176677fc..97c5e5423827 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -1205,6 +1205,8 @@ struct opal_vm_area {
struct opal_os_ops {
__be64 os_printf; /* void printf(int32_t level, const char *str) */
+ __be64 os_vm_map; /* int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags) */
+ __be64 os_vm_unmap; /* void os_vm_unmap(uint64_t ea) */
};
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 0fbfcd088c58..93b9afaf33b3 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -1095,6 +1095,61 @@ static pgprot_t opal_vm_flags_to_prot(uint64_t flags)
return prot;
}
+static int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags)
+{
+ struct mm_struct *mm = opal_mm;
+ spinlock_t *ptl;
+ pte_t pte, *ptep;
+ pgprot_t prot;
+
+ if (WARN_ON_ONCE(!opal_mm_enabled))
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(!(mfmsr() & (MSR_IR|MSR_DR))))
+ return -EINVAL;
+
+ /* mm should be active_mm if MMU is on here */
+
+// printk("os_vm_map 0x%llx->0x%llx flags=0x%llx\n", ea, pa, flags);
+
+ prot = opal_vm_flags_to_prot(flags);
+
+ pte = pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL_X);
+
+ ptep = get_locked_pte(mm, ea, &ptl);
+ set_pte_at(mm, ea, ptep, pte);
+ pte_unmap_unlock(ptep, ptl);
+
+ return 0;
+}
+
+static void os_vm_unmap(uint64_t ea)
+{
+ struct mm_struct *mm = opal_mm;
+ spinlock_t *ptl;
+ pte_t *ptep;
+
+ if (WARN_ON_ONCE(!opal_mm_enabled))
+ return;
+
+ if (WARN_ON_ONCE(!(mfmsr() & (MSR_IR|MSR_DR))))
+ return;
+
+// printk("os_vm_unmap 0x%llx\n", ea);
+
+ /* mm should be active_mm if MMU is on here */
+
+ ptep = get_locked_pte(mm, ea, &ptl);
+ pte_clear(mm, ea, ptep);
+ pte_unmap_unlock(ptep, ptl);
+
+ /*
+ * This leaves potential TLBs in other CPUs for this EA, but it is
+ * only used by this CPU. Can't do a broadcast flush here, no IPIs.
+ */
+ local_flush_tlb_mm(mm);
+}
+
static int __init opal_init_mm(void)
{
struct mm_struct *mm;
@@ -1174,6 +1229,8 @@ static int __init opal_init_early(void)
memset(&opal_os_ops, 0, sizeof(opal_os_ops));
opal_os_ops.os_printf = cpu_to_be64(&os_printf);
+ opal_os_ops.os_vm_map = cpu_to_be64(&os_vm_map);
+ opal_os_ops.os_vm_unmap = cpu_to_be64(&os_vm_unmap);
if (opal_register_os_ops(&opal_os_ops, sizeof(opal_os_ops))) {
pr_warn("OPAL register OS ops failed, firmware will run in v3 mode.\n");
} else {
--
2.23.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL
2020-05-02 11:19 ` [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL Nicholas Piggin
@ 2020-05-02 14:30 ` kbuild test robot
0 siblings, 0 replies; 14+ messages in thread
From: kbuild test robot @ 2020-05-02 14:30 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 7083 bytes --]
Hi Nicholas,
[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on powerpc/next]
[also build test ERROR on linus/master scottwood/next v5.7-rc3]
[cannot apply to next-20200501]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/OPAL-V4/20200502-195816
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-mpc866_ads_defconfig (attached as .config)
compiler: powerpc-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/kernel/traps.c: In function 'program_check_exception':
>> arch/powerpc/kernel/traps.c:1509:11: error: implicit declaration of function 'opal_report_trap' [-Werror=implicit-function-declaration]
1509 | ret = opal_report_trap(regs->nip);
| ^~~~~~~~~~~~~~~~
>> arch/powerpc/kernel/traps.c:1510:16: error: 'OPAL_TRAP_WARN' undeclared (first use in this function)
1510 | if (ret == OPAL_TRAP_WARN) {
| ^~~~~~~~~~~~~~
arch/powerpc/kernel/traps.c:1510:16: note: each undeclared identifier is reported only once for each function it appears in
cc1: all warnings being treated as errors
vim +/opal_report_trap +1509 arch/powerpc/kernel/traps.c
1460
1461 void program_check_exception(struct pt_regs *regs)
1462 {
1463 enum ctx_state prev_state = exception_enter();
1464 unsigned int reason = get_reason(regs);
1465
1466 /* We can now get here via a FP Unavailable exception if the core
1467 * has no FPU, in that case the reason flags will be 0 */
1468
1469 if (reason & REASON_FP) {
1470 /* IEEE FP exception */
1471 parse_fpe(regs);
1472 goto bail;
1473 }
1474 if (reason & REASON_TRAP) {
1475 /* Debugger is first in line to stop recursive faults in
1476 * rcu_lock, notify_die, or atomic_notifier_call_chain */
1477 if (debugger_bpt(regs))
1478 goto bail;
1479
1480 if (kprobe_handler(regs))
1481 goto bail;
1482
1483 /* trap exception */
1484 if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
1485 == NOTIFY_STOP)
1486 goto bail;
1487
1488 if (!(regs->msr & MSR_PR)) { /* not user-mode */
1489 unsigned long bugaddr;
1490 enum bug_trap_type t;
1491
1492 /*
1493 * Fixup bugaddr for BUG_ON() in real mode
1494 */
1495 bugaddr = regs->nip;
1496 if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
1497 bugaddr += PAGE_OFFSET;
1498 t = report_bug(bugaddr, regs);
1499 if (t == BUG_TRAP_TYPE_WARN) {
1500 regs->nip += 4;
1501 goto bail;
1502 }
1503 if (t == BUG_TRAP_TYPE_BUG)
1504 goto bug;
1505
1506 if (firmware_has_feature(FW_FEATURE_OPAL)) {
1507 int64_t ret;
1508
> 1509 ret = opal_report_trap(regs->nip);
> 1510 if (ret == OPAL_TRAP_WARN) {
1511 regs->nip += 4;
1512 goto bail;
1513 }
1514 }
1515 }
1516 bug:
1517 _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
1518 goto bail;
1519 }
1520 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1521 if (reason & REASON_TM) {
1522 /* This is a TM "Bad Thing Exception" program check.
1523 * This occurs when:
1524 * - An rfid/hrfid/mtmsrd attempts to cause an illegal
1525 * transition in TM states.
1526 * - A trechkpt is attempted when transactional.
1527 * - A treclaim is attempted when non transactional.
1528 * - A tend is illegally attempted.
1529 * - writing a TM SPR when transactional.
1530 *
1531 * If usermode caused this, it's done something illegal and
1532 * gets a SIGILL slap on the wrist. We call it an illegal
1533 * operand to distinguish from the instruction just being bad
1534 * (e.g. executing a 'tend' on a CPU without TM!); it's an
1535 * illegal /placement/ of a valid instruction.
1536 */
1537 if (user_mode(regs)) {
1538 _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
1539 goto bail;
1540 } else {
1541 printk(KERN_EMERG "Unexpected TM Bad Thing exception "
1542 "at %lx (msr 0x%lx) tm_scratch=%llx\n",
1543 regs->nip, regs->msr, get_paca()->tm_scratch);
1544 die("Unrecoverable exception", regs, SIGABRT);
1545 }
1546 }
1547 #endif
1548
1549 /*
1550 * If we took the program check in the kernel skip down to sending a
1551 * SIGILL. The subsequent cases all relate to emulating instructions
1552 * which we should only do for userspace. We also do not want to enable
1553 * interrupts for kernel faults because that might lead to further
1554 * faults, and loose the context of the original exception.
1555 */
1556 if (!user_mode(regs))
1557 goto sigill;
1558
1559 /* We restore the interrupt state now */
1560 if (!arch_irq_disabled_regs(regs))
1561 local_irq_enable();
1562
1563 /* (reason & REASON_ILLEGAL) would be the obvious thing here,
1564 * but there seems to be a hardware bug on the 405GP (RevD)
1565 * that means ESR is sometimes set incorrectly - either to
1566 * ESR_DST (!?) or 0. In the process of chasing this with the
1567 * hardware people - not sure if it can happen on any illegal
1568 * instruction or only on FP instructions, whether there is a
1569 * pattern to occurrences etc. -dgibson 31/Mar/2003
1570 */
1571 if (!emulate_math(regs))
1572 goto bail;
1573
1574 /* Try to emulate it if we should. */
1575 if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
1576 switch (emulate_instruction(regs)) {
1577 case 0:
1578 regs->nip += 4;
1579 emulate_single_step(regs);
1580 goto bail;
1581 case -EFAULT:
1582 _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
1583 goto bail;
1584 }
1585 }
1586
1587 sigill:
1588 if (reason & REASON_PRIVILEGED)
1589 _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
1590 else
1591 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1592
1593 bail:
1594 exception_exit(prev_state);
1595 }
1596 NOKPROBE_SYMBOL(program_check_exception);
1597
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 12140 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists
2020-05-02 11:19 ` [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists Nicholas Piggin
@ 2020-05-02 16:25 ` kbuild test robot
2020-05-06 7:02 ` Gautham R Shenoy
1 sibling, 0 replies; 14+ messages in thread
From: kbuild test robot @ 2020-05-02 16:25 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 3330 bytes --]
Hi Nicholas,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on powerpc/next]
[also build test WARNING on linus/master scottwood/next v5.7-rc3]
[cannot apply to next-20200501]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/OPAL-V4/20200502-195816
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
arch/powerpc/platforms/powernv/opal-call.c: In function 'opal_call':
>> arch/powerpc/platforms/powernv/opal-call.c:119:5: warning: 'fn' is used uninitialized in this function [-Wuninitialized]
119 | if (fn) {
| ^
vim +/fn +119 arch/powerpc/platforms/powernv/opal-call.c
102
103 typedef int64_t (*opal_v4_le_entry_fn)(uint64_t r3, uint64_t r4, uint64_t r5,
104 uint64_t r6, uint64_t r7, uint64_t r8,
105 uint64_t r9, uint64_t r10);
106
107 static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
108 int64_t a4, int64_t a5, int64_t a6, int64_t a7, int64_t opcode)
109 {
110 unsigned long flags;
111 unsigned long msr = mfmsr();
112 bool mmu = (msr & (MSR_IR|MSR_DR));
113 int64_t ret;
114 opal_v4_le_entry_fn fn;
115
116 if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
117 fn = (opal_v4_le_entry_fn)(opal.v4_le_entry);
118
> 119 if (fn) {
120 if (!mmu) {
121 BUG_ON(msr & MSR_EE);
122 ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
123 return ret;
124 }
125
126 local_irq_save(flags);
127 hard_irq_disable(); /* XXX r13 */
128 msr &= ~MSR_EE;
129 mtmsr(msr & ~(MSR_IR|MSR_DR));
130
131 ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
132
133 mtmsr(msr);
134 local_irq_restore(flags);
135
136 return ret;
137 }
138
139 msr &= ~MSR_EE;
140
141 if (unlikely(!mmu))
142 return __opal_call(a0, a1, a2, a3, a4, a5, a6, a7, opcode, msr);
143
144 local_save_flags(flags);
145 hard_irq_disable();
146
147 if (DO_TRACE) {
148 ret = __opal_call_trace(a0, a1, a2, a3, a4, a5, a6, a7, opcode, msr);
149 } else {
150 ret = __opal_call(a0, a1, a2, a3, a4, a5, a6, a7, opcode, msr);
151 }
152
153 local_irq_restore(flags);
154
155 return ret;
156 }
157
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 66093 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists
2020-05-02 11:19 ` [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists Nicholas Piggin
2020-05-02 16:25 ` kbuild test robot
@ 2020-05-06 7:02 ` Gautham R Shenoy
1 sibling, 0 replies; 14+ messages in thread
From: Gautham R Shenoy @ 2020-05-06 7:02 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: linuxppc-dev
Hello Nicholas,
On Sat, May 02, 2020 at 09:19:10PM +1000, Nicholas Piggin wrote:
> OPAL may advertise new endian-specific entry point which has different
> calling conventions including using the caller's stack, but otherwise
> provides the standard OPAL call API without any changes required to
> the OS.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
[..snip..]
> index 506b1798081a..32857254d268 100644
> --- a/arch/powerpc/platforms/powernv/opal-call.c
> +++ b/arch/powerpc/platforms/powernv/opal-call.c
> @@ -92,6 +92,18 @@ static s64 __opal_call_trace(s64 a0, s64 a1, s64 a2, s64 a3,
> #define DO_TRACE false
> #endif /* CONFIG_TRACEPOINTS */
>
> +struct opal {
> + u64 base;
> + u64 entry;
> + u64 size;
> + u64 v4_le_entry;
> +};
> +extern struct opal opal;
> +
> +typedef int64_t (*opal_v4_le_entry_fn)(uint64_t r3, uint64_t r4, uint64_t r5,
> + uint64_t r6, uint64_t r7, uint64_t r8,
> + uint64_t r9, uint64_t r10);
> +
> static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
> int64_t a4, int64_t a5, int64_t a6, int64_t a7, int64_t opcode)
> {
> @@ -99,6 +111,30 @@ static int64_t opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
> unsigned long msr = mfmsr();
> bool mmu = (msr & (MSR_IR|MSR_DR));
> int64_t ret;
> + opal_v4_le_entry_fn fn;
fn should be initialized to NULL here to ensure correctness when
kernel is built with CONFIG_CPU_BIG_ENDIAN.
> +
> + if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
> + fn = (opal_v4_le_entry_fn)(opal.v4_le_entry);
> +
> + if (fn) {
> + if (!mmu) {
> + BUG_ON(msr & MSR_EE);
> + ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
> + return ret;
> + }
> +
> + local_irq_save(flags);
> + hard_irq_disable(); /* XXX r13 */
> + msr &= ~MSR_EE;
> + mtmsr(msr & ~(MSR_IR|MSR_DR));
> +
> + ret = fn(opcode, a0, a1, a2, a3, a4, a5, a6);
> +
> + mtmsr(msr);
> + local_irq_restore(flags);
> +
> + return ret;
> + }
>
> msr &= ~MSR_EE;
>
--
Thanks and Regards
gautham.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2020-05-06 7:03 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-02 11:19 [RFC PATCH 00/10] OPAL V4 Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 01/10] kallsyms: architecture specific symbol lookups Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 02/10] powerpc/powernv: Wire up OPAL address lookups Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 03/10] powerpc/powernv: Use OPAL_REPORT_TRAP to cope with trap interrupts from OPAL Nicholas Piggin
2020-05-02 14:30 ` kbuild test robot
2020-05-02 11:19 ` [RFC PATCH 04/10] powerpc/powernv: avoid polling in opal_get_chars Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 05/10] powerpc/powernv: Don't translate kernel addresses to real addresses for OPAL Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 06/10] powerpc/powernv: opal use new opal call entry point if it exists Nicholas Piggin
2020-05-02 16:25 ` kbuild test robot
2020-05-06 7:02 ` Gautham R Shenoy
2020-05-02 11:19 ` [RFC PATCH 07/10] powerpc/powernv: Add OPAL_FIND_VM_AREA API Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 08/10] powerpc/powernv: Set up an mm context to call OPAL in Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 09/10] powerpc/powernv: OPAL V4 OS services Nicholas Piggin
2020-05-02 11:19 ` [RFC PATCH 10/10] powerpc/powernv: OPAL V4 Implement vm_map/unmap service Nicholas Piggin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.