diff mbox series

[RFC,7/8] xscoms: read/write xscoms using ucall

Message ID 20190905132919.8765-8-grimm@linux.ibm.com
State Superseded
Headers show
Series PEF support in Skiboot | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch warning Failed to apply on branch master (7b12d5489fcfd73ef7ec0cb27eff7f8a5f13b238)
snowpatch_ozlabs/apply_patch fail Failed to apply to any branch

Commit Message

Ryan Grimm Sept. 5, 2019, 1:29 p.m. UTC
From: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>

xscom registers are in the secure memory area when secure mode is
enabled. These registers cannot be accessed directly and need to use
ultravisor services using ultracall.

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
[ linuxram: Set uv_present just after starting UV ]
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
---
 hw/ultravisor.c      |  8 ++++++++
 include/ultravisor.h | 28 ++++++++++++++++++++++++++++
 include/xscom.h      | 11 +++++++++--
 3 files changed, 45 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/hw/ultravisor.c b/hw/ultravisor.c
index e73540a9..9384b44f 100644
--- a/hw/ultravisor.c
+++ b/hw/ultravisor.c
@@ -29,6 +29,7 @@ 
 #include <ultravisor-api.h>
 #include <libfdt/libfdt.h>
 
+bool uv_present = false;
 static char *uv_image = NULL;
 static size_t uv_image_size;
 struct xz_decompress *uv_xz = NULL;
@@ -176,6 +177,7 @@  static void cpu_start_ultravisor(void *data)
 
 int start_ultravisor(void)
 {
+	struct proc_chip *chip = get_chip(this_cpu()->chip_id);
 	struct cpu_thread *cpu;
 	struct cpu_job **jobs;
 	int i=0;
@@ -195,6 +197,12 @@  int start_ultravisor(void)
 
 	cpu_start_ultravisor((void *)uv_opal);
 
+	/*
+	 * From now on XSCOM must go through Ultravisor via ucall, indicate that
+	 */
+	if (chip->xscom_base & UV_ACCESS_BIT)
+		uv_present = true;
+
 	/* wait for everyone to sync back */
 	while (i > 0) {
 		cpu_wait_job(jobs[--i], true);
diff --git a/include/ultravisor.h b/include/ultravisor.h
index 3fc2ecd9..ee339406 100644
--- a/include/ultravisor.h
+++ b/include/ultravisor.h
@@ -23,6 +23,9 @@ 
  * for the secure virtual machines */
 #define UV_SECURE_MEM_BIT              (PPC_BIT(15))
 #define MAX_COMPRESSED_UV_IMAGE_SIZE 0x40000 /* 256 Kilobytes */
+#define UV_READ_SCOM  0xF114
+#define UV_WRITE_SCOM 0xF118
+#define UCALL_BUFSIZE 4
 #define UV_ACCESS_BIT		0x1ULL << 48
 /* Address at which the Ultravisor is loaded for BML and Mambo */
 #define UV_LOAD_BASE		0xC0000000
@@ -30,6 +33,9 @@ 
 #define UV_FDT_MAX_SIZE		0x100000
 #define UV_HB_RESERVE_SIZE	0x4000000;
 
+extern bool uv_present;
+#define is_uv_present() uv_present
+
 extern int start_uv(uint64_t entry, struct uv_opal *uv_opal);
 extern bool uv_add_mem_range(__be64 start, __be64 end);
 extern void uv_preload_image(void);
@@ -38,4 +44,26 @@  extern void init_uv(void);
 extern int start_ultravisor(void);
 extern long ucall(unsigned long opcode, unsigned long *retbuf, ...);
 
+static inline bool can_access_xscom(void)
+{
+	return (is_msr_bit_set(MSR_S) || !is_uv_present());
+}
+
+static inline int uv_xscom_read(u64 partid, u64 pcb_addr, u64 *val)
+{
+	long rc;
+	unsigned long retbuf[UCALL_BUFSIZE];
+
+	rc = ucall(UV_READ_SCOM, retbuf, partid, pcb_addr);
+	*val = retbuf[0];
+	return rc;
+}
+
+static inline int uv_xscom_write(u64 partid, u64 pcb_addr, u64 val)
+{
+	unsigned long retbuf[UCALL_BUFSIZE];
+
+	return ucall(UV_WRITE_SCOM, retbuf, partid, pcb_addr, val);
+}
+
 #endif /* __ULTRAVISOR_H */
diff --git a/include/xscom.h b/include/xscom.h
index 1f89ba9b..595161c5 100644
--- a/include/xscom.h
+++ b/include/xscom.h
@@ -7,6 +7,7 @@ 
 #include <stdint.h>
 #include <processor.h>
 #include <cpu.h>
+#include <ultravisor.h>
 
 /*
  * SCOM "partID" definitions:
@@ -215,10 +216,16 @@  extern void _xscom_unlock(void);
 /* Targeted SCOM access */
 static inline int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val)
 {
-	return _xscom_read(partid, pcb_addr, val, true);
+	if (can_access_xscom())
+		return _xscom_read(partid, pcb_addr, val, true);
+
+	return uv_xscom_read(partid, pcb_addr, val);
 }
 static inline int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val) {
-	return _xscom_write(partid, pcb_addr, val, true);
+	if (can_access_xscom())
+		return _xscom_write(partid, pcb_addr, val, true);
+
+	return uv_xscom_write(partid, pcb_addr, val);
 }
 extern int xscom_write_mask(uint32_t partid, uint64_t pcb_addr, uint64_t val, uint64_t mask);