aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>2019-08-29 13:57:23 -0400
committerRam Pai <linuxram@us.ibm.com>2020-11-02 19:35:09 -0500
commite90b09680988d642872d2e4117ecf64caabd96de (patch)
tree5823c26edc0c6979e79d3eb487edf8028922518d
parent4d79433502d697a138625e6ca17d66590bc39d44 (diff)
downloadskiboot-e90b09680988d642872d2e4117ecf64caabd96de.zip
skiboot-e90b09680988d642872d2e4117ecf64caabd96de.tar.gz
skiboot-e90b09680988d642872d2e4117ecf64caabd96de.tar.bz2
xscoms: read/write xscoms using ucall
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>
-rw-r--r--hw/ultravisor.c8
-rw-r--r--include/ultravisor.h28
-rw-r--r--include/xscom.h11
3 files changed, 45 insertions, 2 deletions
diff --git a/hw/ultravisor.c b/hw/ultravisor.c
index 3a81fe4..28a57d9 100644
--- a/hw/ultravisor.c
+++ b/hw/ultravisor.c
@@ -16,6 +16,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;
@@ -168,6 +169,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;
@@ -190,6 +192,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 04bacec..334cb8e 100644
--- a/include/ultravisor.h
+++ b/include/ultravisor.h
@@ -12,6 +12,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
@@ -19,6 +22,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);
@@ -27,4 +33,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 8a466d5..b28d044 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:
@@ -174,10 +175,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);