[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] domu console issue



Hi,

I am trying to enable pv console in domu uboot without interrupt, but not work 
well,
When using xl console to attach domu, there are only a few chars output.

I add some debug info in write_console, and see out_cons are not increased after
notify_remote_by_evtchn. The write_console is taken from Linux 
driver/tty/hvc/hvc_xen.c

Any suggestions?

Thanks,
Peng.

struct xen_uart_priv {
        struct xencons_interface *intf;
        u32 evtchn;
        int vtermno;
        struct hvc_struct *hvc;
        grant_ref_t gntref;
};

static int xen_serial_probe(struct udevice *dev)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        uint64_t v = 0;
        unsigned long gfn;
        int r;

        r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
        if (r < 0 || v == 0)
                return r;

        priv->evtchn= v;

        r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
        if (r < 0 || v == 0)
                return -ENODEV;

        gfn = v;

        priv->intf = (struct xencons_interface *)(gfn << XEN_PAGE_SHIFT);
        if (priv->intf == NULL)
                return -EINVAL;

        return 0;
}

static int xen_serial_pending(struct udevice *dev, bool input)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;

        if (!input || intf->in_cons == intf->in_prod)
                return 0;

        return 1;
}

static int xen_serial_getc(struct udevice *dev)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;
        XENCONS_RING_IDX cons, prod;
        int recv = 0;
        char c;
        int num_of_bytes = 1;

        while (intf->in_cons == intf->in_prod) {
                /* wait */
                mb();
        }

        cons = intf->in_cons;
        prod = intf->in_prod;
        mb();                   /* get pointers before reading ring */

        while (cons != prod && recv < num_of_bytes) {
                c = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
                recv++;
        }

        mb();                   /* read ring before consuming */
        intf->in_cons = cons;
        mb();                   /* read ring before consuming */

        if (recv)
                notify_remote_via_evtchn(priv->evtchn);

        return c;
}

static int __write_console(struct udevice *dev, const char *data, int len)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;
        XENCONS_RING_IDX cons, prod;
        int sent = 0;

        cons = intf->out_cons;
        prod = intf->out_prod;
        asm volatile("dsb  sy\r\n" : : : "memory");
        xen_raw_printk("11 %u %u\n", intf->out_cons, intf->out_prod);

        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++];

        asm volatile("dsb  sy\r\n" : : : "memory");
        intf->out_prod = prod;
        xen_raw_printk("12 %u %u %d\n", intf->out_cons, intf->out_prod, sent);

        if (sent)
                notify_remote_via_evtchn(priv->evtchn);

        mdelay(1000);
        asm volatile("dsb  sy\r\n" : : : "memory");
        xen_raw_printk("\n");
        xen_raw_printk("%u %u %s\n", intf->out_cons, intf->out_prod, 
&intf->out[MASK_XENCONS_IDX(intf->out_cons, intf->out)]);

        return sent;
}

static int write_console(struct udevice *dev, const char *data, int len)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;
        int ret = len;

        /*
         * Make sure the whole buffer is emitted, polling if
         * necessary.  We don't ever want to rely on the hvc daemon
         * because the most interesting console output is when the
         * kernel is crippled.
         */
        while (len) {
                int sent = __write_console(dev, data, len);

                data += sent;
                len -= sent;

                if (unlikely(len))
                        HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
                HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
        }

        return ret;
}

static int xen_serial_puts(struct udevice *dev, const char *str)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;
        XENCONS_RING_IDX cons, prod;

        int sent = 0;
        int num_of_bytes = strlen(str);

        xen_raw_printk("%s", str);

        write_console(dev, str, strlen(str));

        return 0;
}

static int xen_serial_putc(struct udevice *dev, const char ch)
{
        struct xen_uart_priv *priv = dev_get_priv(dev);
        struct xencons_interface *intf = priv->intf;
        XENCONS_RING_IDX cons, prod;

        int sent = 0;
        int num_of_bytes = 1;

        xen_raw_printk("%c", ch);

        write_console(dev, &ch, 1);

        return 0;
}

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.