diff options
-rw-r--r-- | arch/powerpc/include/asm/plpar_wrappers.h | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/htmdump.c | 63 |
2 files changed, 63 insertions, 18 deletions
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h index 91be7b885944..f3efa9946b3c 100644 --- a/arch/powerpc/include/asm/plpar_wrappers.h +++ b/arch/powerpc/include/asm/plpar_wrappers.h @@ -65,6 +65,14 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa) return vpa_call(H_VPA_REG_DTL, cpu, vpa); } +/* + * Invokes H_HTM hcall with parameters passed from htm_hcall_wrapper. + * flags: Set to hardwareTarget. + * target: Specifies target using node index, nodal chip index and core index. + * operation : action to perform ie configure, start, stop, deconfigure, trace + * based on the HTM type. + * param1, param2, param3: parameters for each action. + */ static inline long htm_call(unsigned long flags, unsigned long target, unsigned long operation, unsigned long param1, unsigned long param2, unsigned long param3) @@ -73,17 +81,17 @@ static inline long htm_call(unsigned long flags, unsigned long target, param1, param2, param3); } -static inline long htm_get_dump_hardware(unsigned long nodeindex, +static inline long htm_hcall_wrapper(unsigned long nodeindex, unsigned long nodalchipindex, unsigned long coreindexonchip, - unsigned long type, unsigned long addr, unsigned long size, - unsigned long offset) + unsigned long type, unsigned long htm_op, unsigned long param1, unsigned long param2, + unsigned long param3) { return htm_call(H_HTM_FLAGS_HARDWARE_TARGET, H_HTM_TARGET_NODE_INDEX(nodeindex) | H_HTM_TARGET_NODAL_CHIP_INDEX(nodalchipindex) | H_HTM_TARGET_CORE_INDEX_ON_CHIP(coreindexonchip), - H_HTM_OP(H_HTM_OP_DUMP_DATA) | H_HTM_TYPE(type), - addr, size, offset); + H_HTM_OP(htm_op) | H_HTM_TYPE(type), + param1, param2, param3); } extern void vpa_init(int cpu); diff --git a/arch/powerpc/platforms/pseries/htmdump.c b/arch/powerpc/platforms/pseries/htmdump.c index 57fc1700f604..604fde6a0559 100644 --- a/arch/powerpc/platforms/pseries/htmdump.c +++ b/arch/powerpc/platforms/pseries/htmdump.c @@ -18,20 +18,19 @@ static u32 coreindexonchip; static u32 htmtype; static struct dentry *htmdump_debugfs_dir; -static ssize_t htmdump_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *ppos) +/* + * Check the return code for H_HTM hcall. + * Return non-zero value (1) if either H_PARTIAL or H_SUCCESS + * is returned. For other return codes: + * Return zero if H_NOT_AVAILABLE. + * Return -EBUSY if hcall return busy. + * Return -EINVAL if any parameter or operation is not valid. + * Return -EPERM if HTM Virtualization Engine Technology code + * is not applied. + * Return -EIO if the HTM state is not valid. + */ +static ssize_t htm_return_check(long rc) { - void *htm_buf = filp->private_data; - unsigned long page, read_size, available; - loff_t offset; - long rc; - - page = ALIGN_DOWN(*ppos, PAGE_SIZE); - offset = (*ppos) % PAGE_SIZE; - - rc = htm_get_dump_hardware(nodeindex, nodalchipindex, coreindexonchip, - htmtype, virt_to_phys(htm_buf), PAGE_SIZE, page); - switch (rc) { case H_SUCCESS: /* H_PARTIAL for the case where all available data can't be @@ -65,6 +64,38 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf, return -EPERM; } + /* + * Return 1 for H_SUCCESS/H_PARTIAL + */ + return 1; +} + +static ssize_t htmdump_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos) +{ + void *htm_buf = filp->private_data; + unsigned long page, read_size, available; + loff_t offset; + long rc, ret; + + page = ALIGN_DOWN(*ppos, PAGE_SIZE); + offset = (*ppos) % PAGE_SIZE; + + /* + * Invoke H_HTM call with: + * - operation as htm dump (H_HTM_OP_DUMP_DATA) + * - last three values are address, size and offset + */ + rc = htm_hcall_wrapper(nodeindex, nodalchipindex, coreindexonchip, + htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf), + PAGE_SIZE, page); + + ret = htm_return_check(rc); + if (ret <= 0) { + pr_debug("H_HTM hcall failed for op: H_HTM_OP_DUMP_DATA, returning %ld\n", ret); + return ret; + } + available = PAGE_SIZE; read_size = min(count, available); *ppos += read_size; @@ -103,6 +134,12 @@ static int htmdump_init_debugfs(void) static int __init htmdump_init(void) { + /* Disable on kvm guest */ + if (is_kvm_guest()) { + pr_info("htmdump not supported inside KVM guest\n"); + return -EOPNOTSUPP; + } + if (htmdump_init_debugfs()) return -ENOMEM; |