Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/vas: Add hcall wrappers for VAS handling

This patch adds the following hcall wrapper functions to allocate,
modify and deallocate VAS windows, and retrieve VAS capabilities.

H_ALLOCATE_VAS_WINDOW: Allocate VAS window
H_DEALLOCATE_VAS_WINDOW: Close VAS window
H_MODIFY_VAS_WINDOW: Setup window before using
H_QUERY_VAS_CAPABILITIES: Get VAS capabilities

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/40fb02a4d56ca4e240b074a15029082055be5997.camel@linux.ibm.com

authored by

Haren Myneni and committed by
Michael Ellerman
f33ecfde 540761b7

+147
+147
arch/powerpc/platforms/pseries/vas.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright 2020-21 IBM Corp. 4 + */ 5 + 6 + #define pr_fmt(fmt) "vas: " fmt 7 + 8 + #include <linux/module.h> 9 + #include <linux/kernel.h> 10 + #include <linux/export.h> 11 + #include <linux/types.h> 12 + #include <linux/delay.h> 13 + #include <asm/hvcall.h> 14 + #include <asm/plpar_wrappers.h> 15 + #include <asm/vas.h> 16 + #include "vas.h" 17 + 18 + #define VAS_INVALID_WIN_ADDRESS 0xFFFFFFFFFFFFFFFFul 19 + #define VAS_DEFAULT_DOMAIN_ID 0xFFFFFFFFFFFFFFFFul 20 + /* The hypervisor allows one credit per window right now */ 21 + #define DEF_WIN_CREDS 1 22 + 23 + static long hcall_return_busy_check(long rc) 24 + { 25 + /* Check if we are stalled for some time */ 26 + if (H_IS_LONG_BUSY(rc)) { 27 + msleep(get_longbusy_msecs(rc)); 28 + rc = H_BUSY; 29 + } else if (rc == H_BUSY) { 30 + cond_resched(); 31 + } 32 + 33 + return rc; 34 + } 35 + 36 + /* 37 + * Allocate VAS window hcall 38 + */ 39 + static int h_allocate_vas_window(struct pseries_vas_window *win, u64 *domain, 40 + u8 wintype, u16 credits) 41 + { 42 + long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; 43 + long rc; 44 + 45 + do { 46 + rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf, wintype, 47 + credits, domain[0], domain[1], domain[2], 48 + domain[3], domain[4], domain[5]); 49 + 50 + rc = hcall_return_busy_check(rc); 51 + } while (rc == H_BUSY); 52 + 53 + if (rc == H_SUCCESS) { 54 + if (win->win_addr == VAS_INVALID_WIN_ADDRESS) { 55 + pr_err("H_ALLOCATE_VAS_WINDOW: COPY/PASTE is not supported\n"); 56 + return -ENOTSUPP; 57 + } 58 + win->vas_win.winid = retbuf[0]; 59 + win->win_addr = retbuf[1]; 60 + win->complete_irq = retbuf[2]; 61 + win->fault_irq = retbuf[3]; 62 + return 0; 63 + } 64 + 65 + pr_err("H_ALLOCATE_VAS_WINDOW error: %ld, wintype: %u, credits: %u\n", 66 + rc, wintype, credits); 67 + 68 + return -EIO; 69 + } 70 + 71 + /* 72 + * Deallocate VAS window hcall. 73 + */ 74 + static int h_deallocate_vas_window(u64 winid) 75 + { 76 + long rc; 77 + 78 + do { 79 + rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW, winid); 80 + 81 + rc = hcall_return_busy_check(rc); 82 + } while (rc == H_BUSY); 83 + 84 + if (rc == H_SUCCESS) 85 + return 0; 86 + 87 + pr_err("H_DEALLOCATE_VAS_WINDOW error: %ld, winid: %llu\n", 88 + rc, winid); 89 + return -EIO; 90 + } 91 + 92 + /* 93 + * Modify VAS window. 94 + * After the window is opened with allocate window hcall, configure it 95 + * with flags and LPAR PID before using. 96 + */ 97 + static int h_modify_vas_window(struct pseries_vas_window *win) 98 + { 99 + long rc; 100 + u32 lpid = mfspr(SPRN_PID); 101 + 102 + /* 103 + * AMR value is not supported in Linux VAS implementation. 104 + * The hypervisor ignores it if 0 is passed. 105 + */ 106 + do { 107 + rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, 108 + win->vas_win.winid, lpid, 0, 109 + VAS_MOD_WIN_FLAGS, 0); 110 + 111 + rc = hcall_return_busy_check(rc); 112 + } while (rc == H_BUSY); 113 + 114 + if (rc == H_SUCCESS) 115 + return 0; 116 + 117 + pr_err("H_MODIFY_VAS_WINDOW error: %ld, winid %u lpid %u\n", 118 + rc, win->vas_win.winid, lpid); 119 + return -EIO; 120 + } 121 + 122 + /* 123 + * This hcall is used to determine the capabilities from the hypervisor. 124 + * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES 125 + * @query_type: If 0 is passed, the hypervisor returns the overall 126 + * capabilities which provides all feature(s) that are 127 + * available. Then query the hypervisor to get the 128 + * corresponding capabilities for the specific feature. 129 + * Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS 130 + * and VAS GZIP Default capabilities. 131 + * H_QUERY_NX_CAPABILITIES provides NX GZIP 132 + * capabilities. 133 + * @result: Return buffer to save capabilities. 134 + */ 135 + int h_query_vas_capabilities(const u64 hcall, u8 query_type, u64 result) 136 + { 137 + long rc; 138 + 139 + rc = plpar_hcall_norets(hcall, query_type, result); 140 + 141 + if (rc == H_SUCCESS) 142 + return 0; 143 + 144 + pr_err("HCALL(%llx) error %ld, query_type %u, result buffer 0x%llx\n", 145 + hcall, rc, query_type, result); 146 + return -EIO; 147 + }