Port-xen archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[suspend/resume] xbd and xennet
Hi,
Here's a small report relating to suspend/resume progress for port-xen.
Work is going well, now that some hard-to-find issues have been solved.
My current local repo can successfully suspend and resume back with a
working console and xenstore, which makes debugging a lot easier.
I am on my way for xbd and xennet suspend/resume, but I am stuck on the
right way to do it. xentools, xenconsole and xenstore being low level
interfaces, they are closely tied to Xen's API, their implementation
tend to be same from one OS to another (albeit some differences, but no
big deal). For xbd and xennet, things are a little bit different though.
Before asking questions, I will first present how devices work in Xen
world. Please correct if there are any mistakes, as I am currently
basing my xbd/xennet stuff on these assumptions.
Devices are communication end points between two domains. It usually
happens between a privileged (dom0 or a driver-domain) and unprivileged
domain (the domU). On dom0's side, the end point is called the
"backend". On domU's side, it is called the frontend. Both communicates
by means of rings, similar to xenstore and xencons. There are two rings:
one ring is for frontend => backend (writing a block or sending a
packet), and another ring for backend => frontend (reading a block or
receiving a packet).
At start of day (we consider that xencons and xenstore are set up),
backend and frontend are initialized like below (information are
exchanged between dom0 and domU through xenstore, with key-value pairs -
see arch/xen/xenbus/xenbus_xs.c).
Note that during xenbus attach phase, in autoconf, domU is creating a
thread (see xenbus_attach) which creates two watches, one for frontend
modification (on device node), the other for backend modification (on
backend node), in xenstore hierarchy.
1 - dom0 populates xenstore nodes, by placing some values required by
frontend to initialize its driver. Entry added is "vbd", under the path
associated to the domU's devices (the device node). The entry is
following (assuming our domU has domid = 1):
portable-current# xenstore-ls /local/domain/1/device
vbd = ""
1 = ""
backend-id = "0"
backend = "/local/domain/0/backend/vbd/1/1"
...
(note to self: when a domain is making requests to xenstore with
relative paths, xenstore considers that the domain requests data about
himself - that way, a domain does not need to know its domid to get its
own hierarchy information).
2 - frontend's watch fires. calls frontend_changed(), then
xenbus_probe_frontends(). It parses the node's content (termed a
directory, since xenstore is like a very simple fs), gets the device's
type, puts the frontend's entry "state" in "XenbusStateInitialising",
then process to the block device initialisation (in our case,
xbd_xenbus_attach() ). backend is idle here.
3 - during attach, domU allocate a page, initialize ring and private
data structures, then offer the page through grant_table, and obtain the
associated grant ref. This is where the "backend-id" is needed, to offer
the page to backend. An unbound event channel is created, and both
information are stored in xenstore ("ring-ref" and "event-channel").
Once done, domU sets the vbd state to XenbusStateInitialised, and
install a watch for the backend's state.
4 - dom0's backend (via its watch) now sees that the frontend's state
reached XenbusStateInitialised. It gets the grant reference and event
channel from xenstore, and proceed to the mapping of the granted share,
and the connection to the domU's port. Once done, it sets its state to
XenbusStateConnected (this time, under /local/domain/0/backend/vbd/1/1,
which is the backend's node in xenstore).
5 - domU's sees the new backend's state, then reads the device's info
(size and sector-size, type). Proceed its initialisation, and put itself
in XenbusStateConnected mode (in /local/domain/1/device/vbd/1).
6 - Communication starts.
[...]
7 => end : same happens during detach code. Backend's state gets to
XenbusStateClosing, which is noticed by frontend's watch; domU starts
graceful shutdown operations, then once finished, sets its state to
XenbusStateClosed.
I skipped the backend XenbusInitWait state, which happens during step 1.
From a suspend/resume perspective, it does not change much.
What differs during suspend/resume is that MFN may change (which means
that the grant table mapping has to be done again), and that we do not
go from a Unknown to a Connected state, and finally to a Closed one.
Devices stay Connected, but their operation is halted during suspend.
Now, questions: depending on implementation, suspend and resume is not
handled the same way for different OS's.
- linux (the XenSource 2.6.18 implementation) does not have a suspend
routine for its devices. Instead, it checks during resume if anything
has change, and resume operations by copying the ones left behind while
suspending (from a shadow store).
- opensolaris takes a more traditional route, with a suspend and a
resume routine.
I imagine that they have pros and cons. Both approaches are different
though, and before writing the suspend/resume routines, I would like to
know which one should be taken for netbsd. The linux way may have
minimal overhead, but requires extra precaution during resume. Solaris'
way looks cleaner, as we could share code between traditional autoconf
routines and suspend/resume. But it may add extra code paths we do not
necessarily require (like freeing bufs during suspend and reallocate
them during resume).
So I would like to have your opinion.
BTW, where does the XPMAP_OFFSET (difference between KERNBASE and
KERNTEXTOFF) stem from? I thought that kernel virtual space always
started from KERNBASE address? Any reason why Xen domUs require it to
start from KERNTEXTOFF rather than KERNBASE?
Anyway, thanks for reading :)
Cheers,
--
Jean-Yves Migeon
jean-yves.migeon%espci.fr@localhost
Home |
Main Index |
Thread Index |
Old Index