single shot timer interrupts fix
- accidentaly this wasn't part of the SMP merge and the implementation remained uncomplete with the timer keeping ticking periodically - APIC timer is set for a signel shot and restarted everytime it expires. This way we can keep the AP's trully idle - the timer is restarted a little later before leaving to userspace - LAPIC_TIMER_ICR is written before LAPIC_LVTTR so the newest value is used
This commit is contained in:
		
							parent
							
								
									ebbc730fc3
								
							
						
					
					
						commit
						a1eefc013e
					
				| @ -508,14 +508,14 @@ PUBLIC void lapic_set_timer_one_shot(const u32_t usec) | |||||||
| 
 | 
 | ||||||
| 	ticks_per_us = (lapic_bus_freq[cpu] / 1000000) * config_apic_timer_x; | 	ticks_per_us = (lapic_bus_freq[cpu] / 1000000) * config_apic_timer_x; | ||||||
| 
 | 
 | ||||||
|  | 	lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us); | ||||||
|  | 
 | ||||||
| 	lvtt = APIC_TDCR_1; | 	lvtt = APIC_TDCR_1; | ||||||
| 	lapic_write(LAPIC_TIMER_DCR, lvtt); | 	lapic_write(LAPIC_TIMER_DCR, lvtt); | ||||||
| 
 | 
 | ||||||
| 	/* configure timer as one-shot */ | 	/* configure timer as one-shot */ | ||||||
| 	lvtt = APIC_TIMER_INT_VECTOR; | 	lvtt = APIC_TIMER_INT_VECTOR; | ||||||
| 	lapic_write(LAPIC_LVTTR, lvtt); | 	lapic_write(LAPIC_LVTTR, lvtt); | ||||||
| 
 |  | ||||||
| 	lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PUBLIC void lapic_set_timer_periodic(const unsigned freq) | PUBLIC void lapic_set_timer_periodic(const unsigned freq) | ||||||
|  | |||||||
| @ -124,8 +124,8 @@ PUBLIC int init_local_timer(unsigned freq) | |||||||
| 	/* if we know the address, lapic is enabled and we should use it */ | 	/* if we know the address, lapic is enabled and we should use it */ | ||||||
| 	if (lapic_addr) { | 	if (lapic_addr) { | ||||||
| 		unsigned cpu = cpuid; | 		unsigned cpu = cpuid; | ||||||
| 		lapic_set_timer_periodic(freq); |  | ||||||
| 		tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000); | 		tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000); | ||||||
|  | 		lapic_set_timer_one_shot(1000000/system_hz); | ||||||
| 	} else | 	} else | ||||||
| 	{ | 	{ | ||||||
| 		BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n")); | 		BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n")); | ||||||
|  | |||||||
| @ -370,8 +370,6 @@ check_misc_flags: | |||||||
| 	p = arch_finish_switch_to_user(); | 	p = arch_finish_switch_to_user(); | ||||||
| 	assert(!is_zero64(p->p_cpu_time_left)); | 	assert(!is_zero64(p->p_cpu_time_left)); | ||||||
| 
 | 
 | ||||||
| 	restart_local_timer(); |  | ||||||
| 	 |  | ||||||
| 	context_stop(proc_addr(KERNEL)); | 	context_stop(proc_addr(KERNEL)); | ||||||
| 
 | 
 | ||||||
| 	/* If the process isn't the owner of FPU, enable the FPU exception */ | 	/* If the process isn't the owner of FPU, enable the FPU exception */ | ||||||
| @ -389,6 +387,9 @@ check_misc_flags: | |||||||
| #ifdef CONFIG_SMP | #ifdef CONFIG_SMP | ||||||
| 	refresh_tlb(); | 	refresh_tlb(); | ||||||
| #endif | #endif | ||||||
|  | 	 | ||||||
|  | 	restart_local_timer(); | ||||||
|  | 	 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * restore_user_context() carries out the actual mode switch from kernel | 	 * restore_user_context() carries out the actual mode switch from kernel | ||||||
| 	 * to userspace. This function does not return | 	 * to userspace. This function does not return | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tomas Hruby
						Tomas Hruby