|
@@ -169,3 +169,86 @@ void paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch);
|
|
|
(PARAVIRT_PATCH_TYPE_BR_START + 1)
|
|
|
#define PARAVIRT_PATCH_TYPE_BR_WORK_PROCESSED_SYSCALL \
|
|
|
(PARAVIRT_PATCH_TYPE_BR_START + 2)
|
|
|
+#define PARAVIRT_PATCH_TYPE_BR_LEAVE_KERNEL \
|
|
|
+ (PARAVIRT_PATCH_TYPE_BR_START + 3)
|
|
|
+
|
|
|
+#ifdef ASM_SUPPORTED
|
|
|
+#include <asm/paravirt_patch.h>
|
|
|
+
|
|
|
+/*
|
|
|
+ * pv_cpu_ops calling stub.
|
|
|
+ * normal function call convension can't be written by gcc
|
|
|
+ * inline assembly.
|
|
|
+ *
|
|
|
+ * from the caller's point of view,
|
|
|
+ * the following registers will be clobbered.
|
|
|
+ * r2, r3
|
|
|
+ * r8-r15
|
|
|
+ * r16, r17
|
|
|
+ * b6, b7
|
|
|
+ * p6-p15
|
|
|
+ * ar.ccv
|
|
|
+ *
|
|
|
+ * from the callee's point of view ,
|
|
|
+ * the following registers can be used.
|
|
|
+ * r2, r3: scratch
|
|
|
+ * r8: scratch, input argument0 and return value
|
|
|
+ * r0-r15: scratch, input argument1-5
|
|
|
+ * b6: return pointer
|
|
|
+ * b7: scratch
|
|
|
+ * p6-p15: scratch
|
|
|
+ * ar.ccv: scratch
|
|
|
+ *
|
|
|
+ * other registers must not be changed. especially
|
|
|
+ * b0: rp: preserved. gcc ignores b0 in clobbered register.
|
|
|
+ * r16: saved gp
|
|
|
+ */
|
|
|
+/* 5 bundles */
|
|
|
+#define __PARAVIRT_BR \
|
|
|
+ ";;\n" \
|
|
|
+ "{ .mlx\n" \
|
|
|
+ "nop 0\n" \
|
|
|
+ "movl r2 = %[op_addr]\n"/* get function pointer address */ \
|
|
|
+ ";;\n" \
|
|
|
+ "}\n" \
|
|
|
+ "1:\n" \
|
|
|
+ "{ .mii\n" \
|
|
|
+ "ld8 r2 = [r2]\n" /* load function descriptor address */ \
|
|
|
+ "mov r17 = ip\n" /* get ip to calc return address */ \
|
|
|
+ "mov r16 = gp\n" /* save gp */ \
|
|
|
+ ";;\n" \
|
|
|
+ "}\n" \
|
|
|
+ "{ .mii\n" \
|
|
|
+ "ld8 r3 = [r2], 8\n" /* load entry address */ \
|
|
|
+ "adds r17 = 1f - 1b, r17\n" /* calculate return address */ \
|
|
|
+ ";;\n" \
|
|
|
+ "mov b7 = r3\n" /* set entry address */ \
|
|
|
+ "}\n" \
|
|
|
+ "{ .mib\n" \
|
|
|
+ "ld8 gp = [r2]\n" /* load gp value */ \
|
|
|
+ "mov b6 = r17\n" /* set return address */ \
|
|
|
+ "br.cond.sptk.few b7\n" /* intrinsics are very short isns */ \
|
|
|
+ "}\n" \
|
|
|
+ "1:\n" \
|
|
|
+ "{ .mii\n" \
|
|
|
+ "mov gp = r16\n" /* restore gp value */ \
|
|
|
+ "nop 0\n" \
|
|
|
+ "nop 0\n" \
|
|
|
+ ";;\n" \
|
|
|
+ "}\n"
|
|
|
+
|
|
|
+#define PARAVIRT_OP(op) \
|
|
|
+ [op_addr] "i"(&pv_cpu_ops.op)
|
|
|
+
|
|
|
+#define PARAVIRT_TYPE(type) \
|
|
|
+ PARAVIRT_PATCH_TYPE_ ## type
|
|
|
+
|
|
|
+#define PARAVIRT_REG_CLOBBERS0 \
|
|
|
+ "r2", "r3", /*"r8",*/ "r9", "r10", "r11", "r14", \
|
|
|
+ "r15", "r16", "r17"
|
|
|
+
|
|
|
+#define PARAVIRT_REG_CLOBBERS1 \
|
|
|
+ "r2","r3", /*"r8",*/ "r9", "r10", "r11", "r14", \
|
|
|
+ "r15", "r16", "r17"
|
|
|
+
|
|
|
+#define PARAVIRT_REG_CLOBBERS2 \
|