mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
This adds compile-time logic to disable certain frontends in mini-os: - pcifront is disabled by default, enabled for ioemu - blkfront, netfront, fbfront, kbdfront, consfront are enabled by default - xenbus is required for any frontend, and is enabled by default If all frontends and xenbus are disabled, mini-os will run without needing to communicate with xenstore, making it suitable to run the xenstore daemon. The console frontend is not required for the initial console, only consoles opened via openpt or ptmx. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> Acked-by: Ian Campbell <ian.campbell@citrix.com> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
196 lines
4.1 KiB
C
196 lines
4.1 KiB
C
#include <mini-os/types.h>
|
|
#include <mini-os/wait.h>
|
|
#include <mini-os/mm.h>
|
|
#include <mini-os/hypervisor.h>
|
|
#include <mini-os/events.h>
|
|
#include <mini-os/os.h>
|
|
#include <mini-os/lib.h>
|
|
#include <mini-os/xenbus.h>
|
|
#include <xen/io/console.h>
|
|
#include <xen/io/protocols.h>
|
|
#include <xen/io/ring.h>
|
|
#include <mini-os/xmalloc.h>
|
|
#include <mini-os/gnttab.h>
|
|
#include "console.h"
|
|
|
|
DECLARE_WAIT_QUEUE_HEAD(console_queue);
|
|
|
|
static inline void notify_daemon(struct consfront_dev *dev)
|
|
{
|
|
/* Use evtchn: this is called early, before irq is set up. */
|
|
if (!dev)
|
|
notify_remote_via_evtchn(start_info.console.domU.evtchn);
|
|
else
|
|
notify_remote_via_evtchn(dev->evtchn);
|
|
}
|
|
|
|
static inline struct xencons_interface *xencons_interface(void)
|
|
{
|
|
if (start_info.console.domU.evtchn)
|
|
return mfn_to_virt(start_info.console.domU.mfn);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
|
|
{
|
|
int sent = 0;
|
|
struct xencons_interface *intf;
|
|
XENCONS_RING_IDX cons, prod;
|
|
|
|
if (!dev)
|
|
intf = xencons_interface();
|
|
else
|
|
intf = dev->ring;
|
|
if (!intf)
|
|
return sent;
|
|
|
|
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(struct consfront_dev *dev, const char *data, unsigned len)
|
|
{
|
|
int sent;
|
|
|
|
sent = xencons_ring_send_no_notify(dev, data, len);
|
|
notify_daemon(dev);
|
|
|
|
return sent;
|
|
}
|
|
|
|
|
|
|
|
void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
|
|
{
|
|
struct consfront_dev *dev = (struct consfront_dev *) data;
|
|
#ifdef HAVE_LIBC
|
|
int fd = dev ? dev->fd : -1;
|
|
|
|
if (fd != -1)
|
|
files[fd].read = 1;
|
|
|
|
wake_up(&console_queue);
|
|
#else
|
|
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(dev);
|
|
|
|
xencons_tx();
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_LIBC
|
|
int xencons_ring_avail(struct consfront_dev *dev)
|
|
{
|
|
struct xencons_interface *intf;
|
|
XENCONS_RING_IDX cons, prod;
|
|
|
|
if (!dev)
|
|
intf = xencons_interface();
|
|
else
|
|
intf = dev->ring;
|
|
|
|
cons = intf->in_cons;
|
|
prod = intf->in_prod;
|
|
mb();
|
|
BUG_ON((prod - cons) > sizeof(intf->in));
|
|
|
|
return prod - cons;
|
|
}
|
|
|
|
int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
|
|
{
|
|
struct xencons_interface *intf;
|
|
XENCONS_RING_IDX cons, prod;
|
|
unsigned filled = 0;
|
|
|
|
if (!dev)
|
|
intf = xencons_interface();
|
|
else
|
|
intf = dev->ring;
|
|
|
|
cons = intf->in_cons;
|
|
prod = intf->in_prod;
|
|
mb();
|
|
BUG_ON((prod - cons) > sizeof(intf->in));
|
|
|
|
while (filled < len && cons + filled != prod) {
|
|
data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
|
|
filled++;
|
|
}
|
|
|
|
mb();
|
|
intf->in_cons = cons + filled;
|
|
|
|
notify_daemon(dev);
|
|
|
|
return filled;
|
|
}
|
|
#endif
|
|
|
|
struct consfront_dev *xencons_ring_init(void)
|
|
{
|
|
int err;
|
|
struct consfront_dev *dev;
|
|
|
|
if (!start_info.console.domU.evtchn)
|
|
return 0;
|
|
|
|
dev = malloc(sizeof(struct consfront_dev));
|
|
memset(dev, 0, sizeof(struct consfront_dev));
|
|
dev->nodename = "device/console";
|
|
dev->dom = 0;
|
|
dev->backend = 0;
|
|
dev->ring_ref = 0;
|
|
|
|
#ifdef HAVE_LIBC
|
|
dev->fd = -1;
|
|
#endif
|
|
dev->evtchn = start_info.console.domU.evtchn;
|
|
dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn);
|
|
|
|
err = bind_evtchn(dev->evtchn, console_handle_input, dev);
|
|
if (err <= 0) {
|
|
printk("XEN console request chn bind failed %i\n", err);
|
|
free(dev);
|
|
return NULL;
|
|
}
|
|
unmask_evtchn(dev->evtchn);
|
|
|
|
/* In case we have in-flight data after save/restore... */
|
|
notify_daemon(dev);
|
|
|
|
return dev;
|
|
}
|
|
|
|
void xencons_resume(void)
|
|
{
|
|
(void)xencons_ring_init();
|
|
}
|
|
|