From 7c5a8dd4544d607500ff99d7bd9652675324b53e Mon Sep 17 00:00:00 2001 From: Martin Decky Date: Tue, 1 Aug 2006 23:34:02 +0000 Subject: [PATCH] xen32: proper virtual traps, domU asynchronous console --- kernel/arch/xen32/include/asm.h | 4 - kernel/arch/xen32/include/boot/boot.h | 5 +- kernel/arch/xen32/include/hypercall.h | 27 +++++- kernel/arch/xen32/src/asm.S | 147 ------------------------------- kernel/arch/xen32/src/drivers/xconsole.c | 37 +++++++- kernel/arch/xen32/src/pm.c | 6 +- 6 files changed, 71 insertions(+), 155 deletions(-) diff --git a/kernel/arch/xen32/include/asm.h b/kernel/arch/xen32/include/asm.h index a845c17dc..3502bd935 100644 --- a/kernel/arch/xen32/include/asm.h +++ b/kernel/arch/xen32/include/asm.h @@ -41,10 +41,6 @@ #include #include -extern uint32_t interrupt_handler_size; - -extern void interrupt_handlers(void); - extern void enable_l_apic_in_msr(void); diff --git a/kernel/arch/xen32/include/boot/boot.h b/kernel/arch/xen32/include/boot/boot.h index 50cf1a7b7..ecd8d1957 100644 --- a/kernel/arch/xen32/include/boot/boot.h +++ b/kernel/arch/xen32/include/boot/boot.h @@ -49,6 +49,9 @@ #define mp_map ((pfn_t *) XEN_VIRT_START) +#define SIF_PRIVILEGED (1 << 0) /**< Privileged domain */ +#define SIF_INITDOMAIN (1 << 1) /**< Iinitial control domain */ + #include typedef uint32_t evtchn_t; @@ -101,7 +104,7 @@ typedef struct { uint32_t flags; /**< SIF_xxx flags */ pfn_t store_mfn; /**< Shared page (machine page) */ evtchn_t store_evtchn; /**< Event channel for store communication */ - void *console_mfn; /**< Console page (machine address) */ + pfn_t console_mfn; /**< Console page (machine page) */ evtchn_t console_evtchn; /**< Event channel for console messages */ pte_t *ptl0; /**< Boot PTL0 (kernel address) */ uint32_t pt_frames; /**< Number of bootstrap page table frames */ diff --git a/kernel/arch/xen32/include/hypercall.h b/kernel/arch/xen32/include/hypercall.h index c7545d45f..4fb24d182 100644 --- a/kernel/arch/xen32/include/hypercall.h +++ b/kernel/arch/xen32/include/hypercall.h @@ -40,14 +40,27 @@ typedef struct { uint8_t vector; /**< Exception vector */ uint8_t flags; /**< 0-3: privilege level; 4: clear event enable */ uint16_t cs; /**< Code selector */ - uintptr_t address; /**< Code offset */ + void *address; /**< Code offset */ } trap_info_t; +typedef struct { + evtchn_t port; +} evtchn_send_t; + +typedef struct { + uint32_t cmd; + union { + evtchn_send_t send; + }; +} evtchn_op_t; + + #define XEN_SET_TRAP_TABLE 0 #define XEN_MMU_UPDATE 1 #define XEN_SET_CALLBACKS 4 #define XEN_UPDATE_VA_MAPPING 14 +#define XEN_EVENT_CHANNEL_OP 16 #define XEN_VERSION 17 #define XEN_CONSOLE_IO 18 #define XEN_VM_ASSIST 21 @@ -78,6 +91,9 @@ typedef struct { #define MMUEXT_NEW_USER_BASEPTR 15 +#define EVTCHNOP_SEND 4 + + #define UVMF_NONE 0 /**< No flushing at all */ #define UVMF_TLB_FLUSH 1 /**< Flush entire TLB(s) */ #define UVMF_INVLPG 2 /**< Flush only one entry */ @@ -226,4 +242,13 @@ static inline int xen_version(const unsigned int cmd, const void *arg) return hypercall2(XEN_VERSION, cmd, arg); } +static inline int xen_notify_remote(evtchn_t channel) +{ + evtchn_op_t op; + + op.cmd = EVTCHNOP_SEND; + op.send.port = channel; + return hypercall1(XEN_EVENT_CHANNEL_OP, &op); +} + #endif diff --git a/kernel/arch/xen32/src/asm.S b/kernel/arch/xen32/src/asm.S index d22695d24..8a82465ac 100644 --- a/kernel/arch/xen32/src/asm.S +++ b/kernel/arch/xen32/src/asm.S @@ -37,7 +37,6 @@ .global xen_callback .global xen_failsafe_callback .global enable_l_apic_in_msr -.global interrupt_handlers .global memcpy .global memcpy_from_uspace .global memcpy_from_uspace_failover_address @@ -123,149 +122,3 @@ enable_l_apic_in_msr: pop %eax ret - -# Clear nested flag -# overwrites %ecx -.macro CLEAR_NT_FLAG - pushfl - pop %ecx - and $0xffffbfff,%ecx - push %ecx - popfl -.endm - -## Declare interrupt handlers -# -# Declare interrupt handlers for n interrupt -# vectors starting at vector i. -# -# The handlers setup data segment registers -# and call exc_dispatch(). -# -#define INTERRUPT_ALIGN 64 -.macro handler i n - -.ifeq \i-0x30 # Syscall handler - push %ds - push %es - push %fs - push %gs - - # Push arguments on stack - push %edi - push %esi - push %edx - push %ecx - push %eax - - # we must fill the data segment registers - movw $16,%ax - movw %ax,%ds - movw %ax,%es - - sti - - call syscall_handler # syscall_handler(ax,cx,dx,si,di) - cli - addl $20, %esp # clean-up of parameters - - pop %gs - pop %fs - pop %es - pop %ds - - CLEAR_NT_FLAG - iret -.else - /* - * This macro distinguishes between two versions of ia32 exceptions. - * One version has error word and the other does not have it. - * The latter version fakes the error word on the stack so that the - * handlers and istate_t can be the same for both types. - */ - .iflt \i-32 - .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST - /* - * With error word, do nothing - */ - .else - /* - * Version without error word, - */ - subl $4, %esp - .endif - .else - /* - * Version without error word, - */ - subl $4, %esp - .endif - - push %ds - push %es - push %fs - push %gs - -#ifdef CONFIG_DEBUG_ALLREGS - push %ebx - push %ebp - push %edi - push %esi -#else - sub $16, %esp -#endif - push %edx - push %ecx - push %eax - - # we must fill the data segment registers - movw $16,%ax - movw %ax,%ds - movw %ax,%es - - pushl %esp # *istate - pushl $(\i) # intnum - call exc_dispatch # excdispatch(intnum, *istate) - addl $8,%esp # Clear arguments from stack - - CLEAR_NT_FLAG # Modifies %ecx - - pop %eax - pop %ecx - pop %edx -#ifdef CONFIG_DEBUG_ALLREGS - pop %esi - pop %edi - pop %ebp - pop %ebx -#else - add $16, %esp -#endif - - pop %gs - pop %fs - pop %es - pop %ds - - addl $4,%esp # Skip error word, no matter whether real or fake. - iret -.endif - - .align INTERRUPT_ALIGN - .if (\n-\i)-1 - handler "(\i+1)",\n - .endif -.endm - -# keep in sync with pm.h !!! -IDT_ITEMS=64 -.align INTERRUPT_ALIGN -interrupt_handlers: -h_start: - handler 0 IDT_ITEMS -h_end: - -.data -.global interrupt_handler_size - -interrupt_handler_size: .long (h_end-h_start)/IDT_ITEMS diff --git a/kernel/arch/xen32/src/drivers/xconsole.c b/kernel/arch/xen32/src/drivers/xconsole.c index bd62835c6..577681dd7 100644 --- a/kernel/arch/xen32/src/drivers/xconsole.c +++ b/kernel/arch/xen32/src/drivers/xconsole.c @@ -39,7 +39,20 @@ #include #include #include +#include +#define MASK_INDEX(index, ring) ((index) & (sizeof(ring) - 1)) + +typedef struct { + char in[1024]; + char out[2048]; + uint32_t in_cons; + uint32_t in_prod; + uint32_t out_cons; + uint32_t out_prod; +} xencons_t; + +static bool asynchronous = false; static void xen_putchar(chardev_t *d, const char ch); chardev_t xen_console; @@ -51,11 +64,33 @@ void xen_console_init(void) { chardev_initialize("xen_out", &xen_console, &xen_ops); stdout = &xen_console; + if (!(start_info.flags & SIF_INITDOMAIN)) + asynchronous = true; } void xen_putchar(chardev_t *d, const char ch) { - xen_console_io(CONSOLE_IO_WRITE, 1, &ch); + if (asynchronous) { + xencons_t *console = (xencons_t *) PA2KA(MA2PA(PFN2ADDR(start_info.console_mfn))); + uint32_t cons = console->out_cons; + uint32_t prod = console->out_prod; + + memory_barrier(); + + if ((prod - cons) > sizeof(console->out)) + return; + + if (ch == '\n') + console->out[MASK_INDEX(prod++, console->out)] = '\r'; + console->out[MASK_INDEX(prod++, console->out)] = ch; + + write_barrier(); + + console->out_prod = prod; + + xen_notify_remote(start_info.console_evtchn); + } else + xen_console_io(CONSOLE_IO_WRITE, 1, &ch); } /** @} diff --git a/kernel/arch/xen32/src/pm.c b/kernel/arch/xen32/src/pm.c index 2685aaeb8..1403fc5e1 100644 --- a/kernel/arch/xen32/src/pm.c +++ b/kernel/arch/xen32/src/pm.c @@ -103,6 +103,10 @@ void tss_initialize(tss_t *t) memsetb((uintptr_t) t, sizeof(struct tss), 0); } +static void trap(void) +{ +} + void traps_init(void) { index_t i; @@ -116,7 +120,7 @@ void traps_init(void) traps[i].flags = 0; traps[i].cs = XEN_CS; - traps[i].address = ((uintptr_t) interrupt_handlers) + i * interrupt_handler_size; + traps[i].address = trap; exc_register(i, "undef", (iroutine) null_interrupt); } traps[IDT_ITEMS].vector = 0; -- 2.11.4.GIT