aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-03-15 00:16:44 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-03-15 00:16:44 +0000
commit998e4cfacfe9217a1d96e9300fbce22cf7e8b6bb (patch)
treedae6b6e851344579442d3bb7b920cd7511854b0c
parentb500121df2e813156a8fe6220c1e0917be35744e (diff)
downloadxen-998e4cfacfe9217a1d96e9300fbce22cf7e8b6bb.tar.gz
xen-998e4cfacfe9217a1d96e9300fbce22cf7e8b6bb.tar.bz2
xen-998e4cfacfe9217a1d96e9300fbce22cf7e8b6bb.zip
bitkeeper revision 1.131 (3e7270ecL24hQl_PjDBYoS8hhB8GTA)
multicall.h: new file Many files: Multicall now available, so that Xen syscalls can be batched to amortise cost of trap to ring 0. Used by xenolinux to reduce the cost of a context switch.
-rw-r--r--.rootkeys1
-rw-r--r--xen/arch/i386/entry.S85
-rw-r--r--xen/arch/i386/mm.c33
-rw-r--r--xen/common/kernel.c2
-rw-r--r--xen/common/schedule.c8
-rw-r--r--xen/include/hypervisor-ifs/hypervisor-if.h259
-rw-r--r--xen/include/xeno/config.h2
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/hypervisor.c3
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c26
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/setup.c2
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c23
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h37
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h10
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/asm-xeno/multicall.h45
14 files changed, 385 insertions, 151 deletions
diff --git a/.rootkeys b/.rootkeys
index c0f10798ab..e1f67d7c3f 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -529,6 +529,7 @@
3e5a4e673p7PEOyHFm3nHkYX6HQYBg xenolinux-2.4.21-pre4-sparse/include/asm-xeno/irq.h
3e5a4e67zoNch27qYhEBpr2k6SABOg xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu.h
3e5a4e678ddsQOpbSiRdy1GRcDc9WA xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h
+3e7270deQqtGPSnFxcW4AvJZuTUWfg xenolinux-2.4.21-pre4-sparse/include/asm-xeno/multicall.h
3e5a4e67mnQfh-R8KcQCaVo2Oho6yg xenolinux-2.4.21-pre4-sparse/include/asm-xeno/page.h
3e5a4e67uTYU5oEnIDjxuaez8njjqg xenolinux-2.4.21-pre4-sparse/include/asm-xeno/pgalloc.h
3e5a4e67X7JyupgdYkgDX19Huj2sAw xenolinux-2.4.21-pre4-sparse/include/asm-xeno/pgtable-2level.h
diff --git a/xen/arch/i386/entry.S b/xen/arch/i386/entry.S
index cd49578168..436d12a8ff 100644
--- a/xen/arch/i386/entry.S
+++ b/xen/arch/i386/entry.S
@@ -79,6 +79,8 @@
*/
#include <xeno/config.h>
+#include <xeno/errno.h>
+#include <hypervisor-ifs/hypervisor-if.h>
#include <asm/smp.h>
EBX = 0x00
@@ -184,6 +186,77 @@ ENTRY(ret_from_newdomain)
jmp test_all_events
ALIGN
+/*
+ * HYPERVISOR_multicall(call_list, nr_calls)
+ * Execute a list of 'nr_calls' system calls, pointed at by 'call_list'.
+ * This is fairly easy except that:
+ * 1. We may fault reading the call list, and must patch that up; and
+ * 2. We cannot recursively call HYPERVISOR_multicall, or a malicious
+ * caller could cause our stack to blow up.
+ */
+stringstring:
+ .asciz "%08x %08x %08x %08x %08x %08x %d\n"
+do_multicall:
+ popl %eax
+ cmpl $SYMBOL_NAME(ret_from_hypervisor_call),%eax
+ jne multicall_exit /* bail if called recursively */
+ pushl %ebx
+ movl 4(%esp),%ebx /* EBX == call_list */
+ movl 8(%esp),%ecx /* ECX == nr_calls */
+multicall_loop:
+ pushl %ecx
+multicall_fault1:
+ pushl 20(%ebx)
+multicall_fault2:
+ pushl 16(%ebx)
+multicall_fault3:
+ pushl 12(%ebx)
+multicall_fault4:
+ pushl 8(%ebx)
+multicall_fault5:
+ pushl 4(%ebx)
+multicall_fault6:
+ movl (%ebx),%eax
+ andl $255,%eax
+ call *SYMBOL_NAME(hypervisor_call_table)(,%eax,4)
+ addl $20,%esp
+ popl %ecx
+ addl $BYTES_PER_MULTICALL_ENTRY,%ebx
+ loop multicall_loop
+ popl %ebx
+multicall_exit:
+ xorl %eax,%eax
+ jmp ret_from_hypervisor_call
+
+.section __ex_table,"a"
+ .align 4
+ .long multicall_fault1, multicall_fixup1
+ .long multicall_fault2, multicall_fixup2
+ .long multicall_fault3, multicall_fixup3
+ .long multicall_fault4, multicall_fixup4
+ .long multicall_fault5, multicall_fixup5
+ .long multicall_fault6, multicall_fixup6
+.previous
+
+.section .fixup,"ax"
+multicall_fixup6:
+ addl $4,%esp
+multicall_fixup5:
+ addl $4,%esp
+multicall_fixup4:
+ addl $4,%esp
+multicall_fixup3:
+ addl $4,%esp
+multicall_fixup2:
+ addl $4,%esp
+multicall_fixup1:
+ addl $4,%esp
+ popl %ebx
+ movl $-EFAULT,%eax
+ jmp ret_from_hypervisor_call
+.previous
+
+ ALIGN
restore_all:
RESTORE_ALL
@@ -194,7 +267,9 @@ ENTRY(hypervisor_call)
GET_CURRENT(%ebx)
andl $255,%eax
call *SYMBOL_NAME(hypervisor_call_table)(,%eax,4)
- movl %eax,EAX(%esp) # save the return value
+
+ret_from_hypervisor_call:
+ movl %eax,EAX(%esp) # save the return value
test_all_events:
mov PROCESSOR(%ebx),%eax
@@ -517,10 +592,11 @@ ENTRY(hypervisor_call_table)
.long SYMBOL_NAME(do_process_page_updates)
.long SYMBOL_NAME(do_console_write)
.long SYMBOL_NAME(do_set_gdt)
- .long SYMBOL_NAME(do_stack_and_ldt_switch)
+ .long SYMBOL_NAME(do_stack_switch)
+ .long SYMBOL_NAME(do_ldt_switch)
.long SYMBOL_NAME(do_net_update)
.long SYMBOL_NAME(do_fpu_taskswitch)
- .long SYMBOL_NAME(do_sched_op)
+ .long SYMBOL_NAME(do_yield)
.long SYMBOL_NAME(kill_domain)
.long SYMBOL_NAME(do_dom0_op)
.long SYMBOL_NAME(do_network_op)
@@ -530,6 +606,7 @@ ENTRY(hypervisor_call_table)
.long SYMBOL_NAME(do_update_descriptor)
.long SYMBOL_NAME(do_set_fast_trap)
.long SYMBOL_NAME(do_dom_mem_op)
- .rept NR_syscalls-(.-hypervisor_call_table)/4
+ .long SYMBOL_NAME(do_multicall)
+ .rept NR_syscalls-((.-hypervisor_call_table)/4)
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff --git a/xen/arch/i386/mm.c b/xen/arch/i386/mm.c
index 2d4d8ddf52..e330c092c6 100644
--- a/xen/arch/i386/mm.c
+++ b/xen/arch/i386/mm.c
@@ -97,8 +97,7 @@ void __init zap_low_mappings (void)
}
-long do_stack_and_ldt_switch(
- unsigned long ss, unsigned long esp, unsigned long ldts)
+long do_stack_switch(unsigned long ss, unsigned long esp)
{
int nr = smp_processor_id();
struct tss_struct *t = &init_tss[nr];
@@ -106,19 +105,6 @@ long do_stack_and_ldt_switch(
if ( (ss == __HYPERVISOR_CS) || (ss == __HYPERVISOR_DS) )
return -1;
- if ( ldts != current->mm.ldt_sel )
- {
- unsigned long *ptabent;
- ptabent = (unsigned long *)GET_GDT_ADDRESS(current);
- /* Out of range for GDT table? */
- if ( (ldts * 8) > GET_GDT_ENTRIES(current) ) return -1;
- ptabent += ldts * 2; /* 8 bytes per desc == 2 * unsigned long */
- /* Not an LDT entry? (S=0b, type =0010b) */
- if ( (*ptabent & 0x00001f00) != 0x00000200 ) return -1;
- current->mm.ldt_sel = ldts;
- __load_LDT(ldts);
- }
-
current->thread.ss1 = ss;
current->thread.esp1 = esp;
t->ss1 = ss;
@@ -128,6 +114,23 @@ long do_stack_and_ldt_switch(
}
+long do_ldt_switch(unsigned long ldts)
+{
+ unsigned long *ptabent;
+
+ ptabent = (unsigned long *)GET_GDT_ADDRESS(current);
+ /* Out of range for GDT table? */
+ if ( (ldts * 8) > GET_GDT_ENTRIES(current) ) return -1;
+ ptabent += ldts * 2; /* 8 bytes per desc == 2 * unsigned long */
+ /* Not an LDT entry? (S=0b, type =0010b) */
+ if ( ldts && ((*ptabent & 0x00001f00) != 0x00000200) ) return -1;
+ current->mm.ldt_sel = ldts;
+ __load_LDT(ldts);
+
+ return 0;
+}
+
+
long do_set_gdt(unsigned long *frame_list, int entries)
{
return -ENOSYS;
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index 28eaae9b51..0e4552fe11 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -533,7 +533,7 @@ int console_export(char *str, int len)
}
-long do_console_write(char *str, int count)
+long do_console_write(char *str, unsigned int count)
{
#define SIZEOF_BUF 256
unsigned char safe_str[SIZEOF_BUF];
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 92bade958f..3ef29e3c5c 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -148,12 +148,10 @@ int wake_up(struct task_struct *p)
}
/****************************************************************************
- * Domain requested scheduling operations
- * KAF: turn it back into do_yield()!
+ * Voluntarily yield the processor to another domain, until an event occurs.
****************************************************************************/
-long do_sched_op(void)
+long do_yield(void)
{
- /* XXX implement proper */
current->state = TASK_INTERRUPTIBLE;
schedule();
return 0;
@@ -519,7 +517,7 @@ void schedulers_start(void)
* Schedule timeout is used at a number of places and is a bit meaningless
* in the context of Xen, as Domains are not able to call these and all
* there entry points into Xen should be asynchronous. If a domain wishes
- * to block for a while it should use Xen's sched_op entry point.
+ * to block for a while it should use Xen's sched_op/yield entry point.
****************************************************************************/
static void process_timeout(unsigned long __data)
diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h
index 31cc8b18d8..797605e9c1 100644
--- a/xen/include/hypervisor-ifs/hypervisor-if.h
+++ b/xen/include/hypervisor-ifs/hypervisor-if.h
@@ -4,101 +4,64 @@
* Interface to Xeno hypervisor.
*/
-#include "network.h"
-#include "block.h"
-
#ifndef __HYPERVISOR_IF_H__
#define __HYPERVISOR_IF_H__
/*
- * Virtual addresses beyond this are not modifiable by guest OSes.
- * The machine->physical mapping table starts at this address, read-only
- * to all domains except DOM0.
+ * SEGMENT DESCRIPTOR TABLES
*/
-#define HYPERVISOR_VIRT_START (0xFC000000UL)
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
-#endif
-
-typedef struct trap_info_st
-{
- unsigned char vector; /* exception/interrupt vector */
- unsigned char dpl; /* privilege level */
- unsigned short cs; /* code selector */
- unsigned long address; /* code address */
-} trap_info_t;
-
-
-typedef struct
-{
-/*
- * PGREQ_XXX: specified in least-significant bits of 'ptr' field.
- * All requests specify relevent PTE or PT address in 'ptr'.
- * Normal requests specify update value in 'value'.
- * Extended requests specify command in least 8 bits of 'value'.
- */
-/* A normal page-table update request. */
-#define PGREQ_NORMAL 0
-/* Update an entry in the machine->physical mapping table. */
-#define PGREQ_MPT_UPDATE 1
-/* An extended command. */
-#define PGREQ_EXTENDED_COMMAND 2
-/* DOM0 can make entirely unchecked updates which do not affect refcnts. */
-#define PGREQ_UNCHECKED_UPDATE 3
- unsigned long ptr, val; /* *ptr = val */
-/* Announce a new top-level page table. */
-#define PGEXT_PIN_L1_TABLE 0
-#define PGEXT_PIN_L2_TABLE 1
-#define PGEXT_PIN_L3_TABLE 2
-#define PGEXT_PIN_L4_TABLE 3
-#define PGEXT_UNPIN_TABLE 4
-#define PGEXT_NEW_BASEPTR 5
-#define PGEXT_TLB_FLUSH 6
-#define PGEXT_INVLPG 7
-#define PGEXT_CMD_MASK 255
-#define PGEXT_CMD_SHIFT 8
-} page_update_request_t;
+/* 8 entries, plus a TSS entry for each CPU (up to 32 CPUs). */
+#define FIRST_DOMAIN_GDT_ENTRY 40
+/* These are flat segments for domain bootstrap and fallback. */
+#define FLAT_RING1_CS 0x11
+#define FLAT_RING1_DS 0x19
+#define FLAT_RING3_CS 0x23
+#define FLAT_RING3_DS 0x2b
/*
- * Segment descriptor tables.
+ * HYPERVISOR "SYSTEM CALLS"
*/
-/* 8 entries, plus a TSS entry for each CPU (up to 32 CPUs). */
-#define FIRST_DOMAIN_GDT_ENTRY 40
-/* These are flat segments for domain bootstrap and fallback. */
-#define FLAT_RING1_CS 0x11
-#define FLAT_RING1_DS 0x19
-#define FLAT_RING3_CS 0x23
-#define FLAT_RING3_DS 0x2b
-
/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
+#define __HYPERVISOR_set_trap_table 0
+#define __HYPERVISOR_pt_update 1
+#define __HYPERVISOR_console_write 2
+#define __HYPERVISOR_set_gdt 3
+#define __HYPERVISOR_stack_switch 4
+#define __HYPERVISOR_ldt_switch 5
+#define __HYPERVISOR_net_update 6
+#define __HYPERVISOR_fpu_taskswitch 7
+#define __HYPERVISOR_yield 8
+#define __HYPERVISOR_exit 9
+#define __HYPERVISOR_dom0_op 10
+#define __HYPERVISOR_network_op 11
+#define __HYPERVISOR_block_io_op 12
+#define __HYPERVISOR_set_debugreg 13
+#define __HYPERVISOR_get_debugreg 14
+#define __HYPERVISOR_update_descriptor 15
+#define __HYPERVISOR_set_fast_trap 16
+#define __HYPERVISOR_dom_mem_op 17
+#define __HYPERVISOR_multicall 18
+
+/* And the trap vector is... */
+#define TRAP_INSTR "int $0x82"
-#define __HYPERVISOR_set_trap_table 0
-#define __HYPERVISOR_pt_update 1
-#define __HYPERVISOR_console_write 2
-#define __HYPERVISOR_set_gdt 3
-#define __HYPERVISOR_stack_and_ldt_switch 4
-#define __HYPERVISOR_net_update 5
-#define __HYPERVISOR_fpu_taskswitch 6
-#define __HYPERVISOR_sched_op 7
-#define __HYPERVISOR_exit 8
-#define __HYPERVISOR_dom0_op 9
-#define __HYPERVISOR_network_op 10
-#define __HYPERVISOR_block_io_op 11
-#define __HYPERVISOR_set_debugreg 12
-#define __HYPERVISOR_get_debugreg 13
-#define __HYPERVISOR_update_descriptor 14
-#define __HYPERVISOR_set_fast_trap 15
-#define __HYPERVISOR_dom_mem_op 16
-#define TRAP_INSTR "int $0x82"
+/*
+ * MULTICALLS
+ *
+ * Multicalls are listed in an array, with each element being a fixed size
+ * (BYTES_PER_MULTICALL_ENTRY). Each is of the form (op, arg1, ..., argN)
+ * where each element of the tuple is a machine word.
+ */
+#define BYTES_PER_MULTICALL_ENTRY 32
-/* Event message note:
+/* EVENT MESSAGES
*
* Here, as in the interrupts to the guestos, additional network interfaces
- * are defined. These definitions server as placeholders for the event bits,
+ * are defined. These definitions server as placeholders for the event bits,
* however, in the code these events will allways be referred to as shifted
* offsets from the base NET events.
*/
@@ -113,14 +76,88 @@ typedef struct
/* Bit offsets, as opposed to the above masks. */
#define _EVENT_BLK_RESP 0
-#define _EVENT_TIMER 1
-#define _EVENT_DIE 2
-#define _EVENT_NET_TX 3
-#define _EVENT_NET_RX 4
-#define _EVENT_DEBUG 5
+#define _EVENT_TIMER 1
+#define _EVENT_DIE 2
+#define _EVENT_NET_TX 3
+#define _EVENT_NET_RX 4
+#define _EVENT_DEBUG 5
+
+
+/*
+ * Virtual addresses beyond this are not modifiable by guest OSes.
+ * The machine->physical mapping table starts at this address, read-only
+ * to all domains except DOM0.
+ */
+#define HYPERVISOR_VIRT_START (0xFC000000UL)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+
+/*
+ * PAGE UPDATE COMMANDS AND FLAGS
+ *
+ * PGREQ_XXX: specified in least-significant bits of 'ptr' field.
+ * All requests specify relevent PTE or PT address in 'ptr'.
+ * Normal requests specify update value in 'value'.
+ * Extended requests specify command in least 8 bits of 'value'.
+ */
+/* A normal page-table update request. */
+#define PGREQ_NORMAL 0
+/* Update an entry in the machine->physical mapping table. */
+#define PGREQ_MPT_UPDATE 1
+/* An extended command. */
+#define PGREQ_EXTENDED_COMMAND 2
+/* DOM0 can make entirely unchecked updates which do not affect refcnts. */
+#define PGREQ_UNCHECKED_UPDATE 3
+/* Announce a new top-level page table. */
+#define PGEXT_PIN_L1_TABLE 0
+#define PGEXT_PIN_L2_TABLE 1
+#define PGEXT_PIN_L3_TABLE 2
+#define PGEXT_PIN_L4_TABLE 3
+#define PGEXT_UNPIN_TABLE 4
+#define PGEXT_NEW_BASEPTR 5
+#define PGEXT_TLB_FLUSH 6
+#define PGEXT_INVLPG 7
+#define PGEXT_CMD_MASK 255
+#define PGEXT_CMD_SHIFT 8
+
+#ifndef __ASSEMBLY__
+
+#include "network.h"
+#include "block.h"
/*
+ * Send an array of these to HYPERVISOR_set_trap_table()
+ */
+typedef struct trap_info_st
+{
+ unsigned char vector; /* exception/interrupt vector */
+ unsigned char dpl; /* privilege level */
+ unsigned short cs; /* code selector */
+ unsigned long address; /* code address */
+} trap_info_t;
+
+/*
+ * Send an array of these to HYPERVISOR_pt_update()
+ */
+typedef struct
+{
+ unsigned long ptr, val; /* *ptr = val */
+} page_update_request_t;
+
+/*
+ * Send an array of these to HYPERVISOR_multicall()
+ */
+typedef struct
+{
+ unsigned long op;
+ unsigned long args[7];
+} multicall_entry_t;
+
+/*
+ * Xen/guestos shared data -- pointer provided in start_info.
* NB. We expect that this struct is smaller than a page.
*/
typedef struct shared_info_st {
@@ -150,36 +187,34 @@ typedef struct shared_info_st {
* registers, and executing 'iret'.
* This callback is provided with an extended stack frame, augmented
* with saved values for segment registers %ds and %es:
- * %ds, %es, %eip, %cs, %eflags [, %oldesp, %oldss]
+ * %ds, %es, %eip, %cs, %eflags [, %oldesp, %oldss]
* Code segment is the default flat selector.
* FAULTS WHEN CALLING THIS HANDLER WILL TERMINATE THE DOMAIN!!!
*/
unsigned long failsafe_address;
- /*
- * Time:
- * The following abstractions are exposed: System Time, Wall Clock
- * Time, Domain Virtual Time. Domains can access Cycle counter time
- * directly.
- * XXX RN: Need something to pass NTP scaling to GuestOS.
+ /*
+ * Time: The following abstractions are exposed: System Time, Clock Time,
+ * Domain Virtual Time. Domains can access Cycle counter time directly.
+ * XXX RN: Need something to pass NTP scaling to GuestOS.
*/
- u64 cpu_freq; /* to calculate ticks -> real time */
-
- /* System Time */
- long long system_time; /* in ns */
- unsigned long st_timestamp; /* cyclecounter at last update */
+ u64 cpu_freq; /* to calculate ticks -> real time */
- /* Wall Clock Time */
- u32 wc_version; /* a version number for info below */
- long tv_sec; /* essentially a struct timeval */
- long tv_usec;
- long long wc_timestamp; /* system time at last update */
+ /* System Time */
+ long long system_time; /* in ns */
+ unsigned long st_timestamp; /* cyclecounter at last update */
- /* Domain Virtual Time */
- unsigned long long domain_time;
+ /* Wall Clock Time */
+ u32 wc_version; /* a version number for info below */
+ long tv_sec; /* essentially a struct timeval */
+ long tv_usec;
+ long long wc_timestamp; /* system time at last update */
+
+ /* Domain Virtual Time */
+ unsigned long long domain_time;
- /*
+ /*
* Timeout values:
* Allow a domain to specify a timeout value in system time and
* domain virtual time.
@@ -193,18 +228,20 @@ typedef struct shared_info_st {
* NB. We expect that this struct is smaller than a page.
*/
typedef struct start_info_st {
- unsigned long nr_pages; /* total pages allocated to this domain */
- shared_info_t *shared_info; /* VIRTUAL address of shared info struct */
- unsigned long pt_base; /* VIRTUAL address of page directory */
- unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
- unsigned long mod_len; /* size (bytes) of pre-loaded module */
- net_ring_t *net_rings; /* network rings (VIRTUAL ADDRESS) */
+ unsigned long nr_pages; /* total pages allocated to this domain */
+ shared_info_t *shared_info; /* VIRTUAL address of shared info struct */
+ unsigned long pt_base; /* VIRTUAL address of page directory */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
+ unsigned long mod_len; /* size (bytes) of pre-loaded module */
+ net_ring_t *net_rings; /* network rings (VIRTUAL ADDRESS) */
int num_net_rings;
- unsigned long blk_ring; /* block io ring (MACHINE ADDRESS) */
- unsigned char cmd_line[1]; /* variable-length */
+ unsigned long blk_ring; /* block io ring (MACHINE ADDRESS) */
+ unsigned char cmd_line[1]; /* variable-length */
} start_info_t;
/* For use in guest OSes. */
extern shared_info_t *HYPERVISOR_shared_info;
+#endif /* !__ASSEMBLY__ */
+
#endif /* __HYPERVISOR_IF_H__ */
diff --git a/xen/include/xeno/config.h b/xen/include/xeno/config.h
index 08cc5cb0dd..3687748a0b 100644
--- a/xen/include/xeno/config.h
+++ b/xen/include/xeno/config.h
@@ -114,7 +114,7 @@
#define __GUEST_CS 0x11
#define __GUEST_DS 0x19
-#define NR_syscalls 255
+#define NR_syscalls 256
#define offsetof(_p,_f) ((unsigned long)&(((_p *)0)->_f))
#define struct_cpy(_x,_y) (memcpy((_x),(_y),sizeof(*(_x))))
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/hypervisor.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/hypervisor.c
index c49087173f..68670daa8c 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/hypervisor.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/hypervisor.c
@@ -13,6 +13,9 @@
#include <asm/system.h>
#include <asm/ptrace.h>
+multicall_entry_t multicall_list[8];
+int nr_multicall_ents = 0;
+
static unsigned long event_mask = 0;
void frobb(void) {}
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c
index a4e4cd2497..32ce1a66ab 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c
@@ -43,6 +43,7 @@
#include <asm/i387.h>
#include <asm/desc.h>
#include <asm/mmu_context.h>
+#include <asm/multicall.h>
#include <linux/irq.h>
@@ -85,7 +86,7 @@ void cpu_idle (void)
while (1) {
while (!current->need_resched)
- HYPERVISOR_do_sched_op(NULL);
+ HYPERVISOR_yield();
schedule();
check_pgt_cache();
}
@@ -334,9 +335,28 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
- unlazy_fpu(prev_p);
+ /*
+ * This is basically 'unlazy_fpu', except that we queue a multicall to
+ * indicate FPU task switch, rather than synchronously trapping to Xen.
+ */
+ if ( prev_p->flags & PF_USEDFPU )
+ {
+ if ( cpu_has_fxsr )
+ asm volatile( "fxsave %0 ; fnclex"
+ : "=m" (prev_p->thread.i387.fxsave) );
+ else
+ asm volatile( "fnsave %0 ; fwait"
+ : "=m" (prev_p->thread.i387.fsave) );
+ prev_p->flags &= ~PF_USEDFPU;
+ queue_multicall0(__HYPERVISOR_fpu_taskswitch);
+ }
+
+ if ( next->esp0 != 0 )
+ queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0);
- HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, next->esp0, 0);
+ /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */
+ execute_multicall_list();
+ sti(); /* matches 'cli' in switch_mm() */
/*
* Save away %fs and %gs. No need to save %es and %ds, as
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/setup.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/setup.c
index 1650d7028f..00c68a836f 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/setup.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/setup.c
@@ -967,7 +967,7 @@ void __init cpu_init (void)
BUG();
enter_lazy_tlb(&init_mm, current, nr);
- HYPERVISOR_stack_and_ldt_switch(__KERNEL_DS, current->thread.esp0, 0);
+ HYPERVISOR_stack_switch(__KERNEL_DS, current->thread.esp0);
/* Force FPU initialization. */
current->flags &= ~PF_USEDFPU;
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c
index 135ed5c066..93554c3420 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c
@@ -11,6 +11,7 @@
#include <asm/hypervisor.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/multicall.h>
/*
* This suffices to protect us if we ever move to SMP domains.
@@ -85,6 +86,28 @@ static void DEBUG_disallow_pt_read(unsigned long pa)
*/
unsigned long pt_baseptr;
+/*
+ * MULTICALL_flush_page_update_queue:
+ * This is a version of the flush which queues as part of a multicall.
+ */
+void MULTICALL_flush_page_update_queue(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&update_lock, flags);
+ if ( idx != 0 )
+ {
+#if PT_UPDATE_DEBUG > 1
+ printk("Flushing %d entries from pt update queue\n", idx);
+#endif
+#if PT_UPDATE_DEBUG > 0
+ DEBUG_allow_pt_reads();
+#endif
+ queue_multicall2(__HYPERVISOR_pt_update, update_queue, idx);
+ idx = 0;
+ }
+ spin_unlock_irqrestore(&update_lock, flags);
+}
+
static inline void __flush_page_update_queue(void)
{
#if PT_UPDATE_DEBUG > 1
diff --git a/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h
index 16f37cfe65..4b9591102c 100644
--- a/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h
+++ b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h
@@ -129,6 +129,7 @@ static inline int flush_page_update_queue(void)
return idx;
}
#define XENO_flush_page_update_queue() (_flush_page_update_queue())
+void MULTICALL_flush_page_update_queue(void);
/*
@@ -183,14 +184,24 @@ static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
return ret;
}
-static inline int HYPERVISOR_stack_and_ldt_switch(
- unsigned long ss, unsigned long esp, unsigned long ldts)
+static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_stack_and_ldt_switch),
- "b" (ss), "c" (esp), "d" (ldts) );
+ : "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
+ "b" (ss), "c" (esp) : "memory" );
+
+ return ret;
+}
+
+static inline int HYPERVISOR_ldt_switch(unsigned long ldts)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" (__HYPERVISOR_ldt_switch),
+ "b" (ldts) : "memory" );
return ret;
}
@@ -215,13 +226,12 @@ static inline int HYPERVISOR_fpu_taskswitch(void)
return ret;
}
-static inline int HYPERVISOR_do_sched_op(void *sched_op)
+static inline int HYPERVISOR_yield(void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- "b" (sched_op) );
+ : "=a" (ret) : "0" (__HYPERVISOR_yield) );
return ret;
}
@@ -296,7 +306,7 @@ static inline int HYPERVISOR_update_descriptor(
int ret;
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
+ : "=a" (ret) : "0" (__HYPERVISOR_update_descriptor),
"b" (pa), "c" (word1), "d" (word2) );
return ret;
@@ -324,4 +334,15 @@ static inline int HYPERVISOR_dom_mem_op(void *dom_mem_op)
return ret;
}
+static inline int HYPERVISOR_multicall(void *call_list, int nr_calls)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" (__HYPERVISOR_multicall),
+ "b" (call_list), "c" (nr_calls) : "memory" );
+
+ return ret;
+}
+
#endif /* __HYPERVISOR_H__ */
diff --git a/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h
index c5b3cdcd61..ad07796f95 100644
--- a/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h
+++ b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/mmu_context.h
@@ -5,6 +5,7 @@
#include <asm/desc.h>
#include <asm/atomic.h>
#include <asm/pgalloc.h>
+#include <asm/multicall.h>
/*
* possibly do the LDT unload here?
@@ -33,6 +34,7 @@ extern pgd_t *cur_pgd;
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
{
+ cli(); /* protect flush_update_queue multicall */
if (prev != next) {
/* stop flush ipis for the previous mm */
clear_bit(cpu, &prev->cpu_vm_mask);
@@ -50,7 +52,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
/* Re-load page tables */
cur_pgd = next->pgd;
queue_pt_switch(__pa(cur_pgd));
- XENO_flush_page_update_queue();
+ MULTICALL_flush_page_update_queue();
}
#ifdef CONFIG_SMP
else {
@@ -70,6 +72,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
}
#define activate_mm(prev, next) \
- switch_mm((prev),(next),NULL,smp_processor_id())
+do { \
+ switch_mm((prev),(next),NULL,smp_processor_id()); \
+ execute_multicall_list(); \
+ sti(); /* matches 'cli' in switch_mm() */ \
+} while ( 0 )
#endif
diff --git a/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/multicall.h b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/multicall.h
new file mode 100644
index 0000000000..27126dcaac
--- /dev/null
+++ b/xenolinux-2.4.21-pre4-sparse/include/asm-xeno/multicall.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * multicall.h
+ */
+
+#ifndef __MULTICALL_H__
+#define __MULTICALL_H__
+
+#include <asm/hypervisor.h>
+
+extern multicall_entry_t multicall_list[];
+extern int nr_multicall_ents;
+
+static inline void queue_multicall0(unsigned long op)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ nr_multicall_ents = i+1;
+}
+
+static inline void queue_multicall1(unsigned long op, unsigned long arg1)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ multicall_list[i].args[0] = arg1;
+ nr_multicall_ents = i+1;
+}
+
+static inline void queue_multicall2(
+ unsigned long op, unsigned long arg1, unsigned long arg2)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ multicall_list[i].args[0] = arg1;
+ multicall_list[i].args[1] = arg2;
+ nr_multicall_ents = i+1;
+}
+
+static inline void execute_multicall_list(void)
+{
+ if ( unlikely(nr_multicall_ents == 0) ) return;
+ (void)HYPERVISOR_multicall(multicall_list, nr_multicall_ents);
+ nr_multicall_ents = 0;
+}
+
+#endif /* __MULTICALL_H__ */