Colinux base # TODO: Follow functions would crash under coLinux # arch/x86/mm/init_32.c # kernel_physical_mapping_init(): set_pmd, set_pte # free_init_pages(): set_memory_np, set_memory_rw Index: linux-2.6.26-source/CREDITS =================================================================== --- linux-2.6.26-source.orig/CREDITS +++ linux-2.6.26-source/CREDITS @@ -16,6 +16,13 @@ S: (ask for current address) S: Finland +N: Dan Aloni +E: da-x@colinux.org +W: http://www.colinux.org +D: Cooperative Linux +D: Various kernel patches +S: Israel + N: Dragos Acostachioaie E: dragos@iname.com W: http://www.arbornet.org/~dragos Index: linux-2.6.26-source/Makefile =================================================================== --- linux-2.6.26-source.orig/Makefile +++ linux-2.6.26-source/Makefile @@ -299,7 +299,11 @@ AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld +ifeq ($(GCCTRACE),Y) +CC = $(COLINUX_ROOT)/bin/tracewrapper.py $(CROSS_COMPILE)gcc +else CC = $(CROSS_COMPILE)gcc +endif CPP = $(CC) -E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm Index: linux-2.6.26-source/arch/x86/Kconfig =================================================================== --- linux-2.6.26-source.orig/arch/x86/Kconfig +++ linux-2.6.26-source/arch/x86/Kconfig @@ -69,6 +69,7 @@ config ZONE_DMA def_bool y + depends on !COOPERATIVE config SBUS bool @@ -186,7 +187,7 @@ config X86_BIOS_REBOOT bool - depends on !X86_VISWS && !X86_VOYAGER + depends on !X86_VISWS && !X86_VOYAGER && !COOPERATIVE default y config X86_TRAMPOLINE @@ -204,6 +205,7 @@ config SMP bool "Symmetric multi-processing support" + depends on !COOPERATIVE ---help--- This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -472,6 +474,7 @@ config HPET_TIMER def_bool X86_64 prompt "HPET Timer Support" if X86_32 + depends on !COOPERATIVE help Use the IA-PC HPET (High Precision Event Timer) to manage time in preference to the PIT and RTC, if a HPET is @@ -598,7 +601,7 @@ config X86_UP_APIC bool "Local APIC support on uniprocessors" - depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH) + depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH || COOPERATIVE) help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU @@ -621,6 +624,10 @@ to use it. If you say Y here even though your machine doesn't have an IO-APIC, then the kernel will still run with no slowdown at all. +config X86_UP_COPIC + bool 'Cooperative PIC (COPIC) support' + depends on COOPERATIVE + config X86_LOCAL_APIC def_bool y depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH)) @@ -714,6 +721,7 @@ config I8K tristate "Dell laptop support" + depends on !COOPERATIVE ---help--- This adds a driver to safely access the System Management Mode of the CPU on the Dell Inspiron 8000. The System Management Mode @@ -735,7 +743,7 @@ config X86_REBOOTFIXUPS def_bool n prompt "Enable X86 board specific fixups for reboot" - depends on X86_32 && X86 + depends on X86_32 && X86 && !COOPERATIVE ---help--- This enables chipset and/or board specific fixups to be done in order to get reboot to work correctly. This is only needed on @@ -833,14 +841,14 @@ config HIGHMEM4G bool "4GB" - depends on !X86_NUMAQ + depends on !X86_NUMAQ && !COOPERATIVE help Select this if you have a 32-bit processor and between 1 and 4 gigabytes of physical RAM. config HIGHMEM64G bool "64GB" - depends on !M386 && !M486 + depends on !M386 && !M486 && !COOPERATIVE select X86_PAE help Select this if you have a 32-bit processor and more than 4 @@ -899,7 +907,7 @@ config X86_PAE def_bool n prompt "PAE (Physical Address Extension) Support" - depends on X86_32 && !HIGHMEM4G + depends on X86_32 && !HIGHMEM4G && !COOPERATIVE select RESOURCES_64BIT help PAE is required for NX support, and furthermore enables @@ -1007,7 +1015,7 @@ config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC && !COOPERATIVE) select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 @@ -1058,6 +1066,7 @@ config MTRR bool "MTRR (Memory Type Range Register) support" + depends on !COOPERATIVE ---help--- On Intel P6 family processors (Pentium Pro, Pentium II and later) the Memory Type Range Registers (MTRRs) may be used to control @@ -1173,7 +1182,7 @@ config KEXEC bool "kexec system call" - depends on X86_BIOS_REBOOT + depends on X86_BIOS_REBOOT && !COOPERATIVE help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -1298,6 +1307,17 @@ Say N if you want to disable CPU hotplug and don't need to suspend. +config COOPERATIVE + bool 'Cooperative Mode' + default y + +config COLINUX_STATS + bool 'Cooperative Linux stats' + depends on COOPERATIVE + default y + help + OS switch counters readable in /proc/colinux/stats. + config COMPAT_VDSO def_bool y prompt "Compat VDSO support" @@ -1322,7 +1342,7 @@ depends on NUMA menu "Power management options" - depends on !X86_VOYAGER + depends on !X86_VOYAGER && !COOPERATIVE config ARCH_HIBERNATION_HEADER def_bool y Index: linux-2.6.26-source/arch/x86/Kconfig.cpu =================================================================== --- linux-2.6.26-source.orig/arch/x86/Kconfig.cpu +++ linux-2.6.26-source/arch/x86/Kconfig.cpu @@ -397,7 +397,7 @@ config X86_TSC def_bool y - depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64 + depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ && !COOPERATIVE) || X86_64 # this should be set for all -march=.. options where the compiler # generates cmov. Index: linux-2.6.26-source/arch/x86/kernel/Makefile =================================================================== --- linux-2.6.26-source.orig/arch/x86/kernel/Makefile +++ linux-2.6.26-source/arch/x86/kernel/Makefile @@ -17,16 +17,18 @@ obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o obj-y += traps_$(BITS).o irq_$(BITS).o -obj-y += time_$(BITS).o ioport.o ldt.o -obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o +obj-y += ldt.o +obj-y += setup_$(BITS).o setup.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o -obj-y += bootflag.o e820_$(BITS).o +obj-y += bootflag.o obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o -obj-y += alternative.o i8253.o pci-nommu.o +obj-y += alternative.o pci-nommu.o obj-$(CONFIG_X86_64) += bugs_64.o +ifndef CONFIG_COOPERATIVE obj-y += tsc_$(BITS).o io_delay.o rtc.o +endif obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-y += process.o @@ -40,11 +42,14 @@ obj-y += cpu/ obj-y += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o +obj-$(CONFIG_COOPERATIVE) += reboot_cooperative.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o +ifndef CONFIG_COOPERATIVE obj-$(CONFIG_PCI) += early-quirks.o +endif apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o @@ -61,7 +66,9 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit_32.o +ifndef CONFIG_COOPERATIVE obj-y += vsmp_64.o +endif obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_MODULES) += module_$(BITS).o obj-$(CONFIG_ACPI_SRAT) += srat_32.o @@ -104,3 +111,15 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o endif + +### +# coLinux specific files +ifdef CONFIG_COOPERATIVE +obj-y += cooperative.o +obj-y += timer_cooperative.o +obj-y += ioport_cooperative.o i8259_cooperative.o +else +obj-y += ioport.o i8253.o i8259_$(BITS).o +obj-y += time_$(BITS).o +obj-y += e820_$(BITS).o +endif Index: linux-2.6.26-source/arch/x86/kernel/cooperative.c =================================================================== --- /dev/null +++ linux-2.6.26-source/arch/x86/kernel/cooperative.c @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +CO_TRACE_STOP; + +int co_passage_page_holding_count = 0; +bool co_host_fpu_saved = 0; +char co_host_fpu[0x200] __attribute__ ((__aligned__(16))); + +static void __init co_early_cpu_init(void) +{ + /* + * On the first switch to Linux we must set up a valid TR because + * the passage page code assumes such one exists. This is basically + * copied code from cpu_init(). + * + * P.S this is protected by CO_TRACE_STOP so that we don't + * have a monitor context switch. + */ + int cpu = smp_processor_id(); + struct task_struct *curr = current; + struct tss_struct * t = &per_cpu(init_tss, cpu); + struct thread_struct *thread = &curr->thread; + struct desc_struct *gdt = get_cpu_gdt_table(cpu); + + /* + * Initialize the per-CPU GDT with the boot GDT, + * and set up the GDT descriptor: + */ + + load_idt(&idt_descr); + switch_to_new_gdt(); /* Sets GDT and %fs */ + + /* + * Delete NT + */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + + /* + * Set up and load the per-CPU TSS and LDT + */ + atomic_inc(&init_mm.mm_count); + curr->active_mm = &init_mm; + enter_lazy_tlb(&init_mm, curr); + + load_sp0(t, thread); + set_tss_desc(cpu,t); + gdt[GDT_ENTRY_TSS].b &= 0xfffffdff; + + load_TR_desc(); + load_LDT(&init_mm.context); + +#ifdef CONFIG_DOUBLEFAULT + /* Set up doublefault TSS pointer in the GDT */ + __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); + gdt[GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff; +#endif + + /* Clear %gs. */ + asm volatile ("mov %0, %%gs" : : "r" (0)); + + write_cr4(mmu_cr4_features); +} + +/* + * 'co_start' is the first Linux code that runs in the + * coLinux kernel context. It receives %ecx which contains the + * address of the passage page. The passage page code sets %ecx + * to this value in its context restore part. + */ + +void __init co_start(void) +{ + co_early_cpu_init(); + co_start_kernel(); +} + +static void co_switch_wrapper_protected(void) +{ + kernel_fpu_begin(); + + if (co_host_fpu_saved) { + CO_FPU_RESTORE(co_host_fpu); + co_host_fpu_saved = 0; + } + + /* And switch... */ + co_switch(); + + kernel_fpu_end(); +} + +void co_switch_wrapper(void) +{ + /* taken from irq.c: debugging check for stack overflow */ + long esp; + + __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE - 1)); + if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) { + printk("co_switch_wrapper: stack overflow: %ld\n", esp - sizeof(struct thread_info)); + co_terminate(CO_TERMINATE_STACK_OVERFLOW); + } + +#ifdef CONFIG_COLINUX_STATS + co_proc_counts.switches[co_passage_page->operation]++; +#endif + co_switch_wrapper_protected(); +} + +void co_debug(const char *fmt, ...) +{ +} + +#define MAX_TRACE_POINTS 1024 + +typedef struct { + unsigned char *code; + unsigned char original_byte; + int off; +} co_tracepoint_t; + +co_tracepoint_t tracepoints[MAX_TRACE_POINTS]; +static int active_tracepoints = 0; + +void co_kernel_breakpoint(struct pt_regs * regs) +{ + int i = 0; + unsigned char *code = (unsigned char *)regs->ip; + if (!code) + return; + + code--; + for (i=0; i < active_tracepoints; i++) { + if (tracepoints[i].code == code) { + co_debug("TRACEPOINT: %p", code); + break; + } + } + + if (i == active_tracepoints) { + /* Bad, we don't know this tracepoint */ + co_terminate(CO_TERMINATE_INVALID_OPERATION); + return; + } + + *tracepoints[i].code = tracepoints[i].original_byte; + regs->flags |= (1 << 8); /* Enable TF */ + regs->ip = (unsigned long)code; + tracepoints[i].off = 1; +} + +void co_kernel_set_breakpoints(void) +{ + int i; + + for (i=0; i < active_tracepoints; i++) + if (tracepoints[i].code && tracepoints[i].off) { + *tracepoints[i].code = 0xcc; + tracepoints[i].off = 0; + } +} + +int co_kernel_debug(struct pt_regs *regs, long error_code, unsigned int condition) +{ + /* if not a single step trap */ + if (!(condition & DR_STEP)) + return 0; + + /* if userspace */ + if (regs->cs & 3) + return 0; + + regs->flags &= ~(1 << 8); /* Disable TF */ + + co_kernel_set_breakpoints(); + + return 1; +} + +void co_kernel_tracepoint_add(unsigned char *code) +{ + if (active_tracepoints >= MAX_TRACE_POINTS) + return; + + tracepoints[active_tracepoints].code = code; + tracepoints[active_tracepoints].original_byte = *code; + tracepoints[active_tracepoints].off = 0; + active_tracepoints++; + *code = 0xcc; +} + +co_arch_info_t co_arch_info = { + .kernel_cs = __KERNEL_CS, + .kernel_ds = __KERNEL_DS, +}; + +CO_TRACE_CONTINUE; Index: linux-2.6.26-source/arch/x86/kernel/entry_32.S =================================================================== --- linux-2.6.26-source.orig/arch/x86/kernel/entry_32.S +++ linux-2.6.26-source/arch/x86/kernel/entry_32.S @@ -614,7 +614,11 @@ SAVE_ALL TRACE_IRQS_OFF movl %esp,%eax +#ifdef CONFIG_COOPERATIVE + call proxy_interrupt_handler +#else call do_IRQ +#endif jmp ret_from_intr ENDPROC(common_interrupt) CFI_ENDPROC @@ -722,6 +726,9 @@ testl $0x4, %eax # EM (math emulation bit) jne device_not_available_emulate preempt_stop(CLBR_ANY) +#if defined(CONFIG_COOPERATIVE) && !defined(CONFIG_PREEMPT) + DISABLE_INTERRUPTS(CLBR_ANY) +#endif call math_state_restore jmp ret_from_exception device_not_available_emulate: Index: linux-2.6.26-source/arch/x86/kernel/head_32.S =================================================================== --- linux-2.6.26-source.orig/arch/x86/kernel/head_32.S +++ linux-2.6.26-source/arch/x86/kernel/head_32.S @@ -359,6 +359,7 @@ */ call setup_idt +ENTRY(co_arch_start_kernel) checkCPUtype: movl $-1,X86_CPUID # -1 for no CPUID initially @@ -554,6 +555,10 @@ #endif call dump_stack hlt_loop: +#ifdef CONFIG_COOPERATIVE + movl $2,%eax /* CO_TERMINATE_PANIC */ + call co_terminate +#endif hlt jmp hlt_loop @@ -644,7 +649,7 @@ .data ENTRY(stack_start) - .long init_thread_union+THREAD_SIZE + .long init_thread_union+THREAD_SIZE-100 .long __BOOT_DS ready: .byte 0 Index: linux-2.6.26-source/arch/x86/kernel/process_32.c =================================================================== --- linux-2.6.26-source.orig/arch/x86/kernel/process_32.c +++ linux-2.6.26-source/arch/x86/kernel/process_32.c @@ -51,6 +51,7 @@ #endif #include +#include #include #include @@ -177,6 +178,9 @@ if (rcu_pending(cpu)) rcu_check_callbacks(cpu, 0); + if (cooperative_mode_enabled()) + idle = co_idle_processor; + if (!idle) idle = default_idle; Index: linux-2.6.26-source/arch/x86/kernel/setup_32.c =================================================================== --- linux-2.6.26-source.orig/arch/x86/kernel/setup_32.c +++ linux-2.6.26-source/arch/x86/kernel/setup_32.c @@ -48,6 +48,7 @@ #include #include #include +#include #include