Index: linux-2.6.33-source/arch/x86/lib/Makefile =================================================================== --- linux-2.6.33-source.orig/arch/x86/lib/Makefile +++ linux-2.6.33-source/arch/x86/lib/Makefile @@ -16,7 +16,11 @@ obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o +ifdef CONFIG_COOPERATIVE +lib-y := delay_cooperative.o +else lib-y := delay.o +endif lib-y += thunk_$(BITS).o lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o Index: linux-2.6.33-source/arch/x86/kernel/timer_cooperative.c =================================================================== --- /dev/null +++ linux-2.6.33-source/arch/x86/kernel/timer_cooperative.c @@ -0,0 +1,142 @@ +/* + * Cooperative mode timer. + * + * Dan Aloni , 2003-2004 (C). + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define CO_CLOCK_SHIFT 20 + +/* FSEC = 10^-15 + NSEC = 10^-9 */ +#define FSEC_PER_NSEC 1000000 + +/* 100Hz is fix from damons 10ms setup */ +#define CO_HOST_HZ 100 + +unsigned int cpu_khz; +EXPORT_SYMBOL(cpu_khz); + +/* + * Functions copied from time.c + */ +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + + return pc; +} +EXPORT_SYMBOL(profile_pc); + +/* Read system date and clock at startup */ +void read_persistent_clock(struct timespec *ts) +{ + unsigned long flags; + + co_passage_page_assert_valid(); + + co_passage_page_acquire(&flags); + co_passage_page->operation = CO_OPERATION_GET_TIME; + co_switch_wrapper(); + ts->tv_sec = co_passage_page->params[0]; + ts->tv_nsec = 0; + co_passage_page_release(flags); +} + +/* need by ntp.c */ +int update_persistent_clock(struct timespec now) +{ + return 0; +} + + +/* + * Clock source related code, based on arch/arm/mach-omap1/time.c + */ + +static cycle_t query_host_highprec_time(struct clocksource *cs) +{ + unsigned long flags; + unsigned long long this_time; + + co_passage_page_assert_valid(); + + co_passage_page_acquire(&flags); + co_passage_page->operation = CO_OPERATION_GET_HIGH_PREC_TIME; + co_switch_wrapper(); + this_time = *(unsigned long long *)(&co_passage_page->params[0]); + co_passage_page_release(flags); + + return this_time; +} + +static struct clocksource co_clocksource = { + .name = "cooperative", + .rating = 450, + .read = query_host_highprec_time, + .mask = CLOCKSOURCE_MASK(64), + .shift = CO_CLOCK_SHIFT, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + + +static void co_timer_setup(enum clock_event_mode mode, + struct clock_event_device *evt) +{ +} + +struct clock_event_device co_clockevent = { + .name = "clock", + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = co_timer_setup, + .shift = CO_CLOCK_SHIFT, +}; + +static irqreturn_t co_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &co_clockevent; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction co_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = co_timer_interrupt, +}; + +extern void (*late_time_init)(void); +static void __init co_register_timer(void) +{ + setup_irq(TIMER_IRQ, &co_timer_irq); +} + +void __init time_init(void) +{ + u64 tmp; + + tmp = (u64)CO_HOST_HZ << CO_CLOCK_SHIFT; + do_div(tmp, FSEC_PER_NSEC); + co_clockevent.mult = (u32)tmp; + + co_clocksource.mult = clocksource_hz2mult(CO_HOST_HZ, CO_CLOCK_SHIFT); + co_clockevent.cpumask = cpumask_of(0); + + clockevents_register_device(&co_clockevent); + late_time_init = co_register_timer; + + cpu_khz = co_boot_params.co_cpu_khz; +} Index: linux-2.6.33-source/arch/x86/include/asm/delay.h =================================================================== --- linux-2.6.33-source.orig/arch/x86/include/asm/delay.h +++ linux-2.6.33-source/arch/x86/include/asm/delay.h @@ -26,6 +26,8 @@ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ __ndelay(n)) +#ifndef CONFIG_COOPERATIVE void use_tsc_delay(void); +#endif #endif /* _ASM_X86_DELAY_H */ Index: linux-2.6.33-source/arch/x86/include/asm/timex.h =================================================================== --- linux-2.6.33-source.orig/arch/x86/include/asm/timex.h +++ linux-2.6.33-source/arch/x86/include/asm/timex.h @@ -7,6 +7,8 @@ /* Assume we use the PIT time source for the clock tick */ #define CLOCK_TICK_RATE PIT_TICK_RATE +#ifndef CONFIG_COOPERATIVE #define ARCH_HAS_READ_CURRENT_TIMER +#endif /* !CONFIG_COOPERATIVE */ #endif /* _ASM_X86_TIMEX_H */ Index: linux-2.6.33-source/arch/x86/include/asm/msr.h =================================================================== --- linux-2.6.33-source.orig/arch/x86/include/asm/msr.h +++ linux-2.6.33-source/arch/x86/include/asm/msr.h @@ -113,7 +113,12 @@ return err; } +#ifdef CONFIG_COOPERATIVE +/* FIXME: */ +#define native_read_tsc() 0 +#else extern unsigned long long native_read_tsc(void); +#endif extern int native_rdmsr_safe_regs(u32 regs[8]); extern int native_wrmsr_safe_regs(u32 regs[8]); Index: linux-2.6.33-source/arch/x86/lib/delay_cooperative.c =================================================================== --- /dev/null +++ linux-2.6.33-source/arch/x86/lib/delay_cooperative.c @@ -0,0 +1,44 @@ +/* + * Delay Loops for coLinux + * + * The __delay function is not very precise under coLinux. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +void __delay(unsigned long loops) +{ + struct timespec tv; + + /* + * A bogos delay loop for creating BogoMIPS... + */ + + loops = loops / 0x10000; + while (loops--) + read_persistent_clock(&tv); +} +EXPORT_SYMBOL(__delay); + +void __const_udelay(unsigned long xloops) +{ + int d0; + + xloops *= 4; + asm("mull %%edx" + :"=d" (xloops), "=&a" (d0) + :"1" (xloops), "0" + (cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4))); + + __delay(++xloops); +} +EXPORT_SYMBOL(__const_udelay);