diff options
author | Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> | 2016-05-04 15:09:40 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-05-18 12:04:25 -0400 |
commit | 1e6e2755b635e85ce0b1ce827b7c375b6a0a890c (patch) | |
tree | f892fef66ac51b3c347982fedc66f4b025db849b | |
parent | 2086d3200dc9966c96a6c319a1214a94f00223f8 (diff) |
KVM: x86: Misc LAPIC changes to expose helper functions
Exporting LAPIC utility functions and macros for re-use in SVM code.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/lapic.c | 127 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 29 |
2 files changed, 82 insertions, 74 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 1a2da0e5a373..f6f42f634e77 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -59,9 +59,8 @@ | |||
59 | /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ | 59 | /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ |
60 | #define apic_debug(fmt, arg...) | 60 | #define apic_debug(fmt, arg...) |
61 | 61 | ||
62 | #define APIC_LVT_NUM 6 | ||
63 | /* 14 is the version for Xeon and Pentium 8.4.8*/ | 62 | /* 14 is the version for Xeon and Pentium 8.4.8*/ |
64 | #define APIC_VERSION (0x14UL | ((APIC_LVT_NUM - 1) << 16)) | 63 | #define APIC_VERSION (0x14UL | ((KVM_APIC_LVT_NUM - 1) << 16)) |
65 | #define LAPIC_MMIO_LENGTH (1 << 12) | 64 | #define LAPIC_MMIO_LENGTH (1 << 12) |
66 | /* followed define is not in apicdef.h */ | 65 | /* followed define is not in apicdef.h */ |
67 | #define APIC_SHORT_MASK 0xc0000 | 66 | #define APIC_SHORT_MASK 0xc0000 |
@@ -73,14 +72,6 @@ | |||
73 | #define APIC_BROADCAST 0xFF | 72 | #define APIC_BROADCAST 0xFF |
74 | #define X2APIC_BROADCAST 0xFFFFFFFFul | 73 | #define X2APIC_BROADCAST 0xFFFFFFFFul |
75 | 74 | ||
76 | #define VEC_POS(v) ((v) & (32 - 1)) | ||
77 | #define REG_POS(v) (((v) >> 5) << 4) | ||
78 | |||
79 | static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val) | ||
80 | { | ||
81 | *((u32 *) (apic->regs + reg_off)) = val; | ||
82 | } | ||
83 | |||
84 | static inline int apic_test_vector(int vec, void *bitmap) | 75 | static inline int apic_test_vector(int vec, void *bitmap) |
85 | { | 76 | { |
86 | return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 77 | return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
@@ -94,11 +85,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector) | |||
94 | apic_test_vector(vector, apic->regs + APIC_IRR); | 85 | apic_test_vector(vector, apic->regs + APIC_IRR); |
95 | } | 86 | } |
96 | 87 | ||
97 | static inline void apic_set_vector(int vec, void *bitmap) | ||
98 | { | ||
99 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | ||
100 | } | ||
101 | |||
102 | static inline void apic_clear_vector(int vec, void *bitmap) | 88 | static inline void apic_clear_vector(int vec, void *bitmap) |
103 | { | 89 | { |
104 | clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 90 | clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
@@ -212,7 +198,7 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val) | |||
212 | { | 198 | { |
213 | bool enabled = val & APIC_SPIV_APIC_ENABLED; | 199 | bool enabled = val & APIC_SPIV_APIC_ENABLED; |
214 | 200 | ||
215 | apic_set_reg(apic, APIC_SPIV, val); | 201 | kvm_lapic_set_reg(apic, APIC_SPIV, val); |
216 | 202 | ||
217 | if (enabled != apic->sw_enabled) { | 203 | if (enabled != apic->sw_enabled) { |
218 | apic->sw_enabled = enabled; | 204 | apic->sw_enabled = enabled; |
@@ -226,13 +212,13 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val) | |||
226 | 212 | ||
227 | static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id) | 213 | static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id) |
228 | { | 214 | { |
229 | apic_set_reg(apic, APIC_ID, id << 24); | 215 | kvm_lapic_set_reg(apic, APIC_ID, id << 24); |
230 | recalculate_apic_map(apic->vcpu->kvm); | 216 | recalculate_apic_map(apic->vcpu->kvm); |
231 | } | 217 | } |
232 | 218 | ||
233 | static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id) | 219 | static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id) |
234 | { | 220 | { |
235 | apic_set_reg(apic, APIC_LDR, id); | 221 | kvm_lapic_set_reg(apic, APIC_LDR, id); |
236 | recalculate_apic_map(apic->vcpu->kvm); | 222 | recalculate_apic_map(apic->vcpu->kvm); |
237 | } | 223 | } |
238 | 224 | ||
@@ -240,8 +226,8 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u8 id) | |||
240 | { | 226 | { |
241 | u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf)); | 227 | u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf)); |
242 | 228 | ||
243 | apic_set_reg(apic, APIC_ID, id << 24); | 229 | kvm_lapic_set_reg(apic, APIC_ID, id << 24); |
244 | apic_set_reg(apic, APIC_LDR, ldr); | 230 | kvm_lapic_set_reg(apic, APIC_LDR, ldr); |
245 | recalculate_apic_map(apic->vcpu->kvm); | 231 | recalculate_apic_map(apic->vcpu->kvm); |
246 | } | 232 | } |
247 | 233 | ||
@@ -287,10 +273,10 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu) | |||
287 | feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); | 273 | feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); |
288 | if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31)))) | 274 | if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31)))) |
289 | v |= APIC_LVR_DIRECTED_EOI; | 275 | v |= APIC_LVR_DIRECTED_EOI; |
290 | apic_set_reg(apic, APIC_LVR, v); | 276 | kvm_lapic_set_reg(apic, APIC_LVR, v); |
291 | } | 277 | } |
292 | 278 | ||
293 | static const unsigned int apic_lvt_mask[APIC_LVT_NUM] = { | 279 | static const unsigned int apic_lvt_mask[KVM_APIC_LVT_NUM] = { |
294 | LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */ | 280 | LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */ |
295 | LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ | 281 | LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ |
296 | LVT_MASK | APIC_MODE_MASK, /* LVTPC */ | 282 | LVT_MASK | APIC_MODE_MASK, /* LVTPC */ |
@@ -349,16 +335,6 @@ void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir) | |||
349 | } | 335 | } |
350 | EXPORT_SYMBOL_GPL(kvm_apic_update_irr); | 336 | EXPORT_SYMBOL_GPL(kvm_apic_update_irr); |
351 | 337 | ||
352 | static inline void apic_set_irr(int vec, struct kvm_lapic *apic) | ||
353 | { | ||
354 | apic_set_vector(vec, apic->regs + APIC_IRR); | ||
355 | /* | ||
356 | * irr_pending must be true if any interrupt is pending; set it after | ||
357 | * APIC_IRR to avoid race with apic_clear_irr | ||
358 | */ | ||
359 | apic->irr_pending = true; | ||
360 | } | ||
361 | |||
362 | static inline int apic_search_irr(struct kvm_lapic *apic) | 338 | static inline int apic_search_irr(struct kvm_lapic *apic) |
363 | { | 339 | { |
364 | return find_highest_vector(apic->regs + APIC_IRR); | 340 | return find_highest_vector(apic->regs + APIC_IRR); |
@@ -563,7 +539,7 @@ static void apic_update_ppr(struct kvm_lapic *apic) | |||
563 | apic, ppr, isr, isrv); | 539 | apic, ppr, isr, isrv); |
564 | 540 | ||
565 | if (old_ppr != ppr) { | 541 | if (old_ppr != ppr) { |
566 | apic_set_reg(apic, APIC_PROCPRI, ppr); | 542 | kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr); |
567 | if (ppr < old_ppr) | 543 | if (ppr < old_ppr) |
568 | kvm_make_request(KVM_REQ_EVENT, apic->vcpu); | 544 | kvm_make_request(KVM_REQ_EVENT, apic->vcpu); |
569 | } | 545 | } |
@@ -571,7 +547,7 @@ static void apic_update_ppr(struct kvm_lapic *apic) | |||
571 | 547 | ||
572 | static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr) | 548 | static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr) |
573 | { | 549 | { |
574 | apic_set_reg(apic, APIC_TASKPRI, tpr); | 550 | kvm_lapic_set_reg(apic, APIC_TASKPRI, tpr); |
575 | apic_update_ppr(apic); | 551 | apic_update_ppr(apic); |
576 | } | 552 | } |
577 | 553 | ||
@@ -668,6 +644,7 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | |||
668 | return false; | 644 | return false; |
669 | } | 645 | } |
670 | } | 646 | } |
647 | EXPORT_SYMBOL_GPL(kvm_apic_match_dest); | ||
671 | 648 | ||
672 | int kvm_vector_to_index(u32 vector, u32 dest_vcpus, | 649 | int kvm_vector_to_index(u32 vector, u32 dest_vcpus, |
673 | const unsigned long *bitmap, u32 bitmap_size) | 650 | const unsigned long *bitmap, u32 bitmap_size) |
@@ -921,7 +898,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
921 | 898 | ||
922 | if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) { | 899 | if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) { |
923 | if (trig_mode) | 900 | if (trig_mode) |
924 | apic_set_vector(vector, apic->regs + APIC_TMR); | 901 | kvm_lapic_set_vector(vector, apic->regs + APIC_TMR); |
925 | else | 902 | else |
926 | apic_clear_vector(vector, apic->regs + APIC_TMR); | 903 | apic_clear_vector(vector, apic->regs + APIC_TMR); |
927 | } | 904 | } |
@@ -929,7 +906,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
929 | if (vcpu->arch.apicv_active) | 906 | if (vcpu->arch.apicv_active) |
930 | kvm_x86_ops->deliver_posted_interrupt(vcpu, vector); | 907 | kvm_x86_ops->deliver_posted_interrupt(vcpu, vector); |
931 | else { | 908 | else { |
932 | apic_set_irr(vector, apic); | 909 | kvm_lapic_set_irr(vector, apic); |
933 | 910 | ||
934 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 911 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
935 | kvm_vcpu_kick(vcpu); | 912 | kvm_vcpu_kick(vcpu); |
@@ -1186,7 +1163,7 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev) | |||
1186 | return container_of(dev, struct kvm_lapic, dev); | 1163 | return container_of(dev, struct kvm_lapic, dev); |
1187 | } | 1164 | } |
1188 | 1165 | ||
1189 | static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len, | 1166 | int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len, |
1190 | void *data) | 1167 | void *data) |
1191 | { | 1168 | { |
1192 | unsigned char alignment = offset & 0xf; | 1169 | unsigned char alignment = offset & 0xf; |
@@ -1223,6 +1200,7 @@ static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len, | |||
1223 | } | 1200 | } |
1224 | return 0; | 1201 | return 0; |
1225 | } | 1202 | } |
1203 | EXPORT_SYMBOL_GPL(kvm_lapic_reg_read); | ||
1226 | 1204 | ||
1227 | static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) | 1205 | static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) |
1228 | { | 1206 | { |
@@ -1240,7 +1218,7 @@ static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this, | |||
1240 | if (!apic_mmio_in_range(apic, address)) | 1218 | if (!apic_mmio_in_range(apic, address)) |
1241 | return -EOPNOTSUPP; | 1219 | return -EOPNOTSUPP; |
1242 | 1220 | ||
1243 | apic_reg_read(apic, offset, len, data); | 1221 | kvm_lapic_reg_read(apic, offset, len, data); |
1244 | 1222 | ||
1245 | return 0; | 1223 | return 0; |
1246 | } | 1224 | } |
@@ -1425,7 +1403,7 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) | |||
1425 | } | 1403 | } |
1426 | } | 1404 | } |
1427 | 1405 | ||
1428 | static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | 1406 | int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) |
1429 | { | 1407 | { |
1430 | int ret = 0; | 1408 | int ret = 0; |
1431 | 1409 | ||
@@ -1457,7 +1435,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1457 | 1435 | ||
1458 | case APIC_DFR: | 1436 | case APIC_DFR: |
1459 | if (!apic_x2apic_mode(apic)) { | 1437 | if (!apic_x2apic_mode(apic)) { |
1460 | apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF); | 1438 | kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF); |
1461 | recalculate_apic_map(apic->vcpu->kvm); | 1439 | recalculate_apic_map(apic->vcpu->kvm); |
1462 | } else | 1440 | } else |
1463 | ret = 1; | 1441 | ret = 1; |
@@ -1472,10 +1450,10 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1472 | int i; | 1450 | int i; |
1473 | u32 lvt_val; | 1451 | u32 lvt_val; |
1474 | 1452 | ||
1475 | for (i = 0; i < APIC_LVT_NUM; i++) { | 1453 | for (i = 0; i < KVM_APIC_LVT_NUM; i++) { |
1476 | lvt_val = kvm_apic_get_reg(apic, | 1454 | lvt_val = kvm_apic_get_reg(apic, |
1477 | APIC_LVTT + 0x10 * i); | 1455 | APIC_LVTT + 0x10 * i); |
1478 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, | 1456 | kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, |
1479 | lvt_val | APIC_LVT_MASKED); | 1457 | lvt_val | APIC_LVT_MASKED); |
1480 | } | 1458 | } |
1481 | apic_update_lvtt(apic); | 1459 | apic_update_lvtt(apic); |
@@ -1486,14 +1464,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1486 | } | 1464 | } |
1487 | case APIC_ICR: | 1465 | case APIC_ICR: |
1488 | /* No delay here, so we always clear the pending bit */ | 1466 | /* No delay here, so we always clear the pending bit */ |
1489 | apic_set_reg(apic, APIC_ICR, val & ~(1 << 12)); | 1467 | kvm_lapic_set_reg(apic, APIC_ICR, val & ~(1 << 12)); |
1490 | apic_send_ipi(apic); | 1468 | apic_send_ipi(apic); |
1491 | break; | 1469 | break; |
1492 | 1470 | ||
1493 | case APIC_ICR2: | 1471 | case APIC_ICR2: |
1494 | if (!apic_x2apic_mode(apic)) | 1472 | if (!apic_x2apic_mode(apic)) |
1495 | val &= 0xff000000; | 1473 | val &= 0xff000000; |
1496 | apic_set_reg(apic, APIC_ICR2, val); | 1474 | kvm_lapic_set_reg(apic, APIC_ICR2, val); |
1497 | break; | 1475 | break; |
1498 | 1476 | ||
1499 | case APIC_LVT0: | 1477 | case APIC_LVT0: |
@@ -1507,7 +1485,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1507 | val |= APIC_LVT_MASKED; | 1485 | val |= APIC_LVT_MASKED; |
1508 | 1486 | ||
1509 | val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4]; | 1487 | val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4]; |
1510 | apic_set_reg(apic, reg, val); | 1488 | kvm_lapic_set_reg(apic, reg, val); |
1511 | 1489 | ||
1512 | break; | 1490 | break; |
1513 | 1491 | ||
@@ -1515,7 +1493,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1515 | if (!kvm_apic_sw_enabled(apic)) | 1493 | if (!kvm_apic_sw_enabled(apic)) |
1516 | val |= APIC_LVT_MASKED; | 1494 | val |= APIC_LVT_MASKED; |
1517 | val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); | 1495 | val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); |
1518 | apic_set_reg(apic, APIC_LVTT, val); | 1496 | kvm_lapic_set_reg(apic, APIC_LVTT, val); |
1519 | apic_update_lvtt(apic); | 1497 | apic_update_lvtt(apic); |
1520 | break; | 1498 | break; |
1521 | 1499 | ||
@@ -1524,14 +1502,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1524 | break; | 1502 | break; |
1525 | 1503 | ||
1526 | hrtimer_cancel(&apic->lapic_timer.timer); | 1504 | hrtimer_cancel(&apic->lapic_timer.timer); |
1527 | apic_set_reg(apic, APIC_TMICT, val); | 1505 | kvm_lapic_set_reg(apic, APIC_TMICT, val); |
1528 | start_apic_timer(apic); | 1506 | start_apic_timer(apic); |
1529 | break; | 1507 | break; |
1530 | 1508 | ||
1531 | case APIC_TDCR: | 1509 | case APIC_TDCR: |
1532 | if (val & 4) | 1510 | if (val & 4) |
1533 | apic_debug("KVM_WRITE:TDCR %x\n", val); | 1511 | apic_debug("KVM_WRITE:TDCR %x\n", val); |
1534 | apic_set_reg(apic, APIC_TDCR, val); | 1512 | kvm_lapic_set_reg(apic, APIC_TDCR, val); |
1535 | update_divide_count(apic); | 1513 | update_divide_count(apic); |
1536 | break; | 1514 | break; |
1537 | 1515 | ||
@@ -1544,7 +1522,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1544 | 1522 | ||
1545 | case APIC_SELF_IPI: | 1523 | case APIC_SELF_IPI: |
1546 | if (apic_x2apic_mode(apic)) { | 1524 | if (apic_x2apic_mode(apic)) { |
1547 | apic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff)); | 1525 | kvm_lapic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff)); |
1548 | } else | 1526 | } else |
1549 | ret = 1; | 1527 | ret = 1; |
1550 | break; | 1528 | break; |
@@ -1556,6 +1534,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1556 | apic_debug("Local APIC Write to read-only register %x\n", reg); | 1534 | apic_debug("Local APIC Write to read-only register %x\n", reg); |
1557 | return ret; | 1535 | return ret; |
1558 | } | 1536 | } |
1537 | EXPORT_SYMBOL_GPL(kvm_lapic_reg_write); | ||
1559 | 1538 | ||
1560 | static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, | 1539 | static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, |
1561 | gpa_t address, int len, const void *data) | 1540 | gpa_t address, int len, const void *data) |
@@ -1585,14 +1564,14 @@ static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, | |||
1585 | apic_debug("%s: offset 0x%x with length 0x%x, and value is " | 1564 | apic_debug("%s: offset 0x%x with length 0x%x, and value is " |
1586 | "0x%x\n", __func__, offset, len, val); | 1565 | "0x%x\n", __func__, offset, len, val); |
1587 | 1566 | ||
1588 | apic_reg_write(apic, offset & 0xff0, val); | 1567 | kvm_lapic_reg_write(apic, offset & 0xff0, val); |
1589 | 1568 | ||
1590 | return 0; | 1569 | return 0; |
1591 | } | 1570 | } |
1592 | 1571 | ||
1593 | void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) | 1572 | void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) |
1594 | { | 1573 | { |
1595 | apic_reg_write(vcpu->arch.apic, APIC_EOI, 0); | 1574 | kvm_lapic_reg_write(vcpu->arch.apic, APIC_EOI, 0); |
1596 | } | 1575 | } |
1597 | EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); | 1576 | EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); |
1598 | 1577 | ||
@@ -1604,10 +1583,10 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) | |||
1604 | /* hw has done the conditional check and inst decode */ | 1583 | /* hw has done the conditional check and inst decode */ |
1605 | offset &= 0xff0; | 1584 | offset &= 0xff0; |
1606 | 1585 | ||
1607 | apic_reg_read(vcpu->arch.apic, offset, 4, &val); | 1586 | kvm_lapic_reg_read(vcpu->arch.apic, offset, 4, &val); |
1608 | 1587 | ||
1609 | /* TODO: optimize to just emulate side effect w/o one more write */ | 1588 | /* TODO: optimize to just emulate side effect w/o one more write */ |
1610 | apic_reg_write(vcpu->arch.apic, offset, val); | 1589 | kvm_lapic_reg_write(vcpu->arch.apic, offset, val); |
1611 | } | 1590 | } |
1612 | EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode); | 1591 | EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode); |
1613 | 1592 | ||
@@ -1740,28 +1719,28 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) | |||
1740 | kvm_apic_set_id(apic, vcpu->vcpu_id); | 1719 | kvm_apic_set_id(apic, vcpu->vcpu_id); |
1741 | kvm_apic_set_version(apic->vcpu); | 1720 | kvm_apic_set_version(apic->vcpu); |
1742 | 1721 | ||
1743 | for (i = 0; i < APIC_LVT_NUM; i++) | 1722 | for (i = 0; i < KVM_APIC_LVT_NUM; i++) |
1744 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); | 1723 | kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); |
1745 | apic_update_lvtt(apic); | 1724 | apic_update_lvtt(apic); |
1746 | if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) | 1725 | if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) |
1747 | apic_set_reg(apic, APIC_LVT0, | 1726 | kvm_lapic_set_reg(apic, APIC_LVT0, |
1748 | SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); | 1727 | SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); |
1749 | apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0)); | 1728 | apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0)); |
1750 | 1729 | ||
1751 | apic_set_reg(apic, APIC_DFR, 0xffffffffU); | 1730 | kvm_lapic_set_reg(apic, APIC_DFR, 0xffffffffU); |
1752 | apic_set_spiv(apic, 0xff); | 1731 | apic_set_spiv(apic, 0xff); |
1753 | apic_set_reg(apic, APIC_TASKPRI, 0); | 1732 | kvm_lapic_set_reg(apic, APIC_TASKPRI, 0); |
1754 | if (!apic_x2apic_mode(apic)) | 1733 | if (!apic_x2apic_mode(apic)) |
1755 | kvm_apic_set_ldr(apic, 0); | 1734 | kvm_apic_set_ldr(apic, 0); |
1756 | apic_set_reg(apic, APIC_ESR, 0); | 1735 | kvm_lapic_set_reg(apic, APIC_ESR, 0); |
1757 | apic_set_reg(apic, APIC_ICR, 0); | 1736 | kvm_lapic_set_reg(apic, APIC_ICR, 0); |
1758 | apic_set_reg(apic, APIC_ICR2, 0); | 1737 | kvm_lapic_set_reg(apic, APIC_ICR2, 0); |
1759 | apic_set_reg(apic, APIC_TDCR, 0); | 1738 | kvm_lapic_set_reg(apic, APIC_TDCR, 0); |
1760 | apic_set_reg(apic, APIC_TMICT, 0); | 1739 | kvm_lapic_set_reg(apic, APIC_TMICT, 0); |
1761 | for (i = 0; i < 8; i++) { | 1740 | for (i = 0; i < 8; i++) { |
1762 | apic_set_reg(apic, APIC_IRR + 0x10 * i, 0); | 1741 | kvm_lapic_set_reg(apic, APIC_IRR + 0x10 * i, 0); |
1763 | apic_set_reg(apic, APIC_ISR + 0x10 * i, 0); | 1742 | kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0); |
1764 | apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); | 1743 | kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0); |
1765 | } | 1744 | } |
1766 | apic->irr_pending = vcpu->arch.apicv_active; | 1745 | apic->irr_pending = vcpu->arch.apicv_active; |
1767 | apic->isr_count = vcpu->arch.apicv_active ? 1 : 0; | 1746 | apic->isr_count = vcpu->arch.apicv_active ? 1 : 0; |
@@ -2139,8 +2118,8 @@ int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
2139 | 2118 | ||
2140 | /* if this is ICR write vector before command */ | 2119 | /* if this is ICR write vector before command */ |
2141 | if (reg == APIC_ICR) | 2120 | if (reg == APIC_ICR) |
2142 | apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); | 2121 | kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); |
2143 | return apic_reg_write(apic, reg, (u32)data); | 2122 | return kvm_lapic_reg_write(apic, reg, (u32)data); |
2144 | } | 2123 | } |
2145 | 2124 | ||
2146 | int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) | 2125 | int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) |
@@ -2157,10 +2136,10 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) | |||
2157 | return 1; | 2136 | return 1; |
2158 | } | 2137 | } |
2159 | 2138 | ||
2160 | if (apic_reg_read(apic, reg, 4, &low)) | 2139 | if (kvm_lapic_reg_read(apic, reg, 4, &low)) |
2161 | return 1; | 2140 | return 1; |
2162 | if (reg == APIC_ICR) | 2141 | if (reg == APIC_ICR) |
2163 | apic_reg_read(apic, APIC_ICR2, 4, &high); | 2142 | kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high); |
2164 | 2143 | ||
2165 | *data = (((u64)high) << 32) | low; | 2144 | *data = (((u64)high) << 32) | low; |
2166 | 2145 | ||
@@ -2176,8 +2155,8 @@ int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data) | |||
2176 | 2155 | ||
2177 | /* if this is ICR write vector before command */ | 2156 | /* if this is ICR write vector before command */ |
2178 | if (reg == APIC_ICR) | 2157 | if (reg == APIC_ICR) |
2179 | apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); | 2158 | kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); |
2180 | return apic_reg_write(apic, reg, (u32)data); | 2159 | return kvm_lapic_reg_write(apic, reg, (u32)data); |
2181 | } | 2160 | } |
2182 | 2161 | ||
2183 | int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) | 2162 | int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) |
@@ -2188,10 +2167,10 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) | |||
2188 | if (!lapic_in_kernel(vcpu)) | 2167 | if (!lapic_in_kernel(vcpu)) |
2189 | return 1; | 2168 | return 1; |
2190 | 2169 | ||
2191 | if (apic_reg_read(apic, reg, 4, &low)) | 2170 | if (kvm_lapic_reg_read(apic, reg, 4, &low)) |
2192 | return 1; | 2171 | return 1; |
2193 | if (reg == APIC_ICR) | 2172 | if (reg == APIC_ICR) |
2194 | apic_reg_read(apic, APIC_ICR2, 4, &high); | 2173 | kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high); |
2195 | 2174 | ||
2196 | *data = (((u64)high) << 32) | low; | 2175 | *data = (((u64)high) << 32) | low; |
2197 | 2176 | ||
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index f71183e502ee..a70cb62933b9 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #define KVM_APIC_INIT 0 | 8 | #define KVM_APIC_INIT 0 |
9 | #define KVM_APIC_SIPI 1 | 9 | #define KVM_APIC_SIPI 1 |
10 | #define KVM_APIC_LVT_NUM 6 | ||
10 | 11 | ||
11 | struct kvm_timer { | 12 | struct kvm_timer { |
12 | struct hrtimer timer; | 13 | struct hrtimer timer; |
@@ -59,6 +60,11 @@ void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu); | |||
59 | void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value); | 60 | void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value); |
60 | u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); | 61 | u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); |
61 | void kvm_apic_set_version(struct kvm_vcpu *vcpu); | 62 | void kvm_apic_set_version(struct kvm_vcpu *vcpu); |
63 | int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val); | ||
64 | int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len, | ||
65 | void *data); | ||
66 | bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | ||
67 | int short_hand, unsigned int dest, int dest_mode); | ||
62 | 68 | ||
63 | void __kvm_apic_update_irr(u32 *pir, void *regs); | 69 | void __kvm_apic_update_irr(u32 *pir, void *regs); |
64 | void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir); | 70 | void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir); |
@@ -99,11 +105,34 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) | |||
99 | int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); | 105 | int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); |
100 | void kvm_lapic_init(void); | 106 | void kvm_lapic_init(void); |
101 | 107 | ||
108 | #define VEC_POS(v) ((v) & (32 - 1)) | ||
109 | #define REG_POS(v) (((v) >> 5) << 4) | ||
110 | |||
111 | static inline void kvm_lapic_set_vector(int vec, void *bitmap) | ||
112 | { | ||
113 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | ||
114 | } | ||
115 | |||
116 | static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic) | ||
117 | { | ||
118 | kvm_lapic_set_vector(vec, apic->regs + APIC_IRR); | ||
119 | /* | ||
120 | * irr_pending must be true if any interrupt is pending; set it after | ||
121 | * APIC_IRR to avoid race with apic_clear_irr | ||
122 | */ | ||
123 | apic->irr_pending = true; | ||
124 | } | ||
125 | |||
102 | static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) | 126 | static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) |
103 | { | 127 | { |
104 | return *((u32 *) (apic->regs + reg_off)); | 128 | return *((u32 *) (apic->regs + reg_off)); |
105 | } | 129 | } |
106 | 130 | ||
131 | static inline void kvm_lapic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val) | ||
132 | { | ||
133 | *((u32 *) (apic->regs + reg_off)) = val; | ||
134 | } | ||
135 | |||
107 | extern struct static_key kvm_no_apic_vcpu; | 136 | extern struct static_key kvm_no_apic_vcpu; |
108 | 137 | ||
109 | static inline bool lapic_in_kernel(struct kvm_vcpu *vcpu) | 138 | static inline bool lapic_in_kernel(struct kvm_vcpu *vcpu) |