From a54b2baac24a08b82791ede1491f31ce9408af3f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 15 Mar 2006 20:25:50 +0100 Subject: Implement console for Mini-os and also fix 2 bugs: a) in initialising new page table frames b) in initialising idle thread. Signed-off-by: Grzegorz Milos --- extras/mini-os/console/console.c | 149 ++++++++++++++++++++++++++++++++++ extras/mini-os/console/xencons_ring.c | 104 ++++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 extras/mini-os/console/console.c create mode 100644 extras/mini-os/console/xencons_ring.c (limited to 'extras/mini-os/console') diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c new file mode 100644 index 0000000000..c9ec60af8f --- /dev/null +++ b/extras/mini-os/console/console.c @@ -0,0 +1,149 @@ +/* + **************************************************************************** + * (C) 2006 - Grzegorz Milos - Cambridge University + **************************************************************************** + * + * File: console.h + * Author: Grzegorz Milos + * Changes: + * + * Date: Mar 2006 + * + * Environment: Xen Minimal OS + * Description: Console interface. + * + * Handles console I/O. Defines printk. + * + **************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Low level functions defined in xencons_ring.c */ +extern int xencons_ring_init(void); +extern int xencons_ring_send(const char *data, unsigned len); +extern int xencons_ring_send_no_notify(const char *data, unsigned len); + + +/* If console not initialised the printk will be sent to xen serial line + NOTE: you need to enable verbose in xen/Rules.mk for it to work. */ +static int console_initialised = 0; + + +void xencons_rx(char *buf, unsigned len, struct pt_regs *regs) +{ + if(len > 0) + { + /* Just repeat what's written */ + buf[len] = '\0'; + printk("%s", buf); + + if(buf[len-1] == '\r') + printk("\nNo console input handler.\n"); + } +} + +void xencons_tx(void) +{ + /* Do nothing, handled by _rx */ +} + + +void console_print(char *data, int length) +{ + char *curr_char, saved_char; + int part_len; + int (*ring_send_fn)(const char *data, unsigned length); + + if(!console_initialised) + ring_send_fn = xencons_ring_send_no_notify; + else + ring_send_fn = xencons_ring_send; + + for(curr_char = data; curr_char < data+length-1; curr_char++) + { + if(*curr_char == '\n') + { + saved_char = *(curr_char+1); + *(curr_char+1) = '\r'; + part_len = curr_char - data + 2; + ring_send_fn(data, part_len); + *(curr_char+1) = saved_char; + data = curr_char+1; + length -= part_len - 1; + } + } + + ring_send_fn(data, length); + + if(data[length-1] == '\n') + ring_send_fn("\r", 1); +} + +void print(int direct, const char *fmt, va_list args) +{ + static char buf[1024]; + + (void)vsnprintf(buf, sizeof(buf), fmt, args); + + if(direct) + { + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); + return; + } + + if(!console_initialised) + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); + + console_print(buf, strlen(buf)); +} + +void printk(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + print(0, fmt, args); + va_end(args); +} + +void xprintk(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + print(1, fmt, args); + va_end(args); +} +void init_console(void) +{ + printk("Initialising console ... "); + xencons_ring_init(); + console_initialised = 1; + /* This is also required to notify the daemon */ + printk("done.\n"); +} diff --git a/extras/mini-os/console/xencons_ring.c b/extras/mini-os/console/xencons_ring.c new file mode 100644 index 0000000000..da2fbac5bc --- /dev/null +++ b/extras/mini-os/console/xencons_ring.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* TODO - need to define BUG_ON for whole mini-os, need crash-dump as well */ +extern void do_exit(void); +#define BUG_ON(_cond) do{if(_cond) do_exit();} while(0); + +static inline struct xencons_interface *xencons_interface(void) +{ + return mfn_to_virt(start_info.console_mfn); +} + +static inline void notify_daemon(void) +{ + /* Use evtchn: this is called early, before irq is set up. */ + notify_remote_via_evtchn(start_info.console_evtchn); +} + +int xencons_ring_send_no_notify(const char *data, unsigned len) +{ + int sent = 0; + struct xencons_interface *intf = xencons_interface(); + XENCONS_RING_IDX cons, prod; + + cons = intf->out_cons; + prod = intf->out_prod; + mb(); + BUG_ON((prod - cons) > sizeof(intf->out)); + + while ((sent < len) && ((prod - cons) < sizeof(intf->out))) + intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; + + wmb(); + intf->out_prod = prod; + + return sent; +} + +int xencons_ring_send(const char *data, unsigned len) +{ + int sent; + sent = xencons_ring_send_no_notify(data, len); + notify_daemon(); + + return sent; +} + + + +static void handle_input(int port, struct pt_regs *regs) +{ + struct xencons_interface *intf = xencons_interface(); + XENCONS_RING_IDX cons, prod; + + cons = intf->in_cons; + prod = intf->in_prod; + mb(); + BUG_ON((prod - cons) > sizeof(intf->in)); + + while (cons != prod) { + xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs); + cons++; + } + + mb(); + intf->in_cons = cons; + + notify_daemon(); + + xencons_tx(); +} + +int xencons_ring_init(void) +{ + int err; + + if (!start_info.console_evtchn) + return 0; + + err = bind_evtchn(start_info.console_evtchn, handle_input); + if (err <= 0) { + printk("XEN console request chn bind failed %i\n", err); + return err; + } + + /* In case we have in-flight data after save/restore... */ + notify_daemon(); + + return 0; +} + +void xencons_resume(void) +{ + (void)xencons_ring_init(); +} + -- cgit v1.2.3