/* Basic arch-specific setup */
void (*arch_setup)(void);
char *(*memory_setup)(void);
+ void (*post_allocator_init)(void);
+
void (*init_IRQ)(void);
void (*time_init)(void);
u64 (*read_tsc)(void);
u64 (*read_pmc)(void);
- u64 (*get_scheduled_cycles)(void);
+ unsigned long long (*sched_clock)(void);
unsigned long (*get_cpu_khz)(void);
/* Segment descriptor handling */
unsigned long va);
/* Hooks for allocating/releasing pagetable pages */
- void (*alloc_pt)(u32 pfn);
+ void (*alloc_pt)(struct mm_struct *mm, u32 pfn);
void (*alloc_pd)(u32 pfn);
void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
void (*release_pt)(u32 pfn);
void (*pte_update_defer)(struct mm_struct *mm,
unsigned long addr, pte_t *ptep);
- pte_t (*ptep_get_and_clear)(pte_t *ptep);
-
#ifdef CONFIG_HIGHPTE
void *(*kmap_atomic_pte)(struct page *page, enum km_type type);
#endif
void (*iret)(void);
};
-/* Mark a paravirt probe function. */
-#define paravirt_probe(fn) \
- static asmlinkage void (*__paravirtprobe_##fn)(void) __attribute_used__ \
- __attribute__((__section__(".paravirtprobe"))) = fn
-
extern struct paravirt_ops paravirt_ops;
#define PARAVIRT_PATCH(x) \
unsigned paravirt_patch_insns(void *site, unsigned len,
const char *start, const char *end);
+int paravirt_disable_iospace(void);
/*
* This generates an indirect call based on the operation type number.
* means that all uses must be wrapped in inline functions. This also
* makes sure the incoming and outgoing types are always correct.
*/
-#define PVOP_CALL0(__rettype, __op) \
- ({ \
- __rettype __ret; \
- if (sizeof(__rettype) > sizeof(unsigned long)) { \
- unsigned long long __tmp; \
- unsigned long __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=A" (__tmp), "=c" (__ecx) \
- : paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } else { \
- unsigned long __tmp, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__tmp), "=d" (__edx), \
- "=c" (__ecx) \
- : paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } \
- __ret; \
- })
-#define PVOP_VCALL0(__op) \
- ({ \
- unsigned long __eax, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
- : paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- })
-
-#define PVOP_CALL1(__rettype, __op, arg1) \
- ({ \
- __rettype __ret; \
- if (sizeof(__rettype) > sizeof(unsigned long)) { \
- unsigned long long __tmp; \
- unsigned long __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=A" (__tmp), "=c" (__ecx) \
- : "a" ((u32)(arg1)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } else { \
- unsigned long __tmp, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__tmp), "=d" (__edx), \
- "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } \
- __ret; \
- })
-#define PVOP_VCALL1(__op, arg1) \
+#define __PVOP_CALL(rettype, op, pre, post, ...) \
({ \
+ rettype __ret; \
unsigned long __eax, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- })
-
-#define PVOP_CALL2(__rettype, __op, arg1, arg2) \
- ({ \
- __rettype __ret; \
- if (sizeof(__rettype) > sizeof(unsigned long)) { \
- unsigned long long __tmp; \
- unsigned long __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=A" (__tmp), "=c" (__ecx) \
- : "a" ((u32)(arg1)), \
- "d" ((u32)(arg2)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } else { \
- unsigned long __tmp, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__tmp), "=d" (__edx), \
- "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } \
- __ret; \
- })
-#define PVOP_VCALL2(__op, arg1, arg2) \
- ({ \
- unsigned long __eax, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- })
-
-#define PVOP_CALL3(__rettype, __op, arg1, arg2, arg3) \
- ({ \
- __rettype __ret; \
- if (sizeof(__rettype) > sizeof(unsigned long)) { \
- unsigned long long __tmp; \
- unsigned long __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=A" (__tmp), "=c" (__ecx) \
- : "a" ((u32)(arg1)), \
- "d" ((u32)(arg2)), \
- "1" ((u32)(arg3)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } else { \
- unsigned long __tmp, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__tmp), "=d" (__edx), \
+ if (sizeof(rettype) > sizeof(unsigned long)) { \
+ asm volatile(pre \
+ paravirt_alt(PARAVIRT_CALL) \
+ post \
+ : "=a" (__eax), "=d" (__edx), \
"=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- "2" ((u32)(arg3)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
+ : paravirt_type(op), \
+ paravirt_clobber(CLBR_ANY), \
+ ##__VA_ARGS__ \
: "memory", "cc"); \
- __ret = (__rettype)__tmp; \
- } \
- __ret; \
- })
-#define PVOP_VCALL3(__op, arg1, arg2, arg3) \
- ({ \
- unsigned long __eax, __edx, __ecx; \
- asm volatile(paravirt_alt(PARAVIRT_CALL) \
- : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- "2" ((u32)(arg3)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc"); \
- })
-
-#define PVOP_CALL4(__rettype, __op, arg1, arg2, arg3, arg4) \
- ({ \
- __rettype __ret; \
- if (sizeof(__rettype) > sizeof(unsigned long)) { \
- unsigned long long __tmp; \
- unsigned long __ecx; \
- asm volatile("push %[_arg4]; " \
- paravirt_alt(PARAVIRT_CALL) \
- "lea 4(%%esp),%%esp" \
- : "=A" (__tmp), "=c" (__ecx) \
- : "a" ((u32)(arg1)), \
- "d" ((u32)(arg2)), \
- "1" ((u32)(arg3)), \
- [_arg4] "mr" ((u32)(arg4)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
- : "memory", "cc",); \
- __ret = (__rettype)__tmp; \
+ __ret = (rettype)((((u64)__edx) << 32) | __eax); \
} else { \
- unsigned long __tmp, __edx, __ecx; \
- asm volatile("push %[_arg4]; " \
+ asm volatile(pre \
paravirt_alt(PARAVIRT_CALL) \
- "lea 4(%%esp),%%esp" \
- : "=a" (__tmp), "=d" (__edx), "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- "2" ((u32)(arg3)), \
- [_arg4]"mr" ((u32)(arg4)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
+ post \
+ : "=a" (__eax), "=d" (__edx), \
+ "=c" (__ecx) \
+ : paravirt_type(op), \
+ paravirt_clobber(CLBR_ANY), \
+ ##__VA_ARGS__ \
: "memory", "cc"); \
- __ret = (__rettype)__tmp; \
+ __ret = (rettype)__eax; \
} \
__ret; \
})
-#define PVOP_VCALL4(__op, arg1, arg2, arg3, arg4) \
+#define __PVOP_VCALL(op, pre, post, ...) \
({ \
unsigned long __eax, __edx, __ecx; \
- asm volatile("push %[_arg4]; " \
+ asm volatile(pre \
paravirt_alt(PARAVIRT_CALL) \
- "lea 4(%%esp),%%esp" \
+ post \
: "=a" (__eax), "=d" (__edx), "=c" (__ecx) \
- : "0" ((u32)(arg1)), \
- "1" ((u32)(arg2)), \
- "2" ((u32)(arg3)), \
- [_arg4]"mr" ((u32)(arg4)), \
- paravirt_type(__op), \
- paravirt_clobber(CLBR_ANY) \
+ : paravirt_type(op), \
+ paravirt_clobber(CLBR_ANY), \
+ ##__VA_ARGS__ \
: "memory", "cc"); \
})
+#define PVOP_CALL0(rettype, op) \
+ __PVOP_CALL(rettype, op, "", "")
+#define PVOP_VCALL0(op) \
+ __PVOP_VCALL(op, "", "")
+
+#define PVOP_CALL1(rettype, op, arg1) \
+ __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)))
+#define PVOP_VCALL1(op, arg1) \
+ __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)))
+
+#define PVOP_CALL2(rettype, op, arg1, arg2) \
+ __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2)))
+#define PVOP_VCALL2(op, arg1, arg2) \
+ __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2)))
+
+#define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \
+ __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), \
+ "1"((u32)(arg2)), "2"((u32)(arg3)))
+#define PVOP_VCALL3(op, arg1, arg2, arg3) \
+ __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)), \
+ "2"((u32)(arg3)))
+
+#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \
+ __PVOP_CALL(rettype, op, \
+ "push %[_arg4];", "lea 4(%%esp),%%esp;", \
+ "0" ((u32)(arg1)), "1" ((u32)(arg2)), \
+ "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4)))
+#define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \
+ __PVOP_VCALL(op, \
+ "push %[_arg4];", "lea 4(%%esp),%%esp;", \
+ "0" ((u32)(arg1)), "1" ((u32)(arg2)), \
+ "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4)))
+
static inline int paravirt_enabled(void)
{
return paravirt_ops.paravirt_enabled;
val = paravirt_read_msr(msr, &_err); \
} while(0)
-#define wrmsrl(msr,val) ((void)paravirt_write_msr(msr, val, 0))
+#define wrmsrl(msr,val) wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
#define wrmsr_safe(msr,a,b) paravirt_write_msr(msr, a, b)
/* rdmsr with exception handling */
{
return PVOP_CALL0(u64, read_tsc);
}
-#define rdtsc(low,high) do { \
- u64 _l = paravirt_read_tsc(); \
- low = (u32)_l; \
- high = _l >> 32; \
-} while(0)
#define rdtscl(low) do { \
u64 _l = paravirt_read_tsc(); \
#define rdtscll(val) (val = paravirt_read_tsc())
-#define get_scheduled_cycles(val) (val = paravirt_ops.get_scheduled_cycles())
+static inline unsigned long long paravirt_sched_clock(void)
+{
+ return PVOP_CALL0(unsigned long long, sched_clock);
+}
#define calculate_cpu_khz() (paravirt_ops.get_cpu_khz())
#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
}
#endif
+static inline void paravirt_post_allocator_init(void)
+{
+ if (paravirt_ops.post_allocator_init)
+ (*paravirt_ops.post_allocator_init)();
+}
+
static inline void paravirt_pagetable_setup_start(pgd_t *base)
{
if (paravirt_ops.pagetable_setup_start)
PVOP_VCALL3(flush_tlb_others, &cpumask, mm, va);
}
-static inline void paravirt_alloc_pt(unsigned pfn)
+static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
{
- PVOP_VCALL1(alloc_pt, pfn);
+ PVOP_VCALL2(alloc_pt, mm, pfn);
}
static inline void paravirt_release_pt(unsigned pfn)
{
PVOP_VCALL1(pmd_clear, pmdp);
}
-static inline pte_t raw_ptep_get_and_clear(pte_t *p)
-{
- unsigned long long val = PVOP_CALL1(unsigned long long, ptep_get_and_clear, p);
- return (pte_t) { val, val >> 32 };
-}
#else /* !CONFIG_X86_PAE */
+
static inline pte_t __pte(unsigned long val)
{
return (pte_t) { PVOP_CALL1(unsigned long, make_pte, val) };
{
PVOP_VCALL2(set_pmd, pmdp, pmdval.pud.pgd.pgd);
}
-
-static inline pte_t raw_ptep_get_and_clear(pte_t *p)
-{
- return (pte_t) { PVOP_CALL1(unsigned long, ptep_get_and_clear, p) };
-}
#endif /* CONFIG_X86_PAE */
#define __HAVE_ARCH_ENTER_LAZY_CPU_MODE
/* Make sure as little as possible of this mess escapes. */
#undef PARAVIRT_CALL
+#undef __PVOP_CALL
+#undef __PVOP_VCALL
#undef PVOP_VCALL0
#undef PVOP_CALL0
#undef PVOP_VCALL1