Xen Test Framework
console.c
Go to the documentation of this file.
1 #include <xtf/types.h>
2 #include <xtf/atomic.h>
3 #include <xtf/bitops.h>
4 #include <xtf/console.h>
5 #include <xtf/hypercall.h>
6 #include <xtf/lib.h>
7 #include <xtf/libc.h>
8 #include <xtf/traps.h>
9 
10 /*
11  * Output functions, registered if/when available.
12  * Possibilities:
13  * - Xen hypervisor console
14  * - PV console
15  * - Qemu debug console
16  */
18 static unsigned int nr_cons_cb;
19 
20 /* Guest PV console details. */
23 
25 {
27  output_fns[nr_cons_cb++] = fn;
28  else
29  panic("Too many console callbacks\n");
30 }
31 
32 /*
33  * Write some data into the pv ring, taking care not to overflow the ring.
34  */
35 static size_t pv_console_write_some(const char *buf, size_t len)
36 {
37  size_t s = 0;
38  uint32_t cons = LOAD_ACQUIRE(&pv_ring->out_cons), prod = pv_ring->out_prod;
39 
40  while ( (s < len) && ((prod - cons) < sizeof(pv_ring->out)) )
41  pv_ring->out[prod++ & (sizeof(pv_ring->out) - 1)] = buf[s++];
42 
43  STORE_RELEASE(&pv_ring->out_prod, prod);
44 
45  return s;
46 }
47 
48 /*
49  * Read out data from the pv ring, either until buffer is filled or no
50  * more data are available. Might result in partial strings, depending
51  * on how xenconsoled passes in data.
52  *
53  * Will block if no data are available.
54  */
55 size_t pv_console_read_some(char *buf, size_t len)
56 {
57  size_t s = 0;
58  uint32_t cons, prod;
59 
61  (pv_ring->in_cons == pv_ring->in_prod) )
63 
64  cons = pv_ring->in_cons;
65  prod = LOAD_ACQUIRE(&pv_ring->in_prod);
66 
67  while ( (s < len) && (0 < (prod - cons)) )
68  buf[s++] = pv_ring->in[cons++ & (sizeof(pv_ring->in) - 1)];
69 
70  STORE_RELEASE(&pv_ring->in_cons, cons);
71 
72  return s;
73 }
74 
75 /*
76  * Write some data into the pv ring, synchronously waiting for all data to be
77  * consumed.
78  */
79 static void pv_console_write(const char *buf, size_t len)
80 {
81  size_t written = 0;
82  uint32_t cons = LOAD_ACQUIRE(&pv_ring->out_cons);
83 
84  do
85  {
86  /* Try and put some data into the ring. */
87  written = pv_console_write_some(&buf[written], len - written);
88 
89  /* Kick xenconsoled into action. */
91 
92  /*
93  * If we have more to write, the ring must have filled up. Wait for
94  * more space.
95  */
96  if ( written < len )
97  {
98  while ( ACCESS_ONCE(pv_ring->out_cons) == cons )
100  }
101 
102  } while ( written < len );
103 
104  /* Wait for xenconsoled to consume all the data we gave. */
105  while ( ACCESS_ONCE(pv_ring->out_cons) != pv_ring->out_prod )
106  hypercall_yield();
107 }
108 
110 {
111  if ( port >= (sizeof(shared_info.evtchn_pending) * CHAR_BIT) )
112  panic("evtchn %u out of evtchn_pending[] range\n", port);
113 
114  pv_ring = ring;
115  pv_evtchn = port;
117 }
118 
119 void vprintk(const char *fmt, va_list args)
120 {
121  static char buf[2048];
122  unsigned int i;
123  int rc;
124 
125  rc = vsnprintf_internal(buf, sizeof(buf), fmt, args, LF_TO_CRLF);
126 
127  if ( rc > (int)sizeof(buf) )
128  panic("vprintk() buffer overflow\n");
129 
130  for ( i = 0; i < nr_cons_cb; ++i )
131  output_fns[i](buf, rc);
132 }
133 
134 void printk(const char *fmt, ...)
135 {
136  va_list args;
137 
138  va_start(args, fmt);
139  vprintk(fmt, args);
140  va_end(args);
141 }
142 
143 /*
144  * Local variables:
145  * mode: C
146  * c-file-style: "BSD"
147  * c-basic-offset: 4
148  * tab-width: 4
149  * indent-tabs-mode: nil
150  * End:
151  */
char out[2048]
Definition: console.h:7
void init_pv_console(xencons_interface_t *ring, evtchn_port_t port)
Definition: console.c:109
static int hypercall_evtchn_send(evtchn_port_t port)
Definition: hypercall.h:213
Common declarations for all tests.
uint32_t out_prod
Definition: console.h:9
static void pv_console_write(const char *buf, size_t len)
Definition: console.c:79
static unsigned int nr_cons_cb
Definition: console.c:18
#define ARRAY_SIZE(a)
Definition: lib.h:8
int vsnprintf_internal(char *buf, size_t size, const char *fmt, va_list args, unsigned int caller_flags)
Definition: vsnprintf.c:276
#define STORE_RELEASE(p, v)
Definition: atomic.h:13
char in[1024]
Definition: console.h:6
#define LOAD_ACQUIRE(p)
Definition: atomic.h:7
uint32_t evtchn_port_t
Definition: event_channel.h:11
void panic(const char *fmt,...)
Definition: lib.c:15
#define LF_TO_CRLF
Definition: libc.h:48
void(* cons_output_cb)(const char *buf, size_t len)
Definition: console.h:11
#define CHAR_BIT
Definition: limits.h:9
uint32_t in_prod
Definition: console.h:8
void printk(const char *fmt,...)
Definition: console.c:134
static xencons_interface_t * pv_ring
Definition: console.c:21
#define va_end(v)
Definition: stdarg.h:11
unsigned long evtchn_pending[sizeof(unsigned long) *8]
Definition: xen.h:186
void register_console_callback(cons_output_cb fn)
Definition: console.c:24
static void hypercall_yield(void)
Definition: hypercall.h:196
uint32_t out_cons
Definition: console.h:9
#define va_start(v, l)
Definition: stdarg.h:10
uint32_t in_cons
Definition: console.h:8
size_t pv_console_read_some(char *buf, size_t len)
Definition: console.c:55
void vprintk(const char *fmt, va_list args)
Definition: console.c:119
__UINT32_TYPE__ uint32_t
Definition: stdint.h:16
Low level bit operations.
__builtin_va_list va_list
Definition: stdarg.h:9
static cons_output_cb output_fns[3]
Definition: console.c:17
static size_t pv_console_write_some(const char *buf, size_t len)
Definition: console.c:35
static long hypercall_poll(evtchn_port_t port)
Definition: hypercall.h:201
static evtchn_port_t pv_evtchn
Definition: console.c:22
static bool test_and_clear_bit(unsigned int bit, volatile void *addr)
Definition: bitops.h:53
#define ACCESS_ONCE(x)
Definition: lib.h:10