32
32
#include <asm/current.h>
33
33
#include <asm/apicdef.h>
34
34
#include <asm/atomic.h>
35
+ #include <asm/apicdef.h>
35
36
#include "kvm_cache_regs.h"
36
37
#include "irq.h"
37
38
#include "trace.h"
@@ -158,6 +159,11 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu)
158
159
apic_set_reg (apic , APIC_LVR , v );
159
160
}
160
161
162
+ static inline int apic_x2apic_mode (struct kvm_lapic * apic )
163
+ {
164
+ return apic -> vcpu -> arch .apic_base & X2APIC_ENABLE ;
165
+ }
166
+
161
167
static unsigned int apic_lvt_mask [APIC_LVT_NUM ] = {
162
168
LVT_MASK | APIC_LVT_TIMER_PERIODIC , /* LVTT */
163
169
LVT_MASK | APIC_MODE_MASK , /* LVTTHMR */
@@ -284,7 +290,12 @@ int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
284
290
int kvm_apic_match_logical_addr (struct kvm_lapic * apic , u8 mda )
285
291
{
286
292
int result = 0 ;
287
- u8 logical_id ;
293
+ u32 logical_id ;
294
+
295
+ if (apic_x2apic_mode (apic )) {
296
+ logical_id = apic_get_reg (apic , APIC_LDR );
297
+ return logical_id & mda ;
298
+ }
288
299
289
300
logical_id = GET_APIC_LOGICAL_ID (apic_get_reg (apic , APIC_LDR ));
290
301
@@ -477,7 +488,10 @@ static void apic_send_ipi(struct kvm_lapic *apic)
477
488
irq .level = icr_low & APIC_INT_ASSERT ;
478
489
irq .trig_mode = icr_low & APIC_INT_LEVELTRIG ;
479
490
irq .shorthand = icr_low & APIC_SHORT_MASK ;
480
- irq .dest_id = GET_APIC_DEST_FIELD (icr_high );
491
+ if (apic_x2apic_mode (apic ))
492
+ irq .dest_id = icr_high ;
493
+ else
494
+ irq .dest_id = GET_APIC_DEST_FIELD (icr_high );
481
495
482
496
apic_debug ("icr_high 0x%x, icr_low 0x%x, "
483
497
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
@@ -538,6 +552,12 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
538
552
return 0 ;
539
553
540
554
switch (offset ) {
555
+ case APIC_ID :
556
+ if (apic_x2apic_mode (apic ))
557
+ val = kvm_apic_id (apic );
558
+ else
559
+ val = kvm_apic_id (apic ) << 24 ;
560
+ break ;
541
561
case APIC_ARBPRI :
542
562
printk (KERN_WARNING "Access APIC ARBPRI register "
543
563
"which is for P6\n" );
@@ -564,28 +584,26 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev)
564
584
return container_of (dev , struct kvm_lapic , dev );
565
585
}
566
586
567
- static int apic_mmio_in_range (struct kvm_lapic * apic , gpa_t addr )
568
- {
569
- return apic_hw_enabled (apic ) &&
570
- addr >= apic -> base_address &&
571
- addr < apic -> base_address + LAPIC_MMIO_LENGTH ;
572
- }
573
-
574
- static int apic_mmio_read (struct kvm_io_device * this ,
575
- gpa_t address , int len , void * data )
587
+ static int apic_reg_read (struct kvm_lapic * apic , u32 offset , int len ,
588
+ void * data )
576
589
{
577
- struct kvm_lapic * apic = to_lapic (this );
578
- unsigned int offset = address - apic -> base_address ;
579
590
unsigned char alignment = offset & 0xf ;
580
591
u32 result ;
581
- if (! apic_mmio_in_range ( apic , address ))
582
- return - EOPNOTSUPP ;
592
+ /* this bitmask has a bit cleared for each reserver register */
593
+ static const u64 rmask = 0x43ff01ffffffe70cULL ;
583
594
584
595
if ((alignment + len ) > 4 ) {
585
- printk (KERN_ERR "KVM_APIC_READ: alignment error %lx %d" ,
586
- ( unsigned long ) address , len );
587
- return 0 ;
596
+ printk (KERN_ERR "KVM_APIC_READ: alignment error %x %d\n " ,
597
+ offset , len );
598
+ return 1 ;
588
599
}
600
+
601
+ if (offset > 0x3f0 || !(rmask & (1ULL << (offset >> 4 )))) {
602
+ printk (KERN_ERR "KVM_APIC_READ: read reserved register %x\n" ,
603
+ offset );
604
+ return 1 ;
605
+ }
606
+
589
607
result = __apic_read (apic , offset & ~0xf );
590
608
591
609
trace_kvm_apic_read (offset , result );
@@ -604,6 +622,27 @@ static int apic_mmio_read(struct kvm_io_device *this,
604
622
return 0 ;
605
623
}
606
624
625
+ static int apic_mmio_in_range (struct kvm_lapic * apic , gpa_t addr )
626
+ {
627
+ return apic_hw_enabled (apic ) &&
628
+ addr >= apic -> base_address &&
629
+ addr < apic -> base_address + LAPIC_MMIO_LENGTH ;
630
+ }
631
+
632
+ static int apic_mmio_read (struct kvm_io_device * this ,
633
+ gpa_t address , int len , void * data )
634
+ {
635
+ struct kvm_lapic * apic = to_lapic (this );
636
+ u32 offset = address - apic -> base_address ;
637
+
638
+ if (!apic_mmio_in_range (apic , address ))
639
+ return - EOPNOTSUPP ;
640
+
641
+ apic_reg_read (apic , offset , len , data );
642
+
643
+ return 0 ;
644
+ }
645
+
607
646
static void update_divide_count (struct kvm_lapic * apic )
608
647
{
609
648
u32 tmp1 , tmp2 , tdcr ;
@@ -657,42 +696,18 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
657
696
apic -> vcpu -> kvm -> arch .vapics_in_nmi_mode -- ;
658
697
}
659
698
660
- static int apic_mmio_write (struct kvm_io_device * this ,
661
- gpa_t address , int len , const void * data )
699
+ static int apic_reg_write (struct kvm_lapic * apic , u32 reg , u32 val )
662
700
{
663
- struct kvm_lapic * apic = to_lapic (this );
664
- unsigned int offset = address - apic -> base_address ;
665
- unsigned char alignment = offset & 0xf ;
666
- u32 val ;
667
- if (!apic_mmio_in_range (apic , address ))
668
- return - EOPNOTSUPP ;
669
-
670
- /*
671
- * APIC register must be aligned on 128-bits boundary.
672
- * 32/64/128 bits registers must be accessed thru 32 bits.
673
- * Refer SDM 8.4.1
674
- */
675
- if (len != 4 || alignment ) {
676
- /* Don't shout loud, $infamous_os would cause only noise. */
677
- apic_debug ("apic write: bad size=%d %lx\n" ,
678
- len , (long )address );
679
- return 0 ;
680
- }
681
-
682
- val = * (u32 * ) data ;
701
+ int ret = 0 ;
683
702
684
- /* too common printing */
685
- if (offset != APIC_EOI )
686
- apic_debug ("%s: offset 0x%x with length 0x%x, and value is "
687
- "0x%x\n" , __func__ , offset , len , val );
703
+ trace_kvm_apic_write (reg , val );
688
704
689
- offset &= 0xff0 ;
690
-
691
- trace_kvm_apic_write (offset , val );
692
-
693
- switch (offset ) {
705
+ switch (reg ) {
694
706
case APIC_ID : /* Local APIC ID */
695
- apic_set_reg (apic , APIC_ID , val );
707
+ if (!apic_x2apic_mode (apic ))
708
+ apic_set_reg (apic , APIC_ID , val );
709
+ else
710
+ ret = 1 ;
696
711
break ;
697
712
698
713
case APIC_TASKPRI :
@@ -705,11 +720,17 @@ static int apic_mmio_write(struct kvm_io_device *this,
705
720
break ;
706
721
707
722
case APIC_LDR :
708
- apic_set_reg (apic , APIC_LDR , val & APIC_LDR_MASK );
723
+ if (!apic_x2apic_mode (apic ))
724
+ apic_set_reg (apic , APIC_LDR , val & APIC_LDR_MASK );
725
+ else
726
+ ret = 1 ;
709
727
break ;
710
728
711
729
case APIC_DFR :
712
- apic_set_reg (apic , APIC_DFR , val | 0x0FFFFFFF );
730
+ if (!apic_x2apic_mode (apic ))
731
+ apic_set_reg (apic , APIC_DFR , val | 0x0FFFFFFF );
732
+ else
733
+ ret = 1 ;
713
734
break ;
714
735
715
736
case APIC_SPIV : {
@@ -739,7 +760,9 @@ static int apic_mmio_write(struct kvm_io_device *this,
739
760
break ;
740
761
741
762
case APIC_ICR2 :
742
- apic_set_reg (apic , APIC_ICR2 , val & 0xff000000 );
763
+ if (!apic_x2apic_mode (apic ))
764
+ val &= 0xff000000 ;
765
+ apic_set_reg (apic , APIC_ICR2 , val );
743
766
break ;
744
767
745
768
case APIC_LVT0 :
@@ -753,16 +776,16 @@ static int apic_mmio_write(struct kvm_io_device *this,
753
776
if (!apic_sw_enabled (apic ))
754
777
val |= APIC_LVT_MASKED ;
755
778
756
- val &= apic_lvt_mask [(offset - APIC_LVTT ) >> 4 ];
757
- apic_set_reg (apic , offset , val );
779
+ val &= apic_lvt_mask [(reg - APIC_LVTT ) >> 4 ];
780
+ apic_set_reg (apic , reg , val );
758
781
759
782
break ;
760
783
761
784
case APIC_TMICT :
762
785
hrtimer_cancel (& apic -> lapic_timer .timer );
763
786
apic_set_reg (apic , APIC_TMICT , val );
764
787
start_apic_timer (apic );
765
- return 0 ;
788
+ break ;
766
789
767
790
case APIC_TDCR :
768
791
if (val & 4 )
@@ -771,11 +794,58 @@ static int apic_mmio_write(struct kvm_io_device *this,
771
794
update_divide_count (apic );
772
795
break ;
773
796
797
+ case APIC_ESR :
798
+ if (apic_x2apic_mode (apic ) && val != 0 ) {
799
+ printk (KERN_ERR "KVM_WRITE:ESR not zero %x\n" , val );
800
+ ret = 1 ;
801
+ }
802
+ break ;
803
+
804
+ case APIC_SELF_IPI :
805
+ if (apic_x2apic_mode (apic )) {
806
+ apic_reg_write (apic , APIC_ICR , 0x40000 | (val & 0xff ));
807
+ } else
808
+ ret = 1 ;
809
+ break ;
774
810
default :
775
- apic_debug ("Local APIC Write to read-only register %x\n" ,
776
- offset );
811
+ ret = 1 ;
777
812
break ;
778
813
}
814
+ if (ret )
815
+ apic_debug ("Local APIC Write to read-only register %x\n" , reg );
816
+ return ret ;
817
+ }
818
+
819
+ static int apic_mmio_write (struct kvm_io_device * this ,
820
+ gpa_t address , int len , const void * data )
821
+ {
822
+ struct kvm_lapic * apic = to_lapic (this );
823
+ unsigned int offset = address - apic -> base_address ;
824
+ u32 val ;
825
+
826
+ if (!apic_mmio_in_range (apic , address ))
827
+ return - EOPNOTSUPP ;
828
+
829
+ /*
830
+ * APIC register must be aligned on 128-bits boundary.
831
+ * 32/64/128 bits registers must be accessed thru 32 bits.
832
+ * Refer SDM 8.4.1
833
+ */
834
+ if (len != 4 || (offset & 0xf )) {
835
+ /* Don't shout loud, $infamous_os would cause only noise. */
836
+ apic_debug ("apic write: bad size=%d %lx\n" , len , (long )address );
837
+ return ;
838
+ }
839
+
840
+ val = * (u32 * )data ;
841
+
842
+ /* too common printing */
843
+ if (offset != APIC_EOI )
844
+ apic_debug ("%s: offset 0x%x with length 0x%x, and value is "
845
+ "0x%x\n" , __func__ , offset , len , val );
846
+
847
+ apic_reg_write (apic , offset & 0xff0 , val );
848
+
779
849
return 0 ;
780
850
}
781
851
@@ -834,6 +904,11 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
834
904
value &= ~MSR_IA32_APICBASE_BSP ;
835
905
836
906
vcpu -> arch .apic_base = value ;
907
+ if (apic_x2apic_mode (apic )) {
908
+ u32 id = kvm_apic_id (apic );
909
+ u32 ldr = ((id & ~0xf ) << 16 ) | (1 << (id & 0xf ));
910
+ apic_set_reg (apic , APIC_LDR , ldr );
911
+ }
837
912
apic -> base_address = apic -> vcpu -> arch .apic_base &
838
913
MSR_IA32_APICBASE_BASE ;
839
914
@@ -1130,3 +1205,35 @@ void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
1130
1205
1131
1206
vcpu -> arch .apic -> vapic_addr = vapic_addr ;
1132
1207
}
1208
+
1209
+ int kvm_x2apic_msr_write (struct kvm_vcpu * vcpu , u32 msr , u64 data )
1210
+ {
1211
+ struct kvm_lapic * apic = vcpu -> arch .apic ;
1212
+ u32 reg = (msr - APIC_BASE_MSR ) << 4 ;
1213
+
1214
+ if (!irqchip_in_kernel (vcpu -> kvm ) || !apic_x2apic_mode (apic ))
1215
+ return 1 ;
1216
+
1217
+ /* if this is ICR write vector before command */
1218
+ if (msr == 0x830 )
1219
+ apic_reg_write (apic , APIC_ICR2 , (u32 )(data >> 32 ));
1220
+ return apic_reg_write (apic , reg , (u32 )data );
1221
+ }
1222
+
1223
+ int kvm_x2apic_msr_read (struct kvm_vcpu * vcpu , u32 msr , u64 * data )
1224
+ {
1225
+ struct kvm_lapic * apic = vcpu -> arch .apic ;
1226
+ u32 reg = (msr - APIC_BASE_MSR ) << 4 , low , high = 0 ;
1227
+
1228
+ if (!irqchip_in_kernel (vcpu -> kvm ) || !apic_x2apic_mode (apic ))
1229
+ return 1 ;
1230
+
1231
+ if (apic_reg_read (apic , reg , 4 , & low ))
1232
+ return 1 ;
1233
+ if (msr == 0x830 )
1234
+ apic_reg_read (apic , APIC_ICR2 , 4 , & high );
1235
+
1236
+ * data = (((u64 )high ) << 32 ) | low ;
1237
+
1238
+ return 0 ;
1239
+ }
0 commit comments