diff options
Diffstat (limited to 'include/asm-x86/paravirt.h')
-rw-r--r-- | include/asm-x86/paravirt.h | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index ef5e8ec6a6ab..fbbde93f12d6 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h | |||
@@ -205,7 +205,6 @@ struct pv_apic_ops { | |||
205 | * these shouldn't be in this interface. | 205 | * these shouldn't be in this interface. |
206 | */ | 206 | */ |
207 | void (*apic_write)(unsigned long reg, u32 v); | 207 | void (*apic_write)(unsigned long reg, u32 v); |
208 | void (*apic_write_atomic)(unsigned long reg, u32 v); | ||
209 | u32 (*apic_read)(unsigned long reg); | 208 | u32 (*apic_read)(unsigned long reg); |
210 | void (*setup_boot_clock)(void); | 209 | void (*setup_boot_clock)(void); |
211 | void (*setup_secondary_clock)(void); | 210 | void (*setup_secondary_clock)(void); |
@@ -326,6 +325,15 @@ struct pv_mmu_ops { | |||
326 | unsigned long phys, pgprot_t flags); | 325 | unsigned long phys, pgprot_t flags); |
327 | }; | 326 | }; |
328 | 327 | ||
328 | struct raw_spinlock; | ||
329 | struct pv_lock_ops { | ||
330 | int (*spin_is_locked)(struct raw_spinlock *lock); | ||
331 | int (*spin_is_contended)(struct raw_spinlock *lock); | ||
332 | void (*spin_lock)(struct raw_spinlock *lock); | ||
333 | int (*spin_trylock)(struct raw_spinlock *lock); | ||
334 | void (*spin_unlock)(struct raw_spinlock *lock); | ||
335 | }; | ||
336 | |||
329 | /* This contains all the paravirt structures: we get a convenient | 337 | /* This contains all the paravirt structures: we get a convenient |
330 | * number for each function using the offset which we use to indicate | 338 | * number for each function using the offset which we use to indicate |
331 | * what to patch. */ | 339 | * what to patch. */ |
@@ -336,6 +344,7 @@ struct paravirt_patch_template { | |||
336 | struct pv_irq_ops pv_irq_ops; | 344 | struct pv_irq_ops pv_irq_ops; |
337 | struct pv_apic_ops pv_apic_ops; | 345 | struct pv_apic_ops pv_apic_ops; |
338 | struct pv_mmu_ops pv_mmu_ops; | 346 | struct pv_mmu_ops pv_mmu_ops; |
347 | struct pv_lock_ops pv_lock_ops; | ||
339 | }; | 348 | }; |
340 | 349 | ||
341 | extern struct pv_info pv_info; | 350 | extern struct pv_info pv_info; |
@@ -345,6 +354,7 @@ extern struct pv_cpu_ops pv_cpu_ops; | |||
345 | extern struct pv_irq_ops pv_irq_ops; | 354 | extern struct pv_irq_ops pv_irq_ops; |
346 | extern struct pv_apic_ops pv_apic_ops; | 355 | extern struct pv_apic_ops pv_apic_ops; |
347 | extern struct pv_mmu_ops pv_mmu_ops; | 356 | extern struct pv_mmu_ops pv_mmu_ops; |
357 | extern struct pv_lock_ops pv_lock_ops; | ||
348 | 358 | ||
349 | #define PARAVIRT_PATCH(x) \ | 359 | #define PARAVIRT_PATCH(x) \ |
350 | (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) | 360 | (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) |
@@ -896,11 +906,6 @@ static inline void apic_write(unsigned long reg, u32 v) | |||
896 | PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); | 906 | PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); |
897 | } | 907 | } |
898 | 908 | ||
899 | static inline void apic_write_atomic(unsigned long reg, u32 v) | ||
900 | { | ||
901 | PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v); | ||
902 | } | ||
903 | |||
904 | static inline u32 apic_read(unsigned long reg) | 909 | static inline u32 apic_read(unsigned long reg) |
905 | { | 910 | { |
906 | return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); | 911 | return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); |
@@ -1083,6 +1088,9 @@ static inline pteval_t pte_flags(pte_t pte) | |||
1083 | ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags, | 1088 | ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags, |
1084 | pte.pte); | 1089 | pte.pte); |
1085 | 1090 | ||
1091 | #ifdef CONFIG_PARAVIRT_DEBUG | ||
1092 | BUG_ON(ret & PTE_PFN_MASK); | ||
1093 | #endif | ||
1086 | return ret; | 1094 | return ret; |
1087 | } | 1095 | } |
1088 | 1096 | ||
@@ -1374,6 +1382,37 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, | |||
1374 | void _paravirt_nop(void); | 1382 | void _paravirt_nop(void); |
1375 | #define paravirt_nop ((void *)_paravirt_nop) | 1383 | #define paravirt_nop ((void *)_paravirt_nop) |
1376 | 1384 | ||
1385 | void paravirt_use_bytelocks(void); | ||
1386 | |||
1387 | #ifdef CONFIG_SMP | ||
1388 | |||
1389 | static inline int __raw_spin_is_locked(struct raw_spinlock *lock) | ||
1390 | { | ||
1391 | return PVOP_CALL1(int, pv_lock_ops.spin_is_locked, lock); | ||
1392 | } | ||
1393 | |||
1394 | static inline int __raw_spin_is_contended(struct raw_spinlock *lock) | ||
1395 | { | ||
1396 | return PVOP_CALL1(int, pv_lock_ops.spin_is_contended, lock); | ||
1397 | } | ||
1398 | |||
1399 | static __always_inline void __raw_spin_lock(struct raw_spinlock *lock) | ||
1400 | { | ||
1401 | PVOP_VCALL1(pv_lock_ops.spin_lock, lock); | ||
1402 | } | ||
1403 | |||
1404 | static __always_inline int __raw_spin_trylock(struct raw_spinlock *lock) | ||
1405 | { | ||
1406 | return PVOP_CALL1(int, pv_lock_ops.spin_trylock, lock); | ||
1407 | } | ||
1408 | |||
1409 | static __always_inline void __raw_spin_unlock(struct raw_spinlock *lock) | ||
1410 | { | ||
1411 | PVOP_VCALL1(pv_lock_ops.spin_unlock, lock); | ||
1412 | } | ||
1413 | |||
1414 | #endif | ||
1415 | |||
1377 | /* These all sit in the .parainstructions section to tell us what to patch. */ | 1416 | /* These all sit in the .parainstructions section to tell us what to patch. */ |
1378 | struct paravirt_patch_site { | 1417 | struct paravirt_patch_site { |
1379 | u8 *instr; /* original instructions */ | 1418 | u8 *instr; /* original instructions */ |
@@ -1396,8 +1435,8 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1396 | * caller saved registers but the argument parameter */ | 1435 | * caller saved registers but the argument parameter */ |
1397 | #define PV_SAVE_REGS "pushq %%rdi;" | 1436 | #define PV_SAVE_REGS "pushq %%rdi;" |
1398 | #define PV_RESTORE_REGS "popq %%rdi;" | 1437 | #define PV_RESTORE_REGS "popq %%rdi;" |
1399 | #define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx" | 1438 | #define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx", "rsi" |
1400 | #define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx" | 1439 | #define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx", "rsi" |
1401 | #define PV_FLAGS_ARG "D" | 1440 | #define PV_FLAGS_ARG "D" |
1402 | #endif | 1441 | #endif |
1403 | 1442 | ||
@@ -1458,6 +1497,7 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1458 | return f; | 1497 | return f; |
1459 | } | 1498 | } |
1460 | 1499 | ||
1500 | |||
1461 | /* Make sure as little as possible of this mess escapes. */ | 1501 | /* Make sure as little as possible of this mess escapes. */ |
1462 | #undef PARAVIRT_CALL | 1502 | #undef PARAVIRT_CALL |
1463 | #undef __PVOP_CALL | 1503 | #undef __PVOP_CALL |
@@ -1489,8 +1529,26 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1489 | 1529 | ||
1490 | 1530 | ||
1491 | #ifdef CONFIG_X86_64 | 1531 | #ifdef CONFIG_X86_64 |
1492 | #define PV_SAVE_REGS pushq %rax; pushq %rdi; pushq %rcx; pushq %rdx | 1532 | #define PV_SAVE_REGS \ |
1493 | #define PV_RESTORE_REGS popq %rdx; popq %rcx; popq %rdi; popq %rax | 1533 | push %rax; \ |
1534 | push %rcx; \ | ||
1535 | push %rdx; \ | ||
1536 | push %rsi; \ | ||
1537 | push %rdi; \ | ||
1538 | push %r8; \ | ||
1539 | push %r9; \ | ||
1540 | push %r10; \ | ||
1541 | push %r11 | ||
1542 | #define PV_RESTORE_REGS \ | ||
1543 | pop %r11; \ | ||
1544 | pop %r10; \ | ||
1545 | pop %r9; \ | ||
1546 | pop %r8; \ | ||
1547 | pop %rdi; \ | ||
1548 | pop %rsi; \ | ||
1549 | pop %rdx; \ | ||
1550 | pop %rcx; \ | ||
1551 | pop %rax | ||
1494 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) | 1552 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) |
1495 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) | 1553 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) |
1496 | #define PARA_INDIRECT(addr) *addr(%rip) | 1554 | #define PARA_INDIRECT(addr) *addr(%rip) |