@@ -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);
@@ -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 */
@@ -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);