colinux64/patch/base-2.6.26.diff
2025-02-13 19:44:47 -07:00

3729 lines
98 KiB
Diff
Executable File

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 <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/reboot.h>
+
+#include <linux/cooperative_internal.h>
+#include <asm/cooperative_internal.h>
+#include <asm/smp.h>
+#include <asm/desc.h>
+#include <asm/mmu_context.h>
+#include <asm/debugreg.h>
+#include <asm/i387.h>
+
+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 <linux/err.h>
+#include <linux/cooperative_internal.h>
#include <asm/tlbflush.h>
#include <asm/cpu.h>
@@ -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 <linux/pci.h>
#include <linux/init_ohci1394_dma.h>
#include <linux/kvm_para.h>
+#include <linux/cooperative_internal.h>
#include <video/edid.h>
@@ -97,6 +98,7 @@
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
+#ifndef CONFIG_COOPERATIVE
static struct resource video_ram_resource = {
.name = "Video RAM area",
.start = 0xa0000,
@@ -155,6 +157,7 @@
.end = 0x00ff,
.flags = IORESOURCE_BUSY | IORESOURCE_IO
} };
+#endif /* !CONFIG_COOPERATIVE */
/* cpu data as detected by the assembly code in head.S */
struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
@@ -181,6 +184,9 @@
/* user-defined highmem size */
static unsigned int highmem_pages = -1;
+/* colinux start_va */
+static long start_va = 0;
+
/*
* Setup options
*/
@@ -239,6 +245,7 @@
int __initdata user_defined_memmap;
+#ifndef CONFIG_COOPERATIVE
/*
* "mem=nopentium" disables the 4MB page tables.
* "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
@@ -272,6 +279,7 @@
return 0;
}
early_param("mem", parse_mem);
+#endif /* !CONFIG_COOPERATIVE */
#ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
@@ -397,6 +405,7 @@
#define BIOS_LOWMEM_KILOBYTES 0x413
+#ifndef CONFIG_COOPERATIVE
/*
* The BIOS places the EBDA/XBDA at the top of conventional
* memory, and usually decreases the reported amount of
@@ -444,6 +453,7 @@
/* reserve all memory between lowmem and the 1MB mark */
reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
}
+#endif /* !CONFIG_COOPERATIVE */
#ifndef CONFIG_NEED_MULTIPLE_NODES
static void __init setup_bootmem_allocator(void);
@@ -455,7 +465,14 @@
*/
min_low_pfn = PFN_UP(init_pg_tables_end);
+#ifdef CONFIG_COOPERATIVE
+ max_low_pfn = max_pfn = co_boot_params.co_memory_size / PAGE_SIZE;
+ min_low_pfn = PFN_UP(__pa((unsigned long)&_end)) + 0x10;
+ start_va = (unsigned long)__va(min_low_pfn << PAGE_SHIFT);
+ co_alloc_pages(start_va, 0x20);
+#else /* CONFIG_COOPERATIVE */
max_low_pfn = find_max_low_pfn();
+#endif /* CONFIG_COOPERATIVE */
#ifdef CONFIG_HIGHMEM
highstart_pfn = highend_pfn = max_pfn;
@@ -485,8 +502,10 @@
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+#ifndef CONFIG_COOPERATIVE
max_zone_pfns[ZONE_DMA] =
virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+#endif /* !CONFIG_COOPERATIVE */
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
@@ -558,6 +577,16 @@
static void __init reserve_initrd(void)
{
+#ifdef CONFIG_COOPERATIVE
+ if (co_boot_params.co_initrd != NULL) {
+ initrd_start = (unsigned long)co_boot_params.co_initrd;
+ initrd_end = (unsigned long)co_boot_params.co_initrd + co_boot_params.co_initrd_size;
+ printk(KERN_INFO "initrd enabled: 0x%x-0x%x size: 0x%08lx\n",
+ (unsigned int)initrd_start, (unsigned int)initrd_end, (long unsigned int)co_boot_params.co_initrd_size);
+
+ reserve_bootmem(virt_to_phys(co_boot_params.co_initrd), co_boot_params.co_initrd_size, BOOTMEM_DEFAULT);
+ }
+#else /* CONFIG_COOPERATIVE */
unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
@@ -598,6 +627,7 @@
initrd_end = initrd_start + ramdisk_size;
do_relocate_initrd = true;
+#endif /* CONFIG_COOPERATIVE */
}
#define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
@@ -654,6 +684,15 @@
*/
bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);
+#ifdef CONFIG_COOPERATIVE
+ {
+ unsigned long bootmem_end =
+ start_va + bootmap_size + (0x10 << PAGE_SHIFT);
+ unsigned long physical_end =
+ __PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT);
+ free_bootmem(__pa(bootmem_end), physical_end - bootmem_end);
+ }
+#else /* CONFIG_COOPERATIVE */
register_bootmem_low_pages(max_low_pfn);
/*
@@ -675,6 +714,8 @@
/* reserve EBDA region */
reserve_ebda_region();
+#endif /* CONFIG_COOPERATIVE */
+
#ifdef CONFIG_SMP
/*
* But first pinch a few for the stack/trampoline stuff
@@ -731,11 +772,13 @@
static void set_mca_bus(int x) { }
#endif
+#ifndef CONFIG_COOPERATIVE
/* Overridden in paravirt.c if CONFIG_PARAVIRT */
char * __init __attribute__((weak)) memory_setup(void)
{
return machine_specific_memory_setup();
}
+#endif
#ifdef CONFIG_NUMA
/*
@@ -792,8 +835,10 @@
#endif
ARCH_SETUP
+#ifndef CONFIG_COOPERATIVE
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
print_memory_map(memory_setup());
+#endif /* !CONFIG_COOPERATIVE */
copy_edd();
@@ -811,12 +856,17 @@
bss_resource.start = virt_to_phys(&__bss_start);
bss_resource.end = virt_to_phys(&__bss_stop)-1;
+#ifdef CONFIG_COOPERATIVE
+ strlcpy(boot_command_line, co_boot_params.co_boot_parameters, COMMAND_LINE_SIZE);
+#endif
parse_early_param();
+#ifndef CONFIG_COOPERATIVE
if (user_defined_memmap) {
printk(KERN_INFO "user-defined physical RAM map:\n");
print_memory_map("user");
}
+#endif /* !CONFIG_COOPERATIVE */
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
@@ -824,11 +874,13 @@
if (efi_enabled)
efi_init();
+#ifndef CONFIG_COOPERATIVE
/* update e820 for memory not covered by WB MTRRs */
propagate_e820_map();
mtrr_bp_init();
if (mtrr_trim_uncached_memory(max_pfn))
propagate_e820_map();
+#endif /* !CONFIG_COOPERATIVE */
max_low_pfn = setup_memory();
@@ -883,7 +935,9 @@
paravirt_post_allocator_init();
+#ifndef CONFIG_COOPERATIVE
dmi_scan_machine();
+#endif
io_delay_init();
@@ -928,11 +982,15 @@
"CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
#endif
+#ifndef CONFIG_COOPERATIVE
e820_register_memory();
e820_mark_nosave_regions();
+#endif /* !CONFIG_COOPERATIVE */
#ifdef CONFIG_VT
-#if defined(CONFIG_VGA_CONSOLE)
+#ifdef CONFIG_COOPERATIVE_CONSOLE
+ conswitchp = &colinux_con;
+#elif defined(CONFIG_VGA_CONSOLE)
if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
@@ -941,6 +999,7 @@
#endif
}
+#ifndef CONFIG_COOPERATIVE
/*
* Request address space for all standard resources
*
@@ -963,3 +1022,4 @@
}
subsys_initcall(request_standard_resources);
+#endif /* !CONFIG_COOPERATIVE */
Index: linux-2.6.26-source/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6.26-source/arch/x86/kernel/traps_32.c
@@ -57,6 +57,8 @@
#include <asm/nmi.h>
#include <asm/smp.h>
#include <asm/io.h>
+#include <linux/cooperative_internal.h>
+#include <asm/cooperative_internal.h>
#include "mach_traps.h"
@@ -527,6 +529,10 @@
return;
kernel_trap:
+ if (cooperative_mode_enabled() && trapnr == 3) {
+ co_kernel_breakpoint(regs);
+ return;
+ }
if (!fixup_exception(regs)) {
tsk->thread.error_code = error_code;
tsk->thread.trap_no = trapnr;
@@ -912,6 +918,10 @@
clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
tsk->thread.debugctlmsr = 0;
+ if (cooperative_mode_enabled() &&
+ co_kernel_debug(regs, error_code, condition))
+ return;
+
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_STOP)
return;
@@ -1165,6 +1175,12 @@
}
clts(); /* Allow maths ops (or we recurse) */
+#ifdef CONFIG_COOPERATIVE
+ if (!co_host_fpu_saved) {
+ CO_FPU_SAVE(co_host_fpu);
+ co_host_fpu_saved = 1;
+ }
+#endif /* CONFIG_COOPERATIVE */
restore_fpu(tsk);
thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
tsk->fpu_counter++;
Index: linux-2.6.26-source/arch/x86/mm/fault.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/mm/fault.c
+++ linux-2.6.26-source/arch/x86/mm/fault.c
@@ -217,6 +217,7 @@
page &= PAGE_MASK;
page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
& (PTRS_PER_PTE - 1)];
+ page = CO_P_TO_PP(page);
printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page);
}
@@ -523,10 +524,6 @@
pmd_t *pmd, *pmd_ref;
pte_t *pte, *pte_ref;
- /* Make sure we are in vmalloc area */
- if (!(address >= VMALLOC_START && address < VMALLOC_END))
- return -1;
-
/* Copy kernel mappings over when needed. This can also
happen within a race in page table update. In the later
case just flush. */
@@ -625,6 +622,10 @@
#else
if (unlikely(address >= TASK_SIZE64)) {
#endif
+ /* Make sure we are in vmalloc area */
+ if (!(address >= VMALLOC_START && address < VMALLOC_END))
+ goto bad_area_nosemaphore;
+
if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
vmalloc_fault(address) >= 0)
return;
Index: linux-2.6.26-source/arch/x86/mm/init_32.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/mm/init_32.c
+++ linux-2.6.26-source/arch/x86/mm/init_32.c
@@ -26,6 +26,7 @@
#include <linux/bootmem.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/cooperative_internal.h>
#include <linux/memory_hotplug.h>
#include <linux/initrd.h>
#include <linux/cpumask.h>
@@ -55,7 +56,9 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long highstart_pfn, highend_pfn;
+#ifndef CONFIG_COOPERATIVE
static noinline int do_test_wp_bit(void);
+#endif
/*
* Creates a middle page table and puts a pointer to it in the
@@ -101,7 +104,7 @@
}
paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
- set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+ set_pmd(pmd, __pmd(CO_PP_TO_P(__pa(page_table)) | _PAGE_TABLE));
BUG_ON(page_table != pte_offset_kernel(pmd, 0));
}
@@ -143,6 +146,7 @@
}
}
+#ifndef CONFIG_COOPERATIVE
static inline int is_kernel_text(unsigned long addr)
{
if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
@@ -226,6 +230,7 @@
return 1;
return 0;
}
+#endif /* !CONFIG_COOPERATIVE */
/*
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
@@ -241,8 +246,10 @@
{
if (pagenr <= 256)
return 1;
+#ifndef CONFIG_COOPERATIVE
if (!page_is_ram(pagenr))
return 1;
+#endif /* !CONFIG_COOPERATIVE */
return 0;
}
@@ -387,6 +394,7 @@
paravirt_pagetable_setup_start(pgd_base);
+#ifndef CONFIG_COOPERATIVE
/* Enable PSE if available */
if (cpu_has_pse)
set_in_cr4(X86_CR4_PSE);
@@ -400,6 +408,7 @@
kernel_physical_mapping_init(pgd_base);
remap_numa_kva();
+#endif /* !CONFIG_COOPERATIVE */
/*
* Fixed mappings, only the page table structure has to be
@@ -538,6 +547,7 @@
* black magic jumps to work around some nasty CPU bugs, but fortunately the
* switch to using exceptions got rid of all that.
*/
+#ifndef CONFIG_COOPERATIVE
static void __init test_wp_bit(void)
{
printk(KERN_INFO
@@ -558,6 +568,7 @@
printk(KERN_CONT "Ok.\n");
}
}
+#endif /* !CONFIG_COOPERATIVE */
static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -616,15 +627,15 @@
#if 1 /* double-sanity-check paranoia */
printk(KERN_INFO "virtual kernel memory layout:\n"
- " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
#ifdef CONFIG_HIGHMEM
- " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
+#endif
+#ifdef CONFIG_COOPERATIVE
+ " colinux : 0x%08lx - 0x%08lx (%4ld MB)\n"
#endif
- " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
- " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
- " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
- " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
- " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
+ " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n",
+
FIXADDR_START, FIXADDR_TOP,
(FIXADDR_TOP - FIXADDR_START) >> 10,
@@ -632,9 +643,19 @@
PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
(LAST_PKMAP*PAGE_SIZE) >> 10,
#endif
+#ifdef CONFIG_COOPERATIVE
+ CO_VPTR_BASE_START, CO_VPTR_BASE_END,
+ (CO_VPTR_BASE_END - CO_VPTR_BASE_START) >> 20,
+#endif
VMALLOC_START, VMALLOC_END,
- (VMALLOC_END - VMALLOC_START) >> 20,
+ (VMALLOC_END - VMALLOC_START) >> 20);
+
+ printk(KERN_INFO
+ " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
+ " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
+ " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
(unsigned long)__va(0), (unsigned long)high_memory,
((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
@@ -653,12 +674,20 @@
BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE > FIXADDR_START);
BUG_ON(VMALLOC_END > PKMAP_BASE);
#endif
+#ifdef CONFIG_COOPERATIVE
+ BUG_ON(CO_VPTR_BASE_END > FIXADDR_START);
+ BUG_ON(VMALLOC_END > CO_VPTR_BASE_START);
+ if (VMALLOC_START > VMALLOC_END)
+ panic("LOWMEM overlaps vmalloc. Decrease total memory with 'mem=...'!");
+#endif
BUG_ON(VMALLOC_START > VMALLOC_END);
BUG_ON((unsigned long)high_memory > VMALLOC_START);
#endif /* double-sanity-check paranoia */
+#ifndef CONFIG_COOPERATIVE
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
+#endif
cpa_init();
save_pg_dir();
@@ -681,6 +710,7 @@
* This function cannot be __init, since exceptions don't work in that
* section. Put this after the callers, so that it cannot be inlined.
*/
+#ifndef CONFIG_COOPERATIVE
static noinline int do_test_wp_bit(void)
{
char tmp_reg;
@@ -700,6 +730,7 @@
return flag;
}
+#endif /* !CONFIG_COOPERATIVE */
#ifdef CONFIG_DEBUG_RODATA
const int rodata_test_data = 0xC3;
@@ -749,7 +780,9 @@
*/
printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
begin, PAGE_ALIGN(end));
+#ifndef CONFIG_COOPERATIVE
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
+#endif /* !CONFIG_COOPERATIVE */
#else
unsigned long addr;
@@ -758,7 +791,9 @@
* we are going to free part of that, we need to make that
* writeable first.
*/
+#ifndef CONFIG_COOPERATIVE
set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
+#endif /* !CONFIG_COOPERATIVE */
for (addr = begin; addr < end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
Index: linux-2.6.26-source/arch/x86/mm/ioremap.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/mm/ioremap.c
+++ linux-2.6.26-source/arch/x86/mm/ioremap.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/cooperative_internal.h>
#include <asm/cacheflush.h>
#include <asm/e820.h>
@@ -47,8 +48,10 @@
int page_is_ram(unsigned long pagenr)
{
+#ifndef CONFIG_COOPERATIVE
resource_size_t addr, end;
int i;
+#endif
/*
* A special case is the first 4Kb of memory;
@@ -66,6 +69,7 @@
pagenr < (BIOS_END >> PAGE_SHIFT))
return 0;
+#ifndef CONFIG_COOPERATIVE
for (i = 0; i < e820.nr_map; i++) {
/*
* Not usable memory:
@@ -79,6 +83,7 @@
if ((pagenr >= addr) && (pagenr < end))
return 1;
}
+#endif /* !CONFIG_COOPERATIVE */
return 0;
}
@@ -259,6 +264,10 @@
*/
void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
{
+#ifdef CONFIG_COOPERATIVE
+ panic("ioremap_nocache %zu:%lu\n", phys_addr, size);
+ return NULL;
+#else /* CONFIG_COOPERATIVE */
/*
* Ideally, this should be:
* pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
@@ -270,6 +279,7 @@
return __ioremap_caller(phys_addr, size, val,
__builtin_return_address(0));
+#endif /* CONFIG_COOPERATIVE */
}
EXPORT_SYMBOL(ioremap_nocache);
@@ -295,6 +305,11 @@
void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
{
+ if (cooperative_mode_enabled()) {
+ panic("ioremap_cache %zu:%lu\n", phys_addr, size);
+ return NULL;
+ }
+
return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WB,
__builtin_return_address(0));
}
Index: linux-2.6.26-source/include/asm-x86/bug.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/bug.h
+++ linux-2.6.26-source/include/asm-x86/bug.h
@@ -4,6 +4,10 @@
#ifdef CONFIG_BUG
#define HAVE_ARCH_BUG
+#ifdef CONFIG_COOPERATIVE
+extern void co_terminate_bug(int code, int line, const char *file);
+#define BUG() do { co_terminate_bug(0, __LINE__, __FILE__); } while(0)
+#else /* CONFIG_COOPERATIVE */
#ifdef CONFIG_DEBUG_BUGVERBOSE
#ifdef CONFIG_X86_32
@@ -34,6 +38,7 @@
#endif
#endif /* !CONFIG_BUG */
+#endif /* CONFIG_COOPERATIVE */
#include <asm-generic/bug.h>
#endif
Index: linux-2.6.26-source/include/asm-x86/cooperative.h
===================================================================
--- /dev/null
+++ linux-2.6.26-source/include/asm-x86/cooperative.h
@@ -0,0 +1,205 @@
+/*
+ * linux/include/asm/cooperative.h
+ *
+ * Copyright (C) 2004 Dan Aloni
+ *
+ * This file defines the lower level interfaces between the Cooperative Linux
+ * kernel and the host OS driver. It's for both external inclusion from the
+ * and internal inclusion in the kernel sources.
+ */
+
+#ifndef __LINUX_ASM_COOPERATIVE_H__
+#define __LINUX_ASM_COOPERATIVE_H__
+
+typedef struct {
+ unsigned short size;
+ struct x86_idt_entry *table;
+} __attribute__((packed)) x86_idt_t;
+
+typedef struct {
+ unsigned short limit;
+ struct x86_dt_entry *base;
+} __attribute__((packed)) x86_gdt_t;
+
+typedef struct {
+ unsigned char border2[0x4];
+
+ unsigned long cs;
+ #define CO_ARCH_STATE_STACK_CS "0x04"
+
+ unsigned long ds;
+ #define CO_ARCH_STATE_STACK_DS "0x08"
+
+ unsigned long es;
+ #define CO_ARCH_STATE_STACK_ES "0x0C"
+
+ unsigned long cr3;
+ #define CO_ARCH_STATE_STACK_CR3 "0x10"
+
+ unsigned long cr4;
+ #define CO_ARCH_STATE_STACK_CR4 "0x14"
+
+ unsigned long cr2;
+ #define CO_ARCH_STATE_STACK_CR2 "0x18"
+
+ unsigned long cr0;
+ #define CO_ARCH_STATE_STACK_CR0 "0x1C"
+
+ x86_gdt_t gdt;
+ #define CO_ARCH_STATE_STACK_GDT "0x20"
+
+ unsigned long fs;
+ #define CO_ARCH_STATE_STACK_FS "0x26"
+
+ unsigned long gs;
+ #define CO_ARCH_STATE_STACK_GS "0x2A"
+
+ unsigned short ldt;
+ #define CO_ARCH_STATE_STACK_LDT "0x2E"
+
+ x86_idt_t idt;
+ #define CO_ARCH_STATE_STACK_IDT "0x30"
+
+ unsigned short tr;
+ #define CO_ARCH_STATE_STACK_TR "0x36"
+
+ unsigned long return_eip;
+ #define CO_ARCH_STATE_STACK_RETURN_EIP "0x38"
+
+ unsigned long flags;
+ #define CO_ARCH_STATE_STACK_FLAGS "0x3C"
+
+ unsigned long esp;
+ #define CO_ARCH_STATE_STACK_ESP "0x40"
+
+ unsigned long ss;
+ #define CO_ARCH_STATE_STACK_SS "0x44"
+
+ unsigned long dr0;
+ #define CO_ARCH_STATE_STACK_DR0 "0x48"
+
+ unsigned long dr1;
+ #define CO_ARCH_STATE_STACK_DR1 "0x4C"
+
+ unsigned long dr2;
+ #define CO_ARCH_STATE_STACK_DR2 "0x50"
+
+ unsigned long dr3;
+ #define CO_ARCH_STATE_STACK_DR3 "0x54"
+
+ unsigned long dr6;
+ #define CO_ARCH_STATE_STACK_DR6 "0x58"
+
+ unsigned long dr7;
+ #define CO_ARCH_STATE_STACK_DR7 "0x5C"
+
+ union {
+ unsigned long temp_cr3;
+ unsigned long other_map;
+ } __attribute__((packed));
+ #define CO_ARCH_STATE_STACK_TEMP_CR3 "0x60"
+ #define CO_ARCH_STATE_STACK_OTHERMAP "0x60"
+
+ unsigned long relocate_eip;
+ #define CO_ARCH_STATE_STACK_RELOCATE_EIP "0x64"
+
+ unsigned long pad1;
+ #define CO_ARCH_STATE_STACK_RELOCATE_EIP_AFTER "0x68"
+
+ unsigned long va;
+ #define CO_ARCH_STATE_STACK_VA "0x6C"
+
+ unsigned long sysenter_cs;
+ #define CO_ARCH_STATE_SYSENTER_CS "0x70"
+
+ unsigned long sysenter_esp;
+ #define CO_ARCH_STATE_SYSENTER_ESP "0x74"
+
+ unsigned long sysenter_eip;
+ #define CO_ARCH_STATE_SYSENTER_EIP "0x78"
+} __attribute__((packed)) co_arch_state_stack_t;
+
+#define CO_MAX_PARAM_SIZE 0x400
+
+typedef struct co_arch_passage_page_normal_address_space {
+ unsigned long pgd[0x400];
+ unsigned long pte[2][0x400];
+} co_arch_passage_page_normal_address_space_t;
+
+typedef struct co_arch_passage_page_pae_address_space {
+ unsigned long long main[0x200];
+ unsigned long long pgd[2][0x200];
+ unsigned long long pte[2][0x200];
+} co_arch_passage_page_pae_address_space_t;
+
+typedef struct co_arch_passage_page {
+ union {
+ struct {
+ union {
+ struct {
+ union {
+ uintptr_t self_physical_address;
+ uintptr_t temp_pgd_physical;
+ } __attribute__((packed));
+ unsigned long dr0;
+ unsigned long dr1;
+ unsigned long dr2;
+ unsigned long dr3;
+ unsigned long dr6;
+ unsigned long dr7;
+ unsigned char code[0x260];
+ } __attribute__((packed));
+ unsigned char pad[0x280]; /* Be careful! see NOTE below */
+ } __attribute__((packed));
+
+ /* Machine states */
+
+ /*
+ * NOTE: *_state fields must be aligned at 16 bytes boundary since
+ * the fxsave/fxload instructions expect an aligned arugment.
+ */
+
+ co_arch_state_stack_t host_state;
+ co_arch_state_stack_t linuxvm_state;
+
+ /* Control parameters */
+ unsigned long operation;
+ uintptr_t params[];
+ } __attribute__((packed));
+ unsigned char first_page[0x1000];
+ };
+
+ /* page tables for passage address spaces */
+ union {
+ co_arch_passage_page_normal_address_space_t guest_normal;
+ co_arch_passage_page_normal_address_space_t temp_space;
+ } __attribute__((packed));
+ union {
+ co_arch_passage_page_normal_address_space_t host_normal;
+ co_arch_passage_page_pae_address_space_t host_pae;
+ } __attribute__((packed));
+} co_arch_passage_page_t;
+
+/*
+ * Address space layout:
+ */
+
+#define CO_VPTR_BASE (0xffc00000ul)
+#define CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP (CO_VPTR_BASE - 0x1000000ul)
+#define CO_VPTR_PSEUDO_RAM_PAGE_TABLES (CO_VPTR_BASE - 0x1100000ul)
+#define CO_VPTR_PASSAGE_PAGE (CO_VPTR_BASE - 0x1101000ul)
+#define CO_VPTR_IO_AREA_SIZE (0x10000ul)
+#define CO_VPTR_IO_AREA_START (CO_VPTR_BASE - 0x1200000ul)
+#define CO_VPTR_SELF_MAP (CO_VPTR_BASE - 0x1400000ul)
+
+#define CO_VPTR_BASE_START CO_VPTR_SELF_MAP
+#define CO_VPTR_BASE_END CO_VPTR_BASE
+
+#define CO_LOWMEMORY_MAX_MB 984
+
+typedef struct {
+ unsigned long kernel_cs;
+ unsigned long kernel_ds;
+} __attribute__((packed)) co_arch_info_t;
+
+#endif
Index: linux-2.6.26-source/include/asm-x86/cooperative_internal.h
===================================================================
--- /dev/null
+++ linux-2.6.26-source/include/asm-x86/cooperative_internal.h
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm/cooperative_internal.h
+ *
+ * Copyright (C) 2004 Dan Aloni
+ */
+
+#ifndef __LINUX_ASM_COOPERATIVE_INTERNAL_H__
+#define __LINUX_ASM_COOPERATIVE_INTERNAL_H__
+
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_COOPERATIVE
+
+extern bool co_host_fpu_saved;
+extern char co_host_fpu[0x200];
+
+extern void co_kernel_breakpoint(struct pt_regs * regs);
+extern int co_kernel_debug(struct pt_regs * regs, long error_code, unsigned int condition);
+
+#define CO_FPU_SAVE(x) \
+do \
+{ \
+ if (cpu_has_fxsr) \
+ asm("fxsave " #x " ; fnclex"); \
+ else \
+ asm("fnsave " #x " ; fwait"); \
+} \
+while (0)
+
+#define CO_FPU_RESTORE(x) \
+do \
+{ \
+ if (cpu_has_fxsr) \
+ asm("fxrstor " #x); \
+ else \
+ asm("frstor " #x); \
+} \
+while (0)
+
+#else
+
+static inline void co_kernel_breakpoint(struct pt_regs * regs)
+{
+}
+
+static inline int co_kernel_debug(struct pt_regs * regs, long error_code, unsigned int condition)
+{
+ return 0;
+}
+
+#endif
+
+#endif
Index: linux-2.6.26-source/include/asm-x86/dma.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/dma.h
+++ linux-2.6.26-source/include/asm-x86/dma.h
@@ -287,6 +287,7 @@
*
* Assumes DMA flip-flop is clear.
*/
+#ifndef CONFIG_COOPERATIVE
static inline int get_dma_residue(unsigned int dmanr)
{
unsigned int io_port;
@@ -301,6 +302,7 @@
return (dmanr <= 3) ? count : (count << 1);
}
+#endif
/* These are in kernel/dma.c: */
Index: linux-2.6.26-source/include/asm-x86/mach-default/irq_vectors.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/mach-default/irq_vectors.h
+++ linux-2.6.26-source/include/asm-x86/mach-default/irq_vectors.h
@@ -67,6 +67,17 @@
#define TIMER_IRQ 0
+#ifdef CONFIG_COOPERATIVE
+#define KEYBOARD_IRQ 1
+#define SERIAL_IRQ 3
+#define SOUND_IRQ 5
+#define POWER_IRQ 9
+#define NETWORK_IRQ 10
+#define SCSI_IRQ 11
+#define MOUSE_IRQ 12
+#define BLOCKDEV_IRQ 15
+#endif
+
/*
* 16 8259A IRQ's, 208 potential APIC interrupt sources.
* Right now the APIC is mostly only used for SMP.
Index: linux-2.6.26-source/include/asm-x86/mach-default/irq_vectors_limits.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/mach-default/irq_vectors_limits.h
+++ linux-2.6.26-source/include/asm-x86/mach-default/irq_vectors_limits.h
@@ -1,7 +1,7 @@
#ifndef _ASM_IRQ_VECTORS_LIMITS_H
#define _ASM_IRQ_VECTORS_LIMITS_H
-#if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT)
+#if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_X86_UP_COPIC) || defined(CONFIG_PARAVIRT)
#define NR_IRQS 224
# if (224 >= 32 * NR_CPUS)
# define NR_IRQ_VECTORS NR_IRQS
Index: linux-2.6.26-source/include/asm-x86/mc146818rtc.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/mc146818rtc.h
+++ linux-2.6.26-source/include/asm-x86/mc146818rtc.h
@@ -87,6 +87,8 @@
#define current_lock_cmos_reg() 0
#endif
+#ifndef CONFIG_COOPERATIVE
+
/*
* The yet supported machines all access the RTC index register via
* an ISA port access but the way to access the date register differs ...
@@ -99,6 +101,11 @@
extern int mach_set_rtc_mmss(unsigned long nowtime);
extern unsigned long mach_get_cmos_time(void);
+#else
+#define CMOS_READ(addr) (0)
+#define CMOS_WRITE(val, addr) do {} while(0)
+#endif
+
#define RTC_IRQ 8
#endif /* _ASM_MC146818RTC_H */
Index: linux-2.6.26-source/include/asm-x86/page.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/page.h
+++ linux-2.6.26-source/include/asm-x86/page.h
@@ -42,6 +42,20 @@
#include <asm/page_32.h>
#endif /* CONFIG_X86_64 */
+#ifdef CONFIG_COOPERATIVE
+#define CO_PA(pfn) (((unsigned long *)CO_VPTR_PSEUDO_RAM_PAGE_TABLES)[pfn])
+#define CO_VA_PFN(pa) (((unsigned long *)CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP)[((pa) >> PAGE_SHIFT)])
+#define CO_PFN_PP_TO_P(pfn) (CO_PA(pfn) >> PAGE_SHIFT)
+#define CO_PFN_P_TO_PP(pfn) (CO_VA_PFN(pfn << PAGE_SHIFT))
+#define CO_PP_TO_P(pa) ((CO_PFN_PP_TO_P(pa >> PAGE_SHIFT) << PAGE_SHIFT) | (pa & ~PAGE_MASK))
+#define CO_P_TO_PP(pa) ((CO_PFN_P_TO_PP(pa >> PAGE_SHIFT) << PAGE_SHIFT) | (pa & ~PAGE_MASK))
+#else
+#define CO_PFN_P_TO_PP(pfn) pfn
+#define CO_PFN_PP_TO_P(pfn) pfn
+#define CO_PP_TO_P(pa) pa
+#define CO_P_TO_PP(pa) pa
+#endif
+
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define VM_DATA_DEFAULT_FLAGS \
@@ -50,6 +64,7 @@
#ifndef __ASSEMBLY__
+#include <asm/cooperative.h>
extern int page_is_ram(unsigned long pagenr);
extern int devmem_is_allowed(unsigned long pagenr);
Index: linux-2.6.26-source/include/asm-x86/pgtable-2level.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/pgtable-2level.h
+++ linux-2.6.26-source/include/asm-x86/pgtable-2level.h
@@ -1,6 +1,8 @@
#ifndef _I386_PGTABLE_2LEVEL_H
#define _I386_PGTABLE_2LEVEL_H
+#include <asm/cooperative.h>
+
#define pte_ERROR(e) \
printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
#define pgd_ERROR(e) \
@@ -55,7 +57,7 @@
#define pte_page(x) pfn_to_page(pte_pfn(x))
#define pte_none(x) (!(x).pte_low)
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_pfn(x) CO_PFN_P_TO_PP((pte_val(x) >> PAGE_SHIFT))
/*
* Bits 0, 6 and 7 are taken, split up the 29 bits of offset
Index: linux-2.6.26-source/include/asm-x86/pgtable.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/pgtable.h
+++ linux-2.6.26-source/include/asm-x86/pgtable.h
@@ -272,13 +272,13 @@
static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
{
- return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) |
+ return __pte((((phys_addr_t)CO_PFN_PP_TO_P(page_nr) << PAGE_SHIFT) |
pgprot_val(pgprot)) & __supported_pte_mask);
}
static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
{
- return __pmd((((phys_addr_t)page_nr << PAGE_SHIFT) |
+ return __pmd((((phys_addr_t)CO_PFN_PP_TO_P(page_nr) << PAGE_SHIFT) |
pgprot_val(pgprot)) & __supported_pte_mask);
}
Index: linux-2.6.26-source/include/asm-x86/processor.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/processor.h
+++ linux-2.6.26-source/include/asm-x86/processor.h
@@ -233,6 +233,7 @@
} __attribute__((packed)) ____cacheline_aligned;
#endif
+#ifdef __KERNEL__
/*
* IO-bitmap sizes:
*/
@@ -654,6 +655,7 @@
return eax;
}
+#endif /* __KERNEL__ */
static inline unsigned int cpuid_ebx(unsigned int op)
{
Index: linux-2.6.26-source/include/linux/cooperative.h
===================================================================
--- /dev/null
+++ linux-2.6.26-source/include/linux/cooperative.h
@@ -0,0 +1,399 @@
+/*
+ * linux/include/linux/cooperative.h
+ *
+ * Copyright (C) 2004 Dan Aloni
+ *
+ * This file defines the interfaces between the Cooperative Linux kernel
+ * and the host OS driver. It's for both external inclusion from the
+ * and internal inclusion in the kernel sources.
+ */
+
+#ifndef __LINUX_COOPERATIVE_H__
+#define __LINUX_COOPERATIVE_H__
+
+#ifdef __KERNEL__
+#ifndef CO_KERNEL
+#define CO_COLINUX_KERNEL
+#define CO_KERNEL
+#endif
+#endif
+
+#include <asm/cooperative.h>
+
+#define CO_LINUX_API_VERSION 14
+
+#pragma pack(0)
+
+#define CO_BOOTPARAM_STRING_LENGTH 0x100
+
+typedef enum {
+ CO_OPERATION_EMPTY=0,
+ CO_OPERATION_START,
+ CO_OPERATION_IDLE,
+ CO_OPERATION_TERMINATE,
+ CO_OPERATION_MESSAGE_TO_MONITOR,
+ CO_OPERATION_MESSAGE_FROM_MONITOR,
+ CO_OPERATION_FORWARD_INTERRUPT,
+ CO_OPERATION_DEVICE,
+ CO_OPERATION_GET_TIME,
+ CO_OPERATION_DEBUG_LINE,
+ CO_OPERATION_GET_HIGH_PREC_TIME,
+ CO_OPERATION_TRACE_POINT,
+ CO_OPERATION_FREE_PAGES,
+ CO_OPERATION_ALLOC_PAGES,
+ CO_OPERATION_PRINTK_unused,
+ CO_OPERATION_GETPP,
+ CO_OPERATION_MAX /* Must be last entry all times */
+} co_operation_t;
+
+#define CO_MODULE_MAX_CONET 16
+#define CO_MODULE_MAX_COBD 32
+#define CO_MODULE_MAX_COFS 32
+#define CO_MODULE_MAX_SERIAL 32
+#define CO_MODULE_MAX_COSCSI 32
+#define CO_MODULE_MAX_COVIDEO 2
+#define CO_MODULE_MAX_COAUDIO 2
+
+typedef enum {
+ CO_MODULE_LINUX,
+ CO_MODULE_MONITOR,
+ CO_MODULE_DAEMON,
+ CO_MODULE_IDLE,
+ CO_MODULE_KERNEL_SWITCH,
+ CO_MODULE_USER_SWITCH,
+ CO_MODULE_CONSOLE,
+ CO_MODULE_PRINTK,
+
+ CO_MODULE_CONET0,
+ CO_MODULE_CONET_END=CO_MODULE_CONET0+CO_MODULE_MAX_CONET-1,
+
+ CO_MODULE_COBD0,
+ CO_MODULE_COBD_END=CO_MODULE_COBD0+CO_MODULE_MAX_COBD-1,
+
+ CO_MODULE_COFS0,
+ CO_MODULE_COFS_END=CO_MODULE_COFS0+CO_MODULE_MAX_COFS-1,
+
+ CO_MODULE_SERIAL0,
+ CO_MODULE_SERIAL_END=CO_MODULE_SERIAL0+CO_MODULE_MAX_SERIAL-1,
+
+ CO_MODULE_COSCSI0,
+ CO_MODULE_COSCSI_END=CO_MODULE_COSCSI0+CO_MODULE_MAX_COSCSI-1,
+
+ CO_MODULE_COVIDEO0,
+ CO_MODULE_COVIDEO_END=CO_MODULE_COVIDEO0+CO_MODULE_MAX_COVIDEO-1,
+
+ CO_MODULE_COAUDIO0,
+ CO_MODULE_COAUDIO_END=CO_MODULE_COAUDIO0+CO_MODULE_MAX_COAUDIO-1,
+ CO_MODULES_MAX,
+} co_module_t;
+
+typedef enum {
+ CO_PRIORITY_DISCARDABLE=0,
+ CO_PRIORITY_IMPORTANT,
+} co_priority_t;
+
+typedef enum {
+ CO_MESSAGE_TYPE_STRING=0,
+ CO_MESSAGE_TYPE_OTHER=1,
+} co_message_type_t;
+
+typedef struct {
+ co_module_t from;
+ co_module_t to;
+ co_priority_t priority;
+ co_message_type_t type;
+ unsigned long size;
+ unsigned char data[0];
+} __attribute__((packed)) co_message_t;
+
+typedef enum {
+ CO_DEVICE_BLOCK=0,
+ CO_DEVICE_CONSOLE,
+ CO_DEVICE_KEYBOARD,
+ CO_DEVICE_NETWORK,
+ CO_DEVICE_TIMER,
+ CO_DEVICE_POWER,
+ CO_DEVICE_SERIAL,
+ CO_DEVICE_FILESYSTEM,
+
+ CO_DEVICE_MOUSE,
+ CO_DEVICE_SCSI,
+ CO_DEVICE_VIDEO,
+ CO_DEVICE_AUDIO,
+ CO_DEVICE_PCI,
+
+ CO_DEVICES_TOTAL,
+} co_device_t;
+
+typedef enum {
+ CO_KBD_SCANCODE_RAW=0,
+ CO_KBD_SCANCODE_ASCII
+} mode_data_from_keyboard_t;
+
+typedef struct {
+ unsigned char code;
+ mode_data_from_keyboard_t mode;
+} __attribute__((packed)) co_scan_code_t;
+
+#define CO_MOUSE_MAX_X 2048
+#define CO_MOUSE_MAX_Y 2048
+
+typedef struct {
+ unsigned btns;
+ unsigned abs_x;
+ unsigned abs_y;
+ int rel_z;
+} __attribute__((packed)) co_mouse_data_t;
+
+typedef enum {
+ CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL=0,
+ CO_LINUX_MESSAGE_POWER_SHUTDOWN,
+ CO_LINUX_MESSAGE_POWER_OFF,
+} co_linux_message_power_type_t;
+
+typedef struct {
+ co_linux_message_power_type_t type;
+} __attribute__((packed)) co_linux_message_power_t;
+
+typedef struct {
+ unsigned long tick_count;
+} __attribute__((packed)) co_linux_message_idle_t;
+
+typedef struct {
+ co_device_t device;
+ unsigned int unit;
+ unsigned long size;
+ char data[];
+} __attribute__((packed)) co_linux_message_t;
+
+typedef enum {
+ CO_TERMINATE_END=0,
+ CO_TERMINATE_REBOOT,
+ CO_TERMINATE_POWEROFF,
+ CO_TERMINATE_PANIC,
+ CO_TERMINATE_HALT,
+ CO_TERMINATE_FORCED_OFF,
+ CO_TERMINATE_FORCED_END,
+ CO_TERMINATE_INVALID_OPERATION,
+ CO_TERMINATE_STACK_OVERFLOW,
+ CO_TERMINATE_BUG,
+ CO_TERMINATE_VMXE,
+} co_termination_reason_t;
+
+#ifdef CO_KERNEL
+
+#ifndef asmlinkage
+#define asmlinkage __attribute__((regparm(0)))
+#endif
+
+typedef void asmlinkage (*co_switcher_t)(co_arch_passage_page_t *page,
+ void *from,
+ void *to);
+
+#define co_passage_page_func_low(_from_,_to_) \
+ (((co_switcher_t)(co_passage_page->code)) \
+ (co_passage_page, \
+ &_from_.border2, \
+ &_to_.border2))
+
+# ifdef CO_COLINUX_KERNEL
+# define co_passage_page ((co_arch_passage_page_t *)(CO_VPTR_PASSAGE_PAGE))
+# define co_current (co_passage_page->linuxvm_state)
+# define co_other (co_passage_page->host_state)
+# else
+# define co_passage_page (cmon->passage_page)
+# define co_other (co_passage_page->linuxvm_state)
+# define co_current (co_passage_page->host_state)
+# endif
+
+# define co_switch() co_passage_page_func_low(co_current, co_other)
+
+#endif /* CO_KERNEL */
+
+/*
+ * Defines operations on various virtual devices.
+ */
+
+typedef enum {
+ CO_OPERATION_CONSOLE_STARTUP=0,
+ CO_OPERATION_CONSOLE_INIT=1,
+ CO_OPERATION_CONSOLE_DEINIT,
+ CO_OPERATION_CONSOLE_CLEAR,
+ CO_OPERATION_CONSOLE_PUTC,
+ CO_OPERATION_CONSOLE_PUTCS,
+ CO_OPERATION_CONSOLE_CURSOR_DRAW,
+ CO_OPERATION_CONSOLE_CURSOR_ERASE,
+ CO_OPERATION_CONSOLE_CURSOR_MOVE,
+ CO_OPERATION_CONSOLE_SCROLL_UP,
+ CO_OPERATION_CONSOLE_SCROLL_DOWN,
+ CO_OPERATION_CONSOLE_BMOVE,
+ CO_OPERATION_CONSOLE_SWITCH,
+ CO_OPERATION_CONSOLE_BLANK,
+ CO_OPERATION_CONSOLE_FONT_OP,
+ CO_OPERATION_CONSOLE_SET_PALETTE,
+ CO_OPERATION_CONSOLE_SCROLLDELTA,
+ CO_OPERATION_CONSOLE_SET_ORIGIN,
+ CO_OPERATION_CONSOLE_SAVE_SCREEN,
+ CO_OPERATION_CONSOLE_INVERT_REGION,
+ CO_OPERATION_CONSOLE_CONFIG,
+ CO_OPERATION_CONSOLE_INIT_SCROLLBUFFER,
+} co_operation_console_t;
+
+
+typedef char co_console_code;
+typedef unsigned short co_console_character;
+typedef unsigned short co_console_unit;
+
+typedef struct {
+ co_console_unit x;
+ co_console_unit y;
+ co_console_unit height;
+} __attribute__((packed)) co_cursor_pos_t;
+
+typedef struct {
+ co_operation_console_t type;
+ union {
+ struct {
+ co_console_unit top;
+ co_console_unit bottom;
+ co_console_unit lines;
+ co_console_character charattr;
+ } scroll;
+ struct {
+ co_console_unit y;
+ co_console_unit x;
+ co_console_unit count;
+ co_console_character data[];
+ } putcs;
+ struct {
+ co_console_unit x;
+ co_console_unit y;
+ co_console_character charattr;
+ } putc;
+ struct {
+ co_console_unit top;
+ co_console_unit left;
+ co_console_unit bottom;
+ co_console_unit right;
+ co_console_character charattr;
+ } clear;
+ struct {
+ co_console_unit y;
+ co_console_unit x;
+ co_console_unit count;
+ } invert;
+ struct {
+ co_console_unit row;
+ co_console_unit column;
+ co_console_unit top;
+ co_console_unit left;
+ co_console_unit bottom;
+ co_console_unit right;
+ } bmove;
+ struct {
+ co_console_unit rows;
+ co_console_unit cols;
+ co_console_unit attr;
+ } config;
+ co_cursor_pos_t cursor;
+ };
+} __attribute__((packed)) co_console_message_t;
+
+typedef struct {
+ unsigned long messages_waiting;
+ unsigned char buffer[];
+} co_io_buffer_t;
+
+typedef struct {
+ unsigned long index;
+ unsigned long flags;
+ unsigned long func;
+ unsigned long pid;
+} __attribute__((packed)) co_trace_point_info_t;
+
+typedef enum {
+ CO_BLOCK_OPEN=0,
+ CO_BLOCK_STAT,
+ CO_BLOCK_READ,
+ CO_BLOCK_WRITE,
+ CO_BLOCK_CLOSE,
+ CO_BLOCK_GET_ALIAS,
+} co_block_request_type_t;
+
+typedef enum {
+ CO_BLOCK_REQUEST_RETCODE_OK=0,
+ CO_BLOCK_REQUEST_RETCODE_ERROR=-1,
+} co_block_request_retcode_t;
+
+typedef enum {
+ CO_NETWORK_GET_MAC=0,
+} co_network_request_type_t;
+
+#ifdef CO_KERNEL
+/* If we are compiling kernel code (Linux or Host Driver) */
+# ifdef CO_COLINUX_KERNEL
+/* Inside Linux, vm_ptr_t considered a valid pointer in its virtual address space */
+typedef void *vm_ptr_t;
+# else
+/* But inside the host, the type is considered not to be a pointer in its own address space */
+typedef uintptr_t vm_ptr_t;
+# endif
+
+typedef struct {
+ co_block_request_type_t type;
+ long rc;
+ union {
+ struct {
+ unsigned long long offset;
+ unsigned long long size;
+ unsigned long long disk_size;
+ vm_ptr_t address;
+ void * irq_request;
+ int async;
+ };
+ struct {
+ char alias[20];
+ };
+ };
+} __attribute__((packed)) co_block_request_t;
+
+typedef struct {
+ void * irq_request;
+ int uptodate;
+} __attribute__((packed)) co_block_intr_t;
+
+typedef struct {
+ co_network_request_type_t type;
+ unsigned int unit;
+ char mac_address[6];
+ char _pad[2];
+ int result;
+} __attribute__((packed)) co_network_request_t;
+
+#endif /* CO_KERNEL */
+
+typedef struct {
+ unsigned long api_version;
+ unsigned long compiler_major;
+ unsigned long compiler_minor;
+ unsigned long compiler_abi;
+} __attribute__((packed)) co_info_t;
+
+typedef struct {
+ unsigned long co_core_end;
+ unsigned long co_memory_size;
+ void *co_initrd;
+ unsigned long co_initrd_size;
+ unsigned long co_cpu_khz;
+ unsigned long filler[5]; // compatible old api: empty 5,6,7,8,9
+ char co_boot_parameters[CO_BOOTPARAM_STRING_LENGTH]; // params[10]
+} __attribute__((packed)) co_boot_params_t;
+
+#ifndef COLINUX_TRACE
+#define CO_TRACE_STOP
+#define CO_TRACE_CONTINUE
+#endif
+
+#pragma pack()
+
+#endif
Index: linux-2.6.26-source/include/linux/cooperative_internal.h
===================================================================
--- /dev/null
+++ linux-2.6.26-source/include/linux/cooperative_internal.h
@@ -0,0 +1,128 @@
+/*
+ * linux/include/linux/cooperative_internal.h
+ *
+ * Copyright (C) 2004 Dan Aloni
+ *
+ * This header gathers the functions and variables in Cooperative Mode
+ * when CONFIG_COOPERATIVE is defined.
+ */
+#ifndef __LINUX_COOPERATIVE_LINUX_H__
+#define __LINUX_COOPERATIVE_LINUX_H__
+
+#include <linux/cooperative.h>
+#include <linux/list.h>
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_COOPERATIVE
+
+typedef struct {
+ struct list_head node;
+ co_message_t msg;
+} co_message_node_t;
+
+extern co_boot_params_t co_boot_params;
+extern int co_passage_page_holding_count;
+
+#ifdef CONFIG_COLINUX_STATS
+typedef struct co_proc_counts {
+ unsigned long switches[CO_OPERATION_MAX];
+} co_proc_counts_t;
+
+extern co_proc_counts_t co_proc_counts;
+#endif
+
+#define co_io_buffer ((co_io_buffer_t *)CO_VPTR_IO_AREA_START)
+#define cooperative_mode_enabled() 1
+
+extern void co_debug(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+extern void co_printk(const char *line, int size);
+
+extern void co_switch_wrapper(void);
+extern void co_callback(struct pt_regs *regs);
+extern void co_idle_processor(void);
+extern void co_terminate(co_termination_reason_t reason);
+extern void co_terminate_panic(const char *text, int len);
+extern void co_terminate_bug(int code, int line, const char *file);
+extern void co_free_pages(unsigned long vaddr, int pages);
+extern int co_alloc_pages(unsigned long vaddr, int pages);
+extern void co_start_kernel(void);
+extern void co_arch_start_kernel(void);
+
+extern void co_send_message(co_module_t from,
+ co_module_t to,
+ co_priority_t priority,
+ co_message_type_t type,
+ unsigned long size,
+ const char *data);
+extern unsigned long co_get_host_time(void);
+
+extern int co_get_message(co_message_node_t **message, co_device_t device);
+static inline void co_free_message(co_message_node_t *message)
+{
+ kfree(message);
+}
+
+extern void *co_map_buffer(void *, int);
+
+static inline void co_passage_page_acquire(unsigned long *flags)
+{
+ local_irq_save(*flags);
+ co_passage_page_holding_count++;
+}
+
+static inline void co_passage_page_ref_down(void)
+{
+ co_passage_page_holding_count--;
+}
+
+static inline void co_passage_page_ref_up(void)
+{
+ co_passage_page_holding_count++;
+}
+
+static inline int co_passage_page_held(void)
+{
+ return co_passage_page_holding_count;
+}
+
+static inline void co_passage_page_release(unsigned long flags)
+{
+ co_passage_page_holding_count--;
+ local_irq_restore(flags);
+}
+
+#define co_passage_page_assert_valid() do { \
+ BUG_ON(co_passage_page_held()); \
+} while (0)
+
+static inline co_message_t *co_send_message_save(unsigned long *flags)
+{
+ co_passage_page_assert_valid();
+ co_passage_page_acquire(flags);
+
+ if (co_io_buffer->messages_waiting) {
+ co_passage_page_release(*flags);
+ return NULL;
+ }
+
+ co_passage_page->operation = CO_OPERATION_MESSAGE_TO_MONITOR;
+ co_io_buffer->messages_waiting = 1;
+ return ((co_message_t *)co_io_buffer->buffer);
+}
+
+static inline void co_send_message_restore(unsigned long flags)
+{
+ co_switch_wrapper();
+ co_passage_page_release(flags);
+}
+
+#else
+
+#define co_printk(line, size) do {} while (0)
+#define co_terminate(reason) do {} while (0)
+#define cooperative_mode_enabled() 0
+
+#endif
+
+#endif
Index: linux-2.6.26-source/kernel/Makefile
===================================================================
--- linux-2.6.26-source.orig/kernel/Makefile
+++ linux-2.6.26-source/kernel/Makefile
@@ -64,6 +64,7 @@
obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o
endif
obj-$(CONFIG_RELAY) += relay.o
+obj-$(CONFIG_COOPERATIVE) += cooperative.o
obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
Index: linux-2.6.26-source/kernel/cooperative.c
===================================================================
--- /dev/null
+++ linux-2.6.26-source/kernel/cooperative.c
@@ -0,0 +1,461 @@
+/*
+ * linux/kernel/cooperative.c
+ *
+ * Cooperative mode (coLinux) support routines.
+ *
+ * Dan Aloni <da-x@colinux.org>, 2003-2004 (C).
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/cooperative_internal.h>
+
+CO_TRACE_STOP;
+
+co_boot_params_t co_boot_params;
+
+typedef struct {
+ struct list_head list;
+ int num_messages;
+} co_message_queue_t;
+
+int co_messages_active = 0;
+co_message_queue_t co_outgoing_messages;
+co_message_queue_t co_incoming_messages;
+co_message_queue_t *co_incoming_queued_messages;
+
+#ifdef CONFIG_COLINUX_STATS
+co_proc_counts_t co_proc_counts;
+#endif
+
+void __init co_start_kernel(void)
+{
+ memcpy(&co_boot_params, co_passage_page->params, sizeof(co_boot_params));
+
+ co_arch_start_kernel();
+
+ /* should never be reached */
+ co_terminate(CO_TERMINATE_END);
+}
+
+void co_send_message(co_module_t from,
+ co_module_t to,
+ co_priority_t priority,
+ co_message_type_t type,
+ unsigned long size,
+ const char *data)
+{
+ unsigned long flags;
+ co_message_t *buffer;
+
+ BUG_ON((sizeof(co_message_t) + size) > CO_VPTR_IO_AREA_SIZE - sizeof(co_io_buffer_t));
+
+ buffer = co_send_message_save(&flags);
+ if (!buffer)
+ return;
+
+ buffer->from = from;
+ buffer->to = to;
+ buffer->priority = priority;
+ buffer->type = type;
+ buffer->size = size;
+ memcpy(buffer->data, data, size);
+
+ co_send_message_restore(flags);
+}
+
+static void co_message_add_to_incoming(co_message_t *message, unsigned long size)
+{
+ co_message_node_t *message_copy;
+
+ message_copy = kmalloc(size + sizeof(co_message_node_t) - sizeof(co_message_t),
+ GFP_ATOMIC);
+ if (!message_copy)
+ return;
+
+ memcpy(&message_copy->msg, message, size);
+ list_add_tail(&message_copy->node, &co_incoming_messages.list);
+}
+
+static void co_handle_jiffies(long count)
+{
+ if (count > HZ) {
+ long secs = count / HZ;
+
+ /* 'warp_clock' for long distances */
+ write_seqlock(&xtime_lock);
+ xtime.tv_sec += secs;
+ count -= (secs * HZ);
+ update_xtime_cache(0);
+ write_sequnlock(&xtime_lock);
+ clock_was_set();
+ }
+
+ while (count > 0) {
+ irq_enter();
+ __do_IRQ(TIMER_IRQ);
+ irq_exit();
+ count--;
+ }
+}
+
+/* called with disabled interrupts */
+static void co_handle_incoming_message(co_message_node_t *node_message)
+{
+ co_linux_message_t *message;
+ co_message_queue_t *queue;
+ int irq;
+
+ message = (co_linux_message_t *)&node_message->msg.data;
+ switch (message->device) {
+ case CO_DEVICE_POWER: irq = POWER_IRQ; break;
+ case CO_DEVICE_KEYBOARD: irq = KEYBOARD_IRQ; break;
+#ifdef CONFIG_CONET_COOPERATIVE
+ case CO_DEVICE_NETWORK: irq = NETWORK_IRQ; break;
+#endif
+#ifdef CONFIG_SERIAL_COOPERATIVE
+ case CO_DEVICE_SERIAL: irq = SERIAL_IRQ; break;
+#endif
+ case CO_DEVICE_SCSI: irq = SCSI_IRQ; break;
+ case CO_DEVICE_MOUSE: irq = MOUSE_IRQ; break;
+ case CO_DEVICE_BLOCK: irq = BLOCKDEV_IRQ; break;
+ default:
+ BUG_ON((unsigned long)message->device >= (unsigned long)CO_DEVICES_TOTAL);
+ co_free_message(node_message);
+ return;
+ }
+
+ /* Add to the queue */
+ queue = &co_incoming_queued_messages[message->device];
+ list_add(&node_message->node, &queue->list);
+ queue->num_messages++;
+
+ irq_enter();
+ __do_IRQ(irq);
+ irq_exit();
+}
+
+static void co_handle_incoming_messages(void)
+{
+ if (!co_messages_active)
+ return;
+
+ /*
+ * Pop a message from the incoming queue.
+ */
+ while (!list_empty(&co_incoming_messages.list)) {
+ co_message_node_t *message;
+
+ message = list_entry(co_incoming_messages.list.next,
+ co_message_node_t, node);
+ BUG_ON((unsigned long)message->msg.from >= (unsigned long)CO_MODULES_MAX);
+ BUG_ON((unsigned long)message->msg.to >= (unsigned long)CO_MODULES_MAX);
+ list_del(&message->node);
+
+ /*
+ * Let the interrupt routine of the arch dependant code
+ * handle the message, and be responsible to free it.
+ */
+ co_handle_incoming_message(message);
+ }
+}
+
+void co_callback(struct pt_regs *regs)
+{
+ long io_size;
+ unsigned long new_jiffies;
+ struct pt_regs null_regs;
+
+ BUG_ON(!irqs_disabled());
+ if (co_passage_page->operation != CO_OPERATION_MESSAGE_FROM_MONITOR) {
+ co_passage_page_ref_down();
+ return;
+ }
+
+#ifdef CONFIG_COLINUX_STATS
+ co_proc_counts.switches[CO_OPERATION_MESSAGE_FROM_MONITOR]++;
+#endif
+ io_size = co_passage_page->params[0];
+ new_jiffies = co_passage_page->params[1];
+
+ if (co_messages_active && io_size > 0 && io_size <= CO_VPTR_IO_AREA_SIZE) {
+ static unsigned char temp_storage[CO_VPTR_IO_AREA_SIZE];
+ unsigned char *io_buffer = temp_storage;
+ unsigned char *io_buffer_end = &temp_storage[io_size];
+
+ /* Copy into temp, because kmalloc calls host to mapping pages */
+ memcpy(temp_storage, co_io_buffer->buffer, io_size);
+ co_io_buffer->messages_waiting = 0;
+ co_passage_page_ref_down();
+
+ while (io_buffer < io_buffer_end) {
+ co_message_t *message = (co_message_t *)io_buffer;
+ co_linux_message_t *linux_message = (co_linux_message_t *)message->data;
+ unsigned long size = message->size + sizeof(*message);
+
+ BUG_ON((unsigned long)message->from >= (unsigned long)CO_MODULES_MAX);
+ BUG_ON((unsigned long)message->to >= (unsigned long)CO_MODULES_MAX);
+ BUG_ON((unsigned long)linux_message->device >= (unsigned long)CO_DEVICES_TOTAL);
+
+ co_message_add_to_incoming(message, size);
+ io_buffer += size;
+ }
+ } else {
+ co_io_buffer->messages_waiting = 0;
+ co_passage_page_ref_down();
+ }
+
+ memset (&null_regs, 0, sizeof(null_regs));
+
+ /* Have only, if from proxy_interrupt_handler(), needs for user_mode() */
+ if (regs)
+ null_regs.cs = regs->cs;
+ set_irq_regs(&null_regs);
+
+ co_handle_jiffies(new_jiffies);
+ co_handle_incoming_messages();
+}
+
+void co_idle_processor(void)
+{
+ co_passage_page_assert_valid();
+ local_irq_disable();
+ co_passage_page_ref_up();
+ co_passage_page->operation = CO_OPERATION_IDLE;
+ co_switch_wrapper();
+ co_callback(NULL);
+ local_irq_enable();
+}
+
+void co_printk(const char *line, int size)
+{
+ unsigned long flags;
+ co_message_t *co_message;
+
+ co_message = co_send_message_save(&flags);
+ if (co_message) {
+ co_message->from = CO_MODULE_LINUX;
+ co_message->to = CO_MODULE_PRINTK;
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
+ co_message->type = CO_MESSAGE_TYPE_STRING;
+ if (size > 200)
+ size = 200;
+ co_message->size = size + 1;
+ memcpy(co_message->data, line, size);
+ co_message->data[size] = '\0';
+ co_send_message_restore(flags);
+ }
+}
+
+NORET_TYPE void co_terminate_panic(const char *text, int len)
+{
+ unsigned long flags;
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_TERMINATE;
+ co_passage_page->params[0] = CO_TERMINATE_PANIC;
+ co_passage_page->params[1] = 0;
+ co_passage_page->params[2] = 0;
+ co_passage_page->params[3] = len;
+ memcpy((char *)&co_passage_page->params[4], text, len+1);
+ co_switch_wrapper();
+ /* This doesn't never return. */
+}
+
+NORET_TYPE void co_terminate_bug(int code, int line, const char *file)
+{
+ unsigned long flags;
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_TERMINATE;
+ co_passage_page->params[0] = CO_TERMINATE_BUG;
+ co_passage_page->params[1] = code;
+ co_passage_page->params[2] = line;
+ co_passage_page->params[3] = strlen(file);
+ strcpy((char *)&co_passage_page->params[4], file);
+ co_switch_wrapper();
+ /* This doesn't never return. */
+}
+EXPORT_SYMBOL(co_terminate_bug);
+
+NORET_TYPE void co_terminate(co_termination_reason_t reason)
+{
+ unsigned long flags;
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_TERMINATE;
+ co_passage_page->params[0] = reason;
+ co_passage_page->params[3] = 0; /* len */
+ co_switch_wrapper();
+ /* This doesn't never return. */
+}
+EXPORT_SYMBOL(co_terminate);
+
+unsigned long co_get_host_time(void)
+{
+ unsigned long flags;
+ unsigned long time;
+
+ co_passage_page_assert_valid();
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_GET_TIME;
+ co_switch_wrapper();
+ time = co_passage_page->params[0];
+ co_passage_page_release(flags);
+
+ return time;
+}
+
+int co_get_message(co_message_node_t **message, co_device_t device)
+{
+ co_message_queue_t *queue;
+ co_message_node_t *node;
+ unsigned long flags;
+
+ if (!co_messages_active)
+ return 0;
+
+ local_irq_save(flags);
+ queue = &co_incoming_queued_messages[device];
+ if (list_empty(&queue->list)) {
+ local_irq_restore(flags);
+ return 0;
+ }
+
+ node = list_entry(queue->list.prev, co_message_node_t, node);
+ list_del(&node->node);
+ queue->num_messages--;
+ local_irq_restore(flags);
+
+ *message = node;
+ return 1;
+}
+
+co_info_t co_info = {
+ .api_version = CO_LINUX_API_VERSION,
+ .compiler_major = __GNUC__,
+ .compiler_minor = __GNUC_MINOR__,
+ .compiler_abi = __GXX_ABI_VERSION,
+};
+
+static int __init initcall_message_queues(void)
+{
+ int queue_index;
+
+ INIT_LIST_HEAD(&co_outgoing_messages.list);
+ INIT_LIST_HEAD(&co_incoming_messages.list);
+
+ co_incoming_queued_messages =
+ kmalloc(sizeof(co_message_queue_t) * CO_DEVICES_TOTAL, GFP_KERNEL);
+ if (!co_incoming_queued_messages)
+ panic("unable to allocate message queues\n");
+
+ for (queue_index=0; queue_index < CO_DEVICES_TOTAL; queue_index++) {
+ co_message_queue_t *queue = &co_incoming_queued_messages[queue_index];
+ queue->num_messages = 0;
+ INIT_LIST_HEAD(&queue->list);
+ }
+
+ co_messages_active = 1;
+
+ return 0;
+}
+
+
+void co_free_pages(unsigned long vaddr, int pages)
+{
+ unsigned long flags;
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_FREE_PAGES;
+ co_passage_page->params[0] = vaddr;
+ co_passage_page->params[1] = pages;
+ co_switch_wrapper();
+ co_passage_page_release(flags);
+}
+
+int co_alloc_pages(unsigned long vaddr, int size)
+{
+ unsigned long flags;
+ long result;
+
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_ALLOC_PAGES;
+ co_passage_page->params[0] = vaddr;
+ co_passage_page->params[1] = size;
+ co_switch_wrapper();
+ result = (long)co_passage_page->params[4];
+ co_passage_page_release(flags);
+
+ if (result < 0)
+ return -ENOMEM;
+
+ return 0;
+}
+
+__initcall(initcall_message_queues);
+
+#ifdef CONFIG_COLINUX_STATS
+static int co_guest_read_status(char *page, char **start, off_t off, int count, int *eof, void *clear)
+{
+ co_proc_counts_t hold;
+ int len;
+
+ local_irq_disable();
+ hold = co_proc_counts;
+ if (clear)
+ memset(&co_proc_counts, 0, sizeof(co_proc_counts));
+ local_irq_enable();
+
+ len = sprintf(page, "idle:\t%lu\n"
+ "msgto:\t%lu\n"
+ "mfrom:\t%lu\n"
+ "intr:\t%lu\n"
+ "dev:\t%lu\n"
+ "time:\t%lu\n"
+ "hpt:\t%lu\n"
+ "free:\t%lu\n"
+ "alloc:\t%lu\n"
+ "getpp:\t%lu\n",
+ hold.switches[CO_OPERATION_IDLE],
+ hold.switches[CO_OPERATION_MESSAGE_TO_MONITOR],
+ hold.switches[CO_OPERATION_MESSAGE_FROM_MONITOR],
+ hold.switches[CO_OPERATION_FORWARD_INTERRUPT],
+ hold.switches[CO_OPERATION_DEVICE],
+ hold.switches[CO_OPERATION_GET_TIME],
+ hold.switches[CO_OPERATION_GET_HIGH_PREC_TIME],
+ hold.switches[CO_OPERATION_FREE_PAGES],
+ hold.switches[CO_OPERATION_ALLOC_PAGES],
+ hold.switches[CO_OPERATION_GETPP]);
+
+ return len;
+}
+
+static __init int co_create_proc_stats(void)
+{
+ struct proc_dir_entry *co_guest_dir;
+
+ co_guest_dir = proc_mkdir("colinux", NULL);
+ if(co_guest_dir) {
+ create_proc_read_entry("stats",
+ 0444, co_guest_dir,
+ co_guest_read_status, NULL);
+ create_proc_read_entry("stats_clear",
+ 0444, co_guest_dir,
+ co_guest_read_status, (void*)1);
+ }
+
+ return 0;
+}
+
+__initcall(co_create_proc_stats);
+#endif /* CONFIG_COLINUX_STATS */
+
+CO_TRACE_CONTINUE;
Index: linux-2.6.26-source/kernel/panic.c
===================================================================
--- linux-2.6.26-source.orig/kernel/panic.c
+++ linux-2.6.26-source/kernel/panic.c
@@ -17,6 +17,7 @@
#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/nmi.h>
+#include <linux/cooperative_internal.h>
#include <linux/kexec.h>
#include <linux/debug_locks.h>
#include <linux/random.h>
@@ -77,11 +78,14 @@
bust_spinlocks(1);
va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
bust_spinlocks(0);
+ if (cooperative_mode_enabled())
+ co_terminate_panic(buf, i);
+
/*
* If we have crashed and we have a crash kernel loaded let it handle
* everything else.
Index: linux-2.6.26-source/kernel/printk.c
===================================================================
--- linux-2.6.26-source.orig/kernel/printk.c
+++ linux-2.6.26-source/kernel/printk.c
@@ -42,6 +42,8 @@
{
}
+#include <linux/cooperative_internal.h>
+
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
/* printk's without a loglevel use this.. */
@@ -718,6 +720,8 @@
printed_len += vscnprintf(printk_buf + printed_len,
sizeof(printk_buf) - printed_len, fmt, args);
+ co_printk(printk_buf, printed_len);
+
/*
* Copy the output into log_buf. If the caller didn't provide
* appropriate log level tags, we insert them here
Index: linux-2.6.26-source/mm/bootmem.c
===================================================================
--- linux-2.6.26-source.orig/mm/bootmem.c
+++ linux-2.6.26-source/mm/bootmem.c
@@ -12,6 +12,7 @@
#include <linux/pfn.h>
#include <linux/bootmem.h>
#include <linux/module.h>
+#include <linux/cooperative_internal.h>
#include <asm/bug.h>
#include <asm/io.h>
@@ -365,6 +366,23 @@
for (i = start; i < start + areasize; i++)
if (unlikely(test_and_set_bit(i, node_bootmem_map)))
BUG();
+
+ if (cooperative_mode_enabled()) {
+ unsigned long alloc_address = (unsigned long)ret;
+ unsigned long alloc_size = size;
+ int result;
+
+ alloc_size += (alloc_address & (~PAGE_MASK));
+ alloc_address &= PAGE_MASK;
+ alloc_size = (alloc_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ result = co_alloc_pages(alloc_address, alloc_size);
+ if (result) {
+ free_bootmem((unsigned long)ret, size);
+ return NULL;
+ }
+ }
+
memset(ret, 0, size);
return ret;
}
Index: linux-2.6.26-source/mm/page_alloc.c
===================================================================
--- linux-2.6.26-source.orig/mm/page_alloc.c
+++ linux-2.6.26-source/mm/page_alloc.c
@@ -46,6 +46,7 @@
#include <linux/page-isolation.h>
#include <linux/memcontrol.h>
#include <linux/debugobjects.h>
+#include <linux/cooperative_internal.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -301,10 +302,44 @@
}
}
+static int co_persistent_alloc_pages(unsigned long address, int size)
+{
+ int result, retries_left;
+
+ for (retries_left = 10; retries_left > 0; retries_left--) {
+ result = co_alloc_pages(address, size);
+ if (result) {
+ unsigned long cache_size;
+ /*
+ * Whoops, we have allocated too much of the
+ * host OS's memory, time to free some cache.
+ * cache.
+ */
+ cache_size = global_page_state(NR_FILE_PAGES)-total_swapcache_pages;
+ cache_size /= 2;
+ if (cache_size < size*2)
+ cache_size = size*2;
+ shrink_all_memory(cache_size);
+ } else {
+ return 0;
+ }
+ }
+
+ return result;
+
+}
+
static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
{
int i;
+ if (cooperative_mode_enabled() &&
+ !TestSetPageCoHostMapped(page)) {
+ int result;
+ result = co_persistent_alloc_pages((unsigned long)page_address(page), 1 << order);
+ BUG_ON(result != 0);
+ }
+
/*
* clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
* and __GFP_HIGHMEM from hard or soft interrupt context.
@@ -417,6 +452,11 @@
int order_size = 1 << order;
int migratetype = get_pageblock_migratetype(page);
+ if (cooperative_mode_enabled()) {
+ co_free_pages((unsigned long)page_address(page), order_size);
+ ClearPageCoHostMapped(page);
+ }
+
if (unlikely(PageCompound(page)))
destroy_compound_page(page, order);
@@ -1632,7 +1672,16 @@
dump_stack();
show_mem();
}
+ return NULL;
got_pg:
+ if (cooperative_mode_enabled() &&
+ !TestSetPageCoHostMapped(page)) {
+ int result = co_persistent_alloc_pages((unsigned long)page_address(page), 1 << order);
+ if (result) {
+ __free_pages(page, order);
+ return NULL;
+ }
+ }
return page;
}
Index: linux-2.6.26-source/mm/vmscan.c
===================================================================
--- linux-2.6.26-source.orig/mm/vmscan.c
+++ linux-2.6.26-source/mm/vmscan.c
@@ -1722,7 +1722,7 @@
wake_up_interruptible(&pgdat->kswapd_wait);
}
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) || defined(CONFIG_COOPERATIVE)
/*
* Helper function for shrink_all_memory(). Tries to reclaim 'nr_pages' pages
* from LRU lists system-wide, for given pass and priority, and returns the
Index: linux-2.6.26-source/drivers/char/mem.c
===================================================================
--- linux-2.6.26-source.orig/drivers/char/mem.c
+++ linux-2.6.26-source/drivers/char/mem.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/crash_dump.h>
+#include <linux/cooperative_internal.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
#include <linux/splice.h>
@@ -120,6 +121,9 @@
ssize_t read, sz;
char *ptr;
+ if (cooperative_mode_enabled())
+ return -ENOMEM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
read = 0;
@@ -188,6 +192,9 @@
unsigned long copied;
void *ptr;
+ if (cooperative_mode_enabled())
+ return -ENOMEM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
@@ -333,6 +340,9 @@
{
size_t size = vma->vm_end - vma->vm_start;
+ if (cooperative_mode_enabled())
+ return -EFAULT;
+
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
return -EINVAL;
@@ -369,6 +379,9 @@
{
unsigned long pfn;
+ if (cooperative_mode_enabled())
+ return -EFAULT;
+
/* Turn a kernel-virtual address into a physical page frame */
pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
@@ -435,6 +448,9 @@
ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+ if (cooperative_mode_enabled())
+ return -ENOMEM;
+
read = 0;
if (p < (unsigned long) high_memory) {
low_count = count;
@@ -584,6 +600,9 @@
ssize_t written;
char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+ if (cooperative_mode_enabled())
+ return -ENOMEM;
+
if (p < (unsigned long) high_memory) {
wrote = count;
Index: linux-2.6.26-source/arch/x86/kernel/cpu/bugs.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/cpu/bugs.c
+++ linux-2.6.26-source/arch/x86/kernel/cpu/bugs.c
@@ -25,6 +25,8 @@
__setup("no-hlt", no_halt);
+// Ignore, if have no emulation compiled in
+#ifdef CONFIG_MATH_EMULATION
static int __init no_387(char *s)
{
boot_cpu_data.hard_math = 0;
@@ -33,6 +35,7 @@
}
__setup("no387", no_387);
+#endif
static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0;
Index: linux-2.6.26-source/arch/x86/kernel/reboot_cooperative.c
===================================================================
--- /dev/null
+++ linux-2.6.26-source/arch/x86/kernel/reboot_cooperative.c
@@ -0,0 +1,133 @@
+/*
+ * linux/arch/x86/kernel/reboot_cooperative.c
+ */
+
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/kthread.h>
+#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+#include <linux/cooperative_internal.h>
+
+/* sys_reboot needs this dummy. */
+void (*pm_power_off)(void);
+
+/*
+ * This is a hack to make ctrl_alt_del work as a poweroff, so the OS can be
+ * notified, unmount and sync everything.
+ */
+static int co_powering_off;
+
+static int co_powerd(void *__unused)
+{
+ extern char * envp_init[];
+ static char *const argv_shutdown[]= { "/sbin/shutdown", "-h", "now", NULL };
+ static char *const argv_halt[]= { "/sbin/halt", NULL };
+
+ if (kernel_execve(argv_shutdown[0], argv_shutdown, envp_init) >= 0)
+ return 0;
+ printk(KERN_INFO "%s spawn failed\n", argv_shutdown[0]);
+
+ if (kernel_execve(argv_halt[0], argv_halt, envp_init) >= 0)
+ return 0;
+ printk(KERN_INFO "%s spawn failed\n", argv_halt[0]);
+
+ printk(KERN_INFO "Fallback into reboot and power off\n");
+ co_powering_off++;
+ ctrl_alt_del();
+
+ return 0;
+}
+
+static void deferred_shutdown(struct work_struct *dummy)
+{
+ kthread_run(co_powerd, NULL, "copowerd");
+}
+
+/*
+ * This function will call from interrupt context.
+ */
+static void co_shedule_shutdown(void)
+{
+ static DECLARE_WORK(shutdown_work, deferred_shutdown);
+
+ schedule_work(&shutdown_work);
+}
+
+
+static void co_machine_restart(void)
+{
+ co_terminate(CO_TERMINATE_REBOOT);
+}
+
+void machine_power_off(void)
+{
+ co_terminate(CO_TERMINATE_POWEROFF);
+}
+
+void machine_shutdown(void)
+{
+ co_terminate(CO_TERMINATE_HALT);
+}
+
+void machine_emergency_restart(void)
+{
+ co_machine_restart();
+}
+
+void machine_restart(char *cmd)
+{
+ if (co_powering_off)
+ machine_power_off();
+ else
+ co_machine_restart();
+}
+
+void machine_halt(void)
+{
+ co_terminate(CO_TERMINATE_HALT);
+}
+
+static irqreturn_t power_interrupt(int irq, void *dev_id)
+{
+ co_message_node_t *node_message;
+
+ if (co_get_message(&node_message, CO_DEVICE_POWER)) {
+ co_linux_message_t *message;
+ co_linux_message_power_t *type;
+
+ message = (co_linux_message_t *)&node_message->msg.data;
+ type = (co_linux_message_power_t *)message->data;
+ switch (type->type) {
+ case CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL:
+ ctrl_alt_del();
+ break;
+ case CO_LINUX_MESSAGE_POWER_SHUTDOWN:
+ co_shedule_shutdown();
+ break;
+ case CO_LINUX_MESSAGE_POWER_OFF:
+ machine_power_off();
+ break;
+ default:
+ printk(KERN_ERR "power interrupt: buggy type %d\n", type->type);
+ }
+ co_free_message(node_message);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init co_power_init(void)
+{
+ int rc;
+
+ rc = request_irq(POWER_IRQ, &power_interrupt, IRQF_SAMPLE_RANDOM, "power", NULL);
+ if (rc) {
+ printk(KERN_ERR "POWER: unable to get irq %d", POWER_IRQ);
+ return rc;
+ }
+
+ return 0;
+}
+
+__initcall(co_power_init);
Index: linux-2.6.26-source/arch/x86/mach-default/setup.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/mach-default/setup.c
+++ linux-2.6.26-source/arch/x86/mach-default/setup.c
@@ -142,6 +142,7 @@
late_initcall(print_ipi_mode);
+#ifndef CONFIG_COOPERATIVE
/**
* machine_specific_memory_setup - Hook for machine specific memory setup.
*
@@ -184,3 +185,4 @@
}
return who;
}
+#endif /* !CONFIG_COOPERATIVE */
Index: linux-2.6.26-source/arch/x86/kernel/i8259_cooperative.c
===================================================================
--- /dev/null
+++ linux-2.6.26-source/arch/x86/kernel/i8259_cooperative.c
@@ -0,0 +1,101 @@
+/*
+ * linux/arch/x86/kernel/i8259_cooperative.c
+ */
+
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cooperative_internal.h>
+
+#include <asm/irq.h>
+#include <asm/desc.h>
+#include <asm/arch_hooks.h>
+
+CO_TRACE_STOP;
+
+/* Function must have the same prototype as do_IRQ() */
+void proxy_interrupt_handler(struct pt_regs *regs)
+{
+ co_passage_page_assert_valid();
+ co_passage_page_ref_up();
+ co_passage_page->operation = CO_OPERATION_FORWARD_INTERRUPT;
+ co_passage_page->params[0] = (~regs->orig_ax) + 0x20; /* IRQ number */
+ co_passage_page->host_state.flags &= ~(1 << 9); /* Turn IF off */
+ co_switch_wrapper();
+ co_callback(regs);
+}
+
+CO_TRACE_CONTINUE;
+
+/*
+ * Not like you have any other choice other than using
+ * COPIC in Cooperative mode.
+ */
+
+static void end_COPIC_irq(unsigned int irq)
+{
+}
+
+static void mask_and_ack_COPIC(unsigned int irq)
+{
+}
+
+static unsigned int startup_COPIC_irq(unsigned int irq)
+{
+ return 0;
+}
+
+#define shutdown_COPIC_irq disable_COPIC_irq
+
+static void disable_COPIC_irq(unsigned int irq)
+{
+}
+
+static void enable_COPIC_irq(unsigned int irq)
+{
+}
+
+static struct irq_chip co_pic_irq_chip = {
+ .name = "COPIC",
+ .startup = startup_COPIC_irq,
+ .shutdown = shutdown_COPIC_irq,
+ .enable = enable_COPIC_irq,
+ .disable = disable_COPIC_irq,
+ .mask_ack = mask_and_ack_COPIC,
+ .end = end_COPIC_irq,
+ .set_affinity = NULL
+};
+
+/* Called from pre_intr_init_hook */
+void __init init_ISA_irqs (void)
+{
+ int i;
+
+ printk("Setting proxy interrupt vectors\n");
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+
+ set_irq_chip_and_handler_name(i, &co_pic_irq_chip, handle_simple_irq, "CO");
+ }
+
+}
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ /* all the set up before the call gates are initialised */
+ pre_intr_init_hook();
+
+ /*
+ * Cover the whole vector space, no vector can escape us.
+ */
+ for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
+ int vector = FIRST_EXTERNAL_VECTOR + i;
+ if (i >= NR_IRQS)
+ break;
+ if (vector != SYSCALL_VECTOR)
+ set_intr_gate(vector, interrupt[i]);
+ }
+}
Index: linux-2.6.26-source/arch/x86/kernel/ioport_cooperative.c
===================================================================
--- /dev/null
+++ linux-2.6.26-source/arch/x86/kernel/ioport_cooperative.c
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/x86/kernel/ioport_cooperative.c
+ */
+
+#include <linux/syscalls.h>
+
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+{
+ return -EPERM;
+}
+
+asmlinkage long sys_iopl(unsigned long unused)
+{
+ return -EPERM;
+}
Index: linux-2.6.26-source/lib/iomap.c
===================================================================
--- linux-2.6.26-source.orig/lib/iomap.c
+++ linux-2.6.26-source/lib/iomap.c
@@ -59,6 +59,7 @@
bad_io_access(port, #is_pio ); \
} while (0)
+#ifndef CONFIG_COOPERATIVE
#ifndef pio_read16be
#define pio_read16be(port) swab16(inw(port))
#define pio_read32be(port) swab32(inl(port))
@@ -224,6 +225,7 @@
EXPORT_SYMBOL(iowrite8_rep);
EXPORT_SYMBOL(iowrite16_rep);
EXPORT_SYMBOL(iowrite32_rep);
+#endif
/* Create a virtual mapping cookie for an IO port range */
void __iomem *ioport_map(unsigned long port, unsigned int nr)
Index: linux-2.6.26-source/drivers/char/Kconfig
===================================================================
--- linux-2.6.26-source.orig/drivers/char/Kconfig
+++ linux-2.6.26-source/drivers/char/Kconfig
@@ -1091,6 +1091,7 @@
config DEVPORT
bool
depends on !M68K
+ depends on !COOPERATIVE
depends on ISA || PCI
default y
Index: linux-2.6.26-source/drivers/crypto/Kconfig
===================================================================
--- linux-2.6.26-source.orig/drivers/crypto/Kconfig
+++ linux-2.6.26-source/drivers/crypto/Kconfig
@@ -52,6 +52,7 @@
config CRYPTO_DEV_GEODE
tristate "Support for the Geode LX AES engine"
depends on X86_32 && PCI
+ depends on !COOPERATIVE
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
help
Index: linux-2.6.26-source/drivers/usb/Kconfig
===================================================================
--- linux-2.6.26-source.orig/drivers/usb/Kconfig
+++ linux-2.6.26-source/drivers/usb/Kconfig
@@ -17,6 +17,7 @@
# NOTE: SL-811 option should be board-specific ...
config USB_ARCH_HAS_HCD
boolean
+ depends on !COOPERATIVE
default y if USB_ARCH_HAS_OHCI
default y if USB_ARCH_HAS_EHCI
default y if PCMCIA && !M32R # sl811_cs
@@ -27,6 +28,7 @@
# many non-PCI SOC chips embed OHCI
config USB_ARCH_HAS_OHCI
boolean
+ depends on !COOPERATIVE
# ARM:
default y if SA1111
default y if ARCH_OMAP
@@ -52,6 +54,7 @@
# some non-PCI hcds implement EHCI
config USB_ARCH_HAS_EHCI
boolean
+ depends on !COOPERATIVE
default y if PPC_83xx
default y if SOC_AU1200
default y if ARCH_IXP4XX
Index: linux-2.6.26-source/arch/x86/mm/comap.c
===================================================================
--- /dev/null
+++ linux-2.6.26-source/arch/x86/mm/comap.c
@@ -0,0 +1,130 @@
+
+/*
+ * This source code is a part of coLinux source package.
+ *
+ * Copyright (C) 2008 Steve Shoecraft <sshoecraft@earthlink.net>
+ *
+ * The code is licensed under the GPL. See the COPYING file in
+ * the root directory.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+
+#include <linux/cooperative.h>
+#include <linux/cooperative_internal.h>
+
+static unsigned long *get_pp(void *host_buffer, int size) {
+ unsigned long *pp, flags;
+ int npages,pp_size,rc;
+
+ /* Get # of pages */
+ npages = size >> PAGE_SHIFT;
+ if ((npages * PAGE_SIZE) < size) npages++;
+
+ /* Alloc mem for phys pages */
+ pp_size = npages * sizeof(unsigned long);
+ pp = kmalloc(pp_size, GFP_KERNEL);
+ if (!pp) {
+ printk(KERN_ERR "co_map_buffer: error allocating memory for physical pages!\n");
+ return 0;
+ }
+
+ /* Request physical pages from the host */
+ co_passage_page_assert_valid();
+ co_passage_page_acquire(&flags);
+ co_passage_page->operation = CO_OPERATION_GETPP;
+ co_passage_page->params[0] = (unsigned long) pp;
+ co_passage_page->params[1] = (unsigned long) host_buffer;
+ co_passage_page->params[2] = size;
+ co_switch_wrapper();
+ rc = co_passage_page->params[0];
+ co_passage_page_release(flags);
+ if (rc) {
+ printk(KERN_ERR "co_map_buffer: error getting physical pages from host!\n");
+ return 0;
+ }
+
+ return pp;
+}
+
+#define VM_OPTS VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_PFNMAP | VM_RAND_READ
+
+void *co_map_buffer(void *host_buffer, int size) {
+ unsigned long addr, *pp, *pd, *pt, pa;
+ struct vm_struct *area;
+ void *buffer;
+ int i,npages,pd_index,pt_index;
+
+ /* Get the physical pages for the host buffer */
+ pp = get_pp(host_buffer, size);
+ if (!pp) return 0;
+
+ /* Get an area of virtual memory */
+ area = get_vm_area(size, VM_OPTS);
+ buffer = area->addr;
+
+ npages = size >> PAGE_SHIFT;
+
+ addr = (unsigned long) buffer;
+ pd = (unsigned long *) init_mm.pgd;
+ while(npages) {
+ /* Get pt */
+ pd_index = pgd_index(addr);
+ if (pd[pd_index] != 0) {
+ pa = pd[pd_index] & PAGE_MASK;
+ pt = __va(CO_P_TO_PP(pa));
+ } else {
+ pt = (unsigned long *) kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!pt) {
+ printk(KERN_ERR "co_map_buffer: unable to alloc new pt entry!\n");
+ return 0;
+ }
+ memset(pt, 0, PAGE_SIZE);
+ pa = CO_PP_TO_P(__pa(pt)) | _PAGE_TABLE;
+ pd[pd_index] = pa;
+ }
+
+ /* Fill pt */
+ pt_index = pte_index(addr);
+ for(i=pt_index; i < 1024; i++) {
+ if (!npages) break;
+ BUG_ON(pt[i] != 0);
+ pt[i] = *pp | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_DIRTY | _PAGE_ACCESSED;
+ pp++;
+ addr += PAGE_SIZE;
+ npages--;
+ }
+ }
+
+ return buffer;
+}
+
+#if 0
+void dump_pt(void *buf, int size) {
+ unsigned long addr, *pd, *pt;
+ int x, pd_index, pt_index, npages;
+
+ npages = size >> PAGE_SHIFT;
+
+ addr = (unsigned long) buf;
+ pd = (unsigned long *) __va(read_cr3());
+ printk(KERN_INFO "pd: %p\n", pd);
+ while(npages) {
+ pd_index = pgd_index(addr);
+ printk(KERN_INFO "pd[%04d]: %lx\n", pd_index, pd[pd_index]);
+ BUG_ON(pd[pd_index] == 0);
+ pt = __va(CO_P_TO_PP(pd[pd_index] & PAGE_MASK));
+ pt_index = pte_index(addr);
+ for(x=pt_index; x < 1024; x++) {
+ if (!npages) break;
+ printk(KERN_INFO "%04d: pt[%04d]: %08lx\n", npages, x, pt[x]);
+ addr += PAGE_SIZE;
+ npages--;
+ }
+ }
+}
+#endif
Index: linux-2.6.26-source/include/linux/page-flags.h
===================================================================
--- linux-2.6.26-source.orig/include/linux/page-flags.h
+++ linux-2.6.26-source/include/linux/page-flags.h
@@ -93,6 +93,9 @@
PG_mappedtodisk, /* Has blocks allocated on-disk */
PG_reclaim, /* To be reclaimed asap */
PG_buddy, /* Page is free, on buddy lists */
+#ifdef CONFIG_COOPERATIVE
+ PG_co_host_mapped, /* Page is mapped on colinux host */
+#endif
#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
PG_uncached, /* Page has been mapped as uncached */
#endif
@@ -195,6 +198,10 @@
PAGEFLAG_FALSE(Uncached)
#endif
+#ifdef CONFIG_COOPERATIVE
+CLEARPAGEFLAG(CoHostMapped, co_host_mapped) TESTSETFLAG(CoHostMapped, co_host_mapped)
+#endif
+
static inline int PageUptodate(struct page *page)
{
int ret = test_bit(PG_uptodate, &(page)->flags);
Index: linux-2.6.26-source/arch/x86/kernel/vmlinux_32.lds.S
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/vmlinux_32.lds.S
+++ linux-2.6.26-source/arch/x86/kernel/vmlinux_32.lds.S
@@ -37,6 +37,7 @@
} :text = 0x9090
/* read-only */
+ _kernel_start = .; /* colinux kernel entry */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
. = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */
*(.text.page_aligned)
Index: linux-2.6.26-source/include/asm-x86/fixmap_32.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/fixmap_32.h
+++ linux-2.6.26-source/include/asm-x86/fixmap_32.h
@@ -32,6 +32,7 @@
#include <linux/threads.h>
#include <asm/kmap_types.h>
#endif
+#include <asm/cooperative.h>
/*
* Here we define all the compile-time 'special' virtual
Index: linux-2.6.26-source/include/asm-x86/io_32.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/io_32.h
+++ linux-2.6.26-source/include/asm-x86/io_32.h
@@ -116,6 +116,9 @@
*/
static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
{
+#ifdef CONFIG_COOPERATIVE
+ panic("ioremap %ld:%ld\n", (long)offset, size);
+#endif
return ioremap_nocache(offset, size);
}
@@ -249,10 +252,18 @@
#endif /* __KERNEL__ */
+#ifdef CONFIG_COOPERATIVE
+static inline void native_io_delay(void)
+{
+ asm volatile("jmp 1f; 1: jmp 1f; 1:" : : : "memory");
+}
+static inline void io_delay_init(void) {}
+#else
extern void native_io_delay(void);
extern int io_delay_type;
extern void io_delay_init(void);
+#endif
#if defined(CONFIG_PARAVIRT)
#include <asm/paravirt.h>
Index: linux-2.6.26-source/include/asm-x86/mmzone_32.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/mmzone_32.h
+++ linux-2.6.26-source/include/asm-x86/mmzone_32.h
@@ -7,6 +7,7 @@
#define _ASM_MMZONE_H_
#include <asm/smp.h>
+#include <asm/cooperative.h>
#ifdef CONFIG_NUMA
extern struct pglist_data *node_data[];
Index: linux-2.6.26-source/include/asm-x86/pgtable_32.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/pgtable_32.h
+++ linux-2.6.26-source/include/asm-x86/pgtable_32.h
@@ -16,6 +16,7 @@
#include <asm/fixmap.h>
#include <linux/threads.h>
#include <asm/paravirt.h>
+#include <asm/cooperative.h>
#include <linux/bitops.h>
#include <linux/slab.h>
@@ -69,6 +70,8 @@
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE - 2 * PAGE_SIZE)
+#elif defined(CONFIG_COOPERATIVE)
+# define VMALLOC_END (CO_VPTR_BASE_START - 2 * PAGE_SIZE)
#else
# define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE)
#endif
@@ -156,10 +159,10 @@
#define pte_offset_kernel(dir, address) \
((pte_t *)pmd_page_vaddr(*(dir)) + pte_index((address)))
-#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+#define pmd_page(pmd) (pfn_to_page(CO_P_TO_PP(pmd_val((pmd))) >> PAGE_SHIFT))
#define pmd_page_vaddr(pmd) \
- ((unsigned long)__va(pmd_val((pmd)) & PTE_MASK))
+ ((unsigned long)__va(CO_P_TO_PP(pmd_val((pmd))) & PTE_MASK))
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \
Index: linux-2.6.26-source/kernel/sysctl.c
===================================================================
--- linux-2.6.26-source.orig/kernel/sysctl.c
+++ linux-2.6.26-source/kernel/sysctl.c
@@ -678,6 +678,7 @@
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+#if !defined(CONFIG_COOPERATIVE)
{
.ctl_name = CTL_UNNUMBERED,
.procname = "io_delay_type",
@@ -686,6 +687,7 @@
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+#endif /* !CONFIG_COOPERATIVE */
#endif
#if defined(CONFIG_MMU)
{
Index: linux-2.6.26-source/include/asm-x86/system.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/system.h
+++ linux-2.6.26-source/include/asm-x86/system.h
@@ -6,6 +6,7 @@
#include <asm/cpufeature.h>
#include <asm/cmpxchg.h>
#include <asm/nops.h>
+#include <asm/page.h>
#include <linux/kernel.h>
#include <linux/irqflags.h>
@@ -273,8 +274,22 @@
#define write_cr0(x) (native_write_cr0(x))
#define read_cr2() (native_read_cr2())
#define write_cr2(x) (native_write_cr2(x))
+#ifdef CONFIG_COOPERATIVE
+
+static inline unsigned long read_cr3(void)
+{
+ return CO_P_TO_PP(native_read_cr3());
+}
+
+static inline void write_cr3(unsigned long val)
+{
+ native_write_cr3(CO_PP_TO_P(val));
+}
+
+#else
#define read_cr3() (native_read_cr3())
#define write_cr3(x) (native_write_cr3(x))
+#endif
#define read_cr4() (native_read_cr4())
#define read_cr4_safe() (native_read_cr4_safe())
#define write_cr4(x) (native_write_cr4(x))
Index: linux-2.6.26-source/include/asm-x86/tlbflush.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/tlbflush.h
+++ linux-2.6.26-source/include/asm-x86/tlbflush.h
@@ -17,7 +17,11 @@
static inline void __native_flush_tlb(void)
{
+#ifdef CONFIG_COOPERATIVE
+ native_write_cr3(native_read_cr3());
+#else
write_cr3(read_cr3());
+#endif
}
static inline void __native_flush_tlb_global(void)
Index: linux-2.6.26-source/arch/x86/power/hibernate_32.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/power/hibernate_32.c
+++ linux-2.6.26-source/arch/x86/power/hibernate_32.c
@@ -64,7 +64,7 @@
if (!page_table)
return NULL;
- set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+ set_pmd(pmd, __pmd(CO_PP_TO_P(__pa(page_table)) | _PAGE_TABLE));
BUG_ON(page_table != pte_offset_kernel(pmd, 0));
Index: linux-2.6.26-source/arch/x86/kernel/i8237.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/i8237.c
+++ linux-2.6.26-source/arch/x86/kernel/i8237.c
@@ -23,6 +23,7 @@
static int i8237A_resume(struct sys_device *dev)
{
+#ifndef CONFIG_COOPERATIVE
unsigned long flags;
int i;
@@ -41,6 +42,7 @@
enable_dma(4);
release_dma_lock(flags);
+#endif
return 0;
}
Index: linux-2.6.26-source/arch/x86/mm/Makefile
===================================================================
--- linux-2.6.26-source.orig/arch/x86/mm/Makefile
+++ linux-2.6.26-source/arch/x86/mm/Makefile
@@ -15,3 +15,4 @@
obj-$(CONFIG_K8_NUMA) += k8topology_64.o
obj-$(CONFIG_ACPI_NUMA) += srat_64.o
endif
+obj-$(CONFIG_COOPERATIVE) += comap.o
Index: linux-2.6.26-source/include/asm-x86/pgalloc.h
===================================================================
--- linux-2.6.26-source.orig/include/asm-x86/pgalloc.h
+++ linux-2.6.26-source/include/asm-x86/pgalloc.h
@@ -4,6 +4,7 @@
#include <linux/threads.h>
#include <linux/mm.h> /* for struct page */
#include <linux/pagemap.h>
+#include <asm/cooperative.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
@@ -47,7 +48,7 @@
pmd_t *pmd, pte_t *pte)
{
paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
- set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+ set_pmd(pmd, __pmd(CO_PP_TO_P(__pa(pte)) | _PAGE_TABLE));
}
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
@@ -56,7 +57,7 @@
unsigned long pfn = page_to_pfn(pte);
paravirt_alloc_pte(mm, pfn);
- set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
+ set_pmd(pmd, __pmd(((pteval_t)CO_PFN_PP_TO_P(pfn) << PAGE_SHIFT) | _PAGE_TABLE));
}
#define pmd_pgtable(pmd) pmd_page(pmd)
Index: linux-2.6.26-source/arch/x86/kernel/process.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/process.c
+++ linux-2.6.26-source/arch/x86/kernel/process.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/pm.h>
+#include <linux/cooperative_internal.h>
struct kmem_cache *task_xstate_cachep;
@@ -59,6 +60,10 @@
*/
void cpu_idle_wait(void)
{
+ if (cooperative_mode_enabled()) {
+ co_terminate(CO_TERMINATE_INVALID_OPERATION);
+ return;
+ }
smp_mb();
/* kick all the CPUs so that they exit out of pm_idle */
smp_call_function(do_nothing, NULL, 0, 1);
Index: linux-2.6.26-source/arch/x86/kvm/Kconfig
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kvm/Kconfig
+++ linux-2.6.26-source/arch/x86/kvm/Kconfig
@@ -6,7 +6,7 @@
menuconfig VIRTUALIZATION
bool "Virtualization"
- depends on HAVE_KVM || X86
+ depends on (HAVE_KVM || X86) && !COOPERATIVE
default y
---help---
Say Y here to get to see options for using your Linux host to run other
Index: linux-2.6.26-source/arch/x86/kernel/pci-nommu.c
===================================================================
--- linux-2.6.26-source.orig/arch/x86/kernel/pci-nommu.c
+++ linux-2.6.26-source/arch/x86/kernel/pci-nommu.c
@@ -14,6 +14,7 @@
static int
check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
{
+#ifndef CONFIG_COOPERATIVE
if (hwdev && bus + size > *hwdev->dma_mask) {
if (*hwdev->dma_mask >= DMA_32BIT_MASK)
printk(KERN_ERR
@@ -22,6 +23,7 @@
(long long)*hwdev->dma_mask);
return 0;
}
+#endif
return 1;
}