Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/xen/console/xen_console.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <xen/xen-os.h> | #include <xen/xen-os.h> | ||||
#include <xen/hypervisor.h> | #include <xen/hypervisor.h> | ||||
#include <xen/xen_intr.h> | #include <xen/xen_intr.h> | ||||
#include <xen/interface/io/console.h> | #include <xen/interface/io/console.h> | ||||
#include <xen/hvm.h> | |||||
#include "opt_ddb.h" | #include "opt_ddb.h" | ||||
#include "opt_printf.h" | #include "opt_printf.h" | ||||
#ifdef DDB | #ifdef DDB | ||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | static const struct xencons_ops xencons_hypervisor_ops = { | ||||
.read = xencons_read_hypervisor, | .read = xencons_read_hypervisor, | ||||
.write = xencons_write_hypervisor, | .write = xencons_write_hypervisor, | ||||
}; | }; | ||||
/*------------------ Helpers for the ring console ---------------------------*/ | /*------------------ Helpers for the ring console ---------------------------*/ | ||||
static void | static void | ||||
xencons_early_init_ring(struct xencons_priv *cons) | xencons_early_init_ring(struct xencons_priv *cons) | ||||
{ | { | ||||
/* | |||||
* The ring is initialized later for the HVM console as the | |||||
* pmap code is not yet fully initialized | |||||
* TODO: See if we can map the ring in another way earlier. | |||||
royger: I'm lost here, both HVM and PVH use exactly the same pmap init code, so I'm not sure why… | |||||
*/ | |||||
if (!xen_hvm_domain()) | |||||
julien_xen.orgUnsubmitted Not Done Inline ActionsI am not sure to understand how the code match the comment. The function will skip the initialisation for non-HVM domain... IOW after this patch, the function will still initialise the ring for HVM domain. julien_xen.org: I am not sure to understand how the code match the comment. The function will skip the… | |||||
return; | |||||
cons->intf = pmap_mapdev_attr(ptoa(xen_get_console_mfn()), PAGE_SIZE, | cons->intf = pmap_mapdev_attr(ptoa(xen_get_console_mfn()), PAGE_SIZE, | ||||
VM_MEMATTR_XEN); | VM_MEMATTR_XEN); | ||||
cons->evtchn = xen_get_console_evtchn(); | cons->evtchn = xen_get_console_evtchn(); | ||||
} | } | ||||
static int | static int | ||||
xencons_init_ring(device_t dev, struct tty *tp, driver_intr_t intr_handler) | xencons_init_ring(device_t dev, struct tty *tp, driver_intr_t intr_handler) | ||||
{ | { | ||||
struct xencons_priv *cons; | struct xencons_priv *cons; | ||||
int err; | int err; | ||||
xen_pfn_t pfn; | |||||
cons = tty_softc(tp); | cons = tty_softc(tp); | ||||
/* | |||||
* The information are already retrieved in | |||||
* xencons_early_init_ring for PV guest | |||||
julien_xen.orgUnsubmitted Not Done Inline ActionsAFAICT, after with the change in xencons_early_init_ring() , cons->evtchn and cons->intf will not be set for PV but HVM domain. julien_xen.org: AFAICT, after with the change in xencons_early_init_ring() , cons->evtchn and cons->intf will… | |||||
*/ | |||||
if (xen_hvm_domain()) { | |||||
cons->evtchn = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN); | |||||
pfn = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN); | |||||
if (!pfn) | |||||
return (ENODEV); | |||||
cons->intf = pmap_mapdev_attr(pfn << PAGE_SHIFT, PAGE_SIZE, | |||||
VM_MEMATTR_XEN); | |||||
} | |||||
if (cons->evtchn == 0) | if (cons->evtchn == 0) | ||||
return (ENODEV); | return (ENODEV); | ||||
err = xen_intr_bind_local_port(dev, cons->evtchn, NULL, | err = xen_intr_bind_local_port(dev, cons->evtchn, NULL, | ||||
intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle); | intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
Show All 26 Lines | xencons_write_ring(struct xencons_priv *cons, const char *buffer, | ||||
struct xencons_interface *intf; | struct xencons_interface *intf; | ||||
XENCONS_RING_IDX wcons, wprod; | XENCONS_RING_IDX wcons, wprod; | ||||
int sent; | int sent; | ||||
intf = cons->intf; | intf = cons->intf; | ||||
xencons_lock_assert(cons); | xencons_lock_assert(cons); | ||||
/* The console page may have not yet been initialized for HVM domain */ | |||||
if (__predict_false(!intf)) | |||||
return -1; | |||||
wcons = intf->out_cons; | wcons = intf->out_cons; | ||||
wprod = intf->out_prod; | wprod = intf->out_prod; | ||||
mb(); | mb(); | ||||
KASSERT((wprod - wcons) <= sizeof(intf->out), | KASSERT((wprod - wcons) <= sizeof(intf->out), | ||||
("console send ring inconsistent")); | ("console send ring inconsistent")); | ||||
for (sent = 0; sent < size; sent++, wprod++) { | for (sent = 0; sent < size; sent++, wprod++) { | ||||
Show All 15 Lines | |||||
{ | { | ||||
struct xencons_interface *intf; | struct xencons_interface *intf; | ||||
XENCONS_RING_IDX rcons, rprod; | XENCONS_RING_IDX rcons, rprod; | ||||
unsigned int rsz; | unsigned int rsz; | ||||
intf = cons->intf; | intf = cons->intf; | ||||
xencons_lock_assert(cons); | xencons_lock_assert(cons); | ||||
/* The console page may have not yet been initialized for HVM domain */ | |||||
if (__predict_false(!intf)) | |||||
return 0; | |||||
rcons = intf->in_cons; | rcons = intf->in_cons; | ||||
rprod = intf->in_prod; | rprod = intf->in_prod; | ||||
rmb(); | rmb(); | ||||
for (rsz = 0; rsz < size; rsz++, rcons++) { | for (rsz = 0; rsz < size; rsz++, rcons++) { | ||||
if (rprod == rcons) | if (rprod == rcons) | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 423 Lines • Show Last 20 Lines |
I'm lost here, both HVM and PVH use exactly the same pmap init code, so I'm not sure why pmap_mapdev_attr would work in one case and not the other?
Is maybe something else that's missing, and not pmap initialization?