diff options
Diffstat (limited to 'arch/i386/kernel/vmi.c')
-rw-r--r-- | arch/i386/kernel/vmi.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c index a94d64b10f75..bb5a7abf949c 100644 --- a/arch/i386/kernel/vmi.c +++ b/arch/i386/kernel/vmi.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/apic.h> | 34 | #include <asm/apic.h> |
35 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
36 | #include <asm/timer.h> | 36 | #include <asm/timer.h> |
37 | #include <asm/vmi_time.h> | ||
37 | 38 | ||
38 | /* Convenient for calling VMI functions indirectly in the ROM */ | 39 | /* Convenient for calling VMI functions indirectly in the ROM */ |
39 | typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void); | 40 | typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void); |
@@ -67,6 +68,7 @@ struct { | |||
67 | void (*set_linear_mapping)(int, u32, u32, u32); | 68 | void (*set_linear_mapping)(int, u32, u32, u32); |
68 | void (*flush_tlb)(int); | 69 | void (*flush_tlb)(int); |
69 | void (*set_initial_ap_state)(int, int); | 70 | void (*set_initial_ap_state)(int, int); |
71 | void (*halt)(void); | ||
70 | } vmi_ops; | 72 | } vmi_ops; |
71 | 73 | ||
72 | /* XXX move this to alternative.h */ | 74 | /* XXX move this to alternative.h */ |
@@ -252,6 +254,19 @@ static void vmi_nop(void) | |||
252 | { | 254 | { |
253 | } | 255 | } |
254 | 256 | ||
257 | /* For NO_IDLE_HZ, we stop the clock when halting the kernel */ | ||
258 | #ifdef CONFIG_NO_IDLE_HZ | ||
259 | static fastcall void vmi_safe_halt(void) | ||
260 | { | ||
261 | int idle = vmi_stop_hz_timer(); | ||
262 | vmi_ops.halt(); | ||
263 | if (idle) { | ||
264 | local_irq_disable(); | ||
265 | vmi_account_time_restart_hz_timer(); | ||
266 | local_irq_enable(); | ||
267 | } | ||
268 | } | ||
269 | #endif | ||
255 | 270 | ||
256 | #ifdef CONFIG_DEBUG_PAGE_TYPE | 271 | #ifdef CONFIG_DEBUG_PAGE_TYPE |
257 | 272 | ||
@@ -727,7 +742,12 @@ static inline int __init activate_vmi(void) | |||
727 | (char *)paravirt_ops.save_fl); | 742 | (char *)paravirt_ops.save_fl); |
728 | patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE], | 743 | patch_offset(&irq_save_disable_callout[IRQ_PATCH_DISABLE], |
729 | (char *)paravirt_ops.irq_disable); | 744 | (char *)paravirt_ops.irq_disable); |
745 | #ifndef CONFIG_NO_IDLE_HZ | ||
730 | para_fill(safe_halt, Halt); | 746 | para_fill(safe_halt, Halt); |
747 | #else | ||
748 | vmi_ops.halt = vmi_get_function(VMI_CALL_Halt); | ||
749 | paravirt_ops.safe_halt = vmi_safe_halt; | ||
750 | #endif | ||
731 | para_fill(wbinvd, WBINVD); | 751 | para_fill(wbinvd, WBINVD); |
732 | /* paravirt_ops.read_msr = vmi_rdmsr */ | 752 | /* paravirt_ops.read_msr = vmi_rdmsr */ |
733 | /* paravirt_ops.write_msr = vmi_wrmsr */ | 753 | /* paravirt_ops.write_msr = vmi_wrmsr */ |
@@ -838,6 +858,31 @@ static inline int __init activate_vmi(void) | |||
838 | #endif | 858 | #endif |
839 | 859 | ||
840 | /* | 860 | /* |
861 | * Check for VMI timer functionality by probing for a cycle frequency method | ||
862 | */ | ||
863 | reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency); | ||
864 | if (rel->type != VMI_RELOCATION_NONE) { | ||
865 | vmi_timer_ops.get_cycle_frequency = (void *)rel->eip; | ||
866 | vmi_timer_ops.get_cycle_counter = | ||
867 | vmi_get_function(VMI_CALL_GetCycleCounter); | ||
868 | vmi_timer_ops.get_wallclock = | ||
869 | vmi_get_function(VMI_CALL_GetWallclockTime); | ||
870 | vmi_timer_ops.wallclock_updated = | ||
871 | vmi_get_function(VMI_CALL_WallclockUpdated); | ||
872 | vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm); | ||
873 | vmi_timer_ops.cancel_alarm = | ||
874 | vmi_get_function(VMI_CALL_CancelAlarm); | ||
875 | paravirt_ops.time_init = vmi_time_init; | ||
876 | paravirt_ops.get_wallclock = vmi_get_wallclock; | ||
877 | paravirt_ops.set_wallclock = vmi_set_wallclock; | ||
878 | #ifdef CONFIG_X86_LOCAL_APIC | ||
879 | paravirt_ops.setup_boot_clock = vmi_timer_setup_boot_alarm; | ||
880 | paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm; | ||
881 | #endif | ||
882 | custom_sched_clock = vmi_sched_clock; | ||
883 | } | ||
884 | |||
885 | /* | ||
841 | * Alternative instruction rewriting doesn't happen soon enough | 886 | * Alternative instruction rewriting doesn't happen soon enough |
842 | * to convert VMI_IRET to a call instead of a jump; so we have | 887 | * to convert VMI_IRET to a call instead of a jump; so we have |
843 | * to do this before IRQs get reenabled. Fortunately, it is | 888 | * to do this before IRQs get reenabled. Fortunately, it is |