From patchwork Mon Nov 1 15:01:40 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 69795 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 56ACDB70FC for ; Tue, 2 Nov 2010 02:49:57 +1100 (EST) Received: from localhost ([127.0.0.1]:52982 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PCwYw-0000rQ-Us for incoming@patchwork.ozlabs.org; Mon, 01 Nov 2010 11:44:47 -0400 Received: from [140.186.70.92] (port=52825 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PCvu0-0003ek-GR for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:02:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PCvtX-0000gw-4I for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:02:07 -0400 Received: from cantor.suse.de ([195.135.220.2]:60264 helo=mx1.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PCvtW-0000fA-Cn for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:01:58 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 93E869486B; Mon, 1 Nov 2010 16:01:54 +0100 (CET) From: Alexander Graf To: qemu-devel Developers Date: Mon, 1 Nov 2010 16:01:40 +0100 Message-Id: <1288623713-28062-28-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1288623713-28062-1-git-send-email-agraf@suse.de> References: <1288623713-28062-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 27/40] xenner: add xc_dom.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds a generic layer for xc calls, allowing us to choose between the xenner and xen implementations at runtime. Signed-off-by: Alexander Graf --- hw/xc_dom.h | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/xen_interfaces.c | 108 ++++++++++++++++++++ hw/xen_interfaces.h | 111 +++++++++++++++++++++ hw/xen_redirect.h | 56 +++++++++++ 4 files changed, 548 insertions(+), 0 deletions(-) create mode 100644 hw/xc_dom.h create mode 100644 hw/xen_interfaces.c create mode 100644 hw/xen_interfaces.h create mode 100644 hw/xen_redirect.h diff --git a/hw/xc_dom.h b/hw/xc_dom.h new file mode 100644 index 0000000..c835a37 --- /dev/null +++ b/hw/xc_dom.h @@ -0,0 +1,273 @@ +#include + +#define INVALID_P2M_ENTRY ((xen_pfn_t)-1) + +/* --- typedefs and structs ---------------------------------------- */ + +typedef uint64_t xen_vaddr_t; +typedef uint64_t xen_paddr_t; + +#define PRIpfn PRI_xen_pfn + +struct xc_dom_seg { + xen_vaddr_t vstart; + xen_vaddr_t vend; + xen_pfn_t pfn; +}; + +struct xc_dom_mem { + struct xc_dom_mem *next; + void *mmap_ptr; + size_t mmap_len; + unsigned char memory[0]; +}; + +struct xc_dom_phys { + struct xc_dom_phys *next; + void *ptr; + xen_pfn_t first; + xen_pfn_t count; +}; + +struct xc_dom_image { + /* files */ + void *kernel_blob; + size_t kernel_size; + void *ramdisk_blob; + size_t ramdisk_size; + + /* arguments and parameters */ + char *cmdline; + uint32_t f_requested[XENFEAT_NR_SUBMAPS]; + + /* info from (elf) kernel image */ + struct { + uint64_t virt_base; + } parms; + + char *guest_type; + + /* memory layout */ + struct xc_dom_seg kernel_seg; + struct xc_dom_seg ramdisk_seg; + struct xc_dom_seg p2m_seg; + struct xc_dom_seg pgtables_seg; + struct xc_dom_seg devicetree_seg; + xen_pfn_t start_info_pfn; + xen_pfn_t console_pfn; + xen_pfn_t xenstore_pfn; + xen_pfn_t shared_info_pfn; + xen_pfn_t bootstack_pfn; + xen_vaddr_t virt_alloc_end; + xen_vaddr_t bsd_symtab_start; + + /* initial page tables */ + unsigned int pgtables; + unsigned int pg_l4; + unsigned int pg_l3; + unsigned int pg_l2; + unsigned int pg_l1; + unsigned int alloc_bootstack; + unsigned int extra_pages; + xen_vaddr_t virt_pgtab_end; + + /* other state info */ + uint32_t f_active[XENFEAT_NR_SUBMAPS]; + xen_pfn_t *p2m_host; + void *p2m_guest; + + /* physical memory */ + xen_pfn_t total_pages; + struct xc_dom_phys *phys_pages; + int realmodearea_log; + + /* malloc memory pool */ + struct xc_dom_mem *memblocks; + + /* memory footprint stats */ + size_t alloc_malloc; + size_t alloc_mem_map; + size_t alloc_file_map; + size_t alloc_domU_map; + + /* misc xen domain config stuff */ + unsigned long flags; + unsigned int console_evtchn; + unsigned int xenstore_evtchn; + xen_pfn_t shared_info_mfn; + + int guest_xc; + domid_t guest_domid; + int shadow_enabled; + + int xen_version; + xen_capabilities_info_t xen_caps; + + /* kernel loader, arch hooks */ + struct xc_dom_loader *kernel_loader; + void *private_loader; + + /* kernel loader */ + struct xc_dom_arch *arch_hooks; +}; + +/* --- pluggable kernel loader ------------------------------------- */ + +struct xc_dom_loader { + char *name; + int (*probe) (struct xc_dom_image * dom); + int (*parser) (struct xc_dom_image * dom); + int (*loader) (struct xc_dom_image * dom); + + struct xc_dom_loader *next; +}; + +#define __init __attribute__ ((constructor)) +void xc_dom_register_loader(struct xc_dom_loader *loader); + +/* --- arch specific hooks ----------------------------------------- */ + +struct xc_dom_arch { + /* pagetable setup */ + int (*alloc_magic_pages) (struct xc_dom_image * dom); + int (*count_pgtables) (struct xc_dom_image * dom); + int (*setup_pgtables) (struct xc_dom_image * dom); + + /* arch-specific data structs setup */ + int (*start_info) (struct xc_dom_image * dom); + int (*shared_info) (struct xc_dom_image * dom, void *shared_info); + int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt); + + char *guest_type; + int page_shift; + int sizeof_pfn; + + struct xc_dom_arch *next; +}; +void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks); + +#define XC_DOM_PAGE_SHIFT(dom) ((dom)->arch_hooks->page_shift) +#define XC_DOM_PAGE_SIZE(dom) (1 << (dom)->arch_hooks->page_shift) + +/* --- main functions ---------------------------------------------- */ + +struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features); +void xc_dom_release_phys(struct xc_dom_image *dom); +void xc_dom_release(struct xc_dom_image *dom); +int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb); + +size_t xc_dom_check_gzip(void *blob, size_t ziplen); +int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen); +int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size); + +int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename); +int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename); +int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, + size_t memsize); +int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, + size_t memsize); + +int xc_dom_parse_image(struct xc_dom_image *dom); +int xc_dom_build_image(struct xc_dom_image *dom); +int xc_dom_update_guest_p2m(struct xc_dom_image *dom); + +int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid); +int xc_dom_boot_mem_init(struct xc_dom_image *dom); +void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, + xen_pfn_t count); +int xc_dom_boot_image(struct xc_dom_image *dom); +int xc_dom_compat_check(struct xc_dom_image *dom); + +/* --- debugging bits ---------------------------------------------- */ + +extern FILE *xc_dom_logfile; + +void xc_dom_loginit(void); +int xc_dom_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2))); +int xc_dom_panic_func(const char *file, int line, xc_error_code err, + const char *fmt, ...) + __attribute__ ((format(printf, 4, 5))); +#define xc_dom_panic(err, fmt, args...) \ + xc_dom_panic_func(__FILE__, __LINE__, err, fmt, ## args) +#define xc_dom_trace(mark) \ + xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark) + +void xc_dom_log_memory_footprint(struct xc_dom_image *dom); + +/* --- simple memory pool ------------------------------------------ */ + +void *xc_dom_malloc(struct xc_dom_image *dom, size_t size); +void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size); +void *xc_dom_malloc_filemap(struct xc_dom_image *dom, + const char *filename, size_t * size); +char *xc_dom_strdup(struct xc_dom_image *dom, const char *str); + +/* --- alloc memory pool ------------------------------------------- */ + +int xc_dom_alloc_page(struct xc_dom_image *dom, char *name); +int xc_dom_alloc_segment(struct xc_dom_image *dom, + struct xc_dom_seg *seg, char *name, + xen_vaddr_t start, xen_vaddr_t size); + +/* --- misc bits --------------------------------------------------- */ + +void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first, + xen_pfn_t count); +void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn); +void xc_dom_unmap_all(struct xc_dom_image *dom); + +static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom, + struct xc_dom_seg *seg) +{ + xen_vaddr_t segsize = seg->vend - seg->vstart; + unsigned int page_size = XC_DOM_PAGE_SIZE(dom); + xen_pfn_t pages = (segsize + page_size - 1) / page_size; + + return xc_dom_pfn_to_ptr(dom, seg->pfn, pages); +} + +static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom, + xen_vaddr_t vaddr) +{ + unsigned int page_size = XC_DOM_PAGE_SIZE(dom); + xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size; + unsigned int offset = (vaddr - dom->parms.virt_base) % page_size; + void *ptr = xc_dom_pfn_to_ptr(dom, page, 0); + return (ptr ? (ptr + offset) : NULL); +} + +static inline int xc_dom_feature_translated(struct xc_dom_image *dom) +{ + return 0; +} + +static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn) +{ + if (dom->shadow_enabled) + return pfn; + return dom->p2m_host[pfn]; +} + +static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, + xen_pfn_t pfn) +{ + if (xc_dom_feature_translated(dom)) + return pfn; + return dom->p2m_host[pfn]; +} + +/* --- arch bits --------------------------------------------------- */ + +int arch_setup_meminit(struct xc_dom_image *dom); +int arch_setup_bootearly(struct xc_dom_image *dom); +int arch_setup_bootlate(struct xc_dom_image *dom); + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/hw/xen_interfaces.c b/hw/xen_interfaces.c new file mode 100644 index 0000000..6dec9f9 --- /dev/null +++ b/hw/xen_interfaces.c @@ -0,0 +1,108 @@ +#include +#include + +#include "hw.h" +#include "xen.h" +#include "xen_interfaces.h" + +#ifdef CONFIG_XEN + +static int xc_evtchn_domid(int handle, int domid) +{ + return -1; +} + +static struct XenEvtOps xc_evtchn_xen = { + .open = xc_evtchn_open, + .domid = xc_evtchn_domid, + .close = xc_evtchn_close, + .fd = xc_evtchn_fd, + .notify = xc_evtchn_notify, + .bind_unbound_port = xc_evtchn_bind_unbound_port, + .bind_interdomain = xc_evtchn_bind_interdomain, + .bind_virq = xc_evtchn_bind_virq, + .unbind = xc_evtchn_unbind, + .pending = xc_evtchn_pending, + .unmask = xc_evtchn_unmask, +}; + +static int xs_domid(struct xs_handle *h, int domid) +{ + return -1; +} + +static struct XenStoreOps xs_xen = { + .daemon_open = xs_daemon_open, + .domain_open = xs_domain_open, + .daemon_open_readonly = xs_daemon_open_readonly, + .domid = xs_domid, + .daemon_close = xs_daemon_close, + .directory = xs_directory, + .read = xs_read, + .write = xs_write, + .mkdir = xs_mkdir, + .rm = xs_rm, + .get_permissions = xs_get_permissions, + .set_permissions = xs_set_permissions, + .watch = xs_watch, + .fileno = xs_fileno, + .read_watch = xs_read_watch, + .unwatch = xs_unwatch, + .transaction_start = xs_transaction_start, + .transaction_end = xs_transaction_end, + .introduce_domain = xs_introduce_domain, + .resume_domain = xs_resume_domain, + .release_domain = xs_release_domain, + .get_domain_path = xs_get_domain_path, + .is_domain_introduced = xs_is_domain_introduced, +}; + +static struct XenGnttabOps xc_gnttab_xen = { + .open = xc_gnttab_open, + .close = xc_gnttab_close, + .map_grant_ref = xc_gnttab_map_grant_ref, + .map_grant_refs = xc_gnttab_map_grant_refs, + .munmap = xc_gnttab_munmap, +}; + +struct XenIfOps xc_xen = { + .interface_open = xc_interface_open, + .interface_close = xc_interface_close, + .map_foreign_range = xc_map_foreign_range, + .map_foreign_batch = xc_map_foreign_batch, + .map_foreign_pages = xc_map_foreign_pages, +}; + +#endif + +struct XenEvtOps xc_evtchn; +struct XenGnttabOps xc_gnttab; +struct XenIfOps xc; +struct XenStoreOps xs; + +void xen_interfaces_init(void) +{ + switch (xen_mode) { +#ifdef CONFIG_XEN + case XEN_ATTACH: + case XEN_CREATE: + xc_evtchn = xc_evtchn_xen; + xc_gnttab = xc_gnttab_xen; + xc = xc_xen; + xs = xs_xen; + break; +#endif +#ifdef CONFIG_XENNER + case XEN_EMULATE: + xc_evtchn = xc_evtchn_xenner; + xc_gnttab = xc_gnttab_xenner; + xc = xc_xenner; + xs = xs_xenner; + break; +#endif + default: + fprintf(stderr, "ERROR: Compiled without %s support, sorry.\n", + xen_mode == XEN_EMULATE ? "xenner" : "Xen"); + exit(1); + } +} diff --git a/hw/xen_interfaces.h b/hw/xen_interfaces.h new file mode 100644 index 0000000..95592e6 --- /dev/null +++ b/hw/xen_interfaces.h @@ -0,0 +1,111 @@ +#ifndef QEMU_HW_XEN_INTERFACES_H +#define QEMU_HW_XEN_INTERFACES_H 1 + +#include +#include + +/* ------------------------------------------------------------- */ +/* xen event channel interface */ + +struct XenEvtOps { + int (*open)(void); + int (*domid)(int xce_handle, int domid); + int (*close)(int xce_handle); + int (*fd)(int xce_handle); + int (*notify)(int xce_handle, evtchn_port_t port); + evtchn_port_or_error_t (*bind_unbound_port)(int xce_handle, int domid); + evtchn_port_or_error_t (*bind_interdomain)(int xce_handle, int domid, + evtchn_port_t remote_port); + evtchn_port_or_error_t (*bind_virq)(int xce_handle, unsigned int virq); + int (*unbind)(int xce_handle, evtchn_port_t port); + evtchn_port_or_error_t (*pending)(int xce_handle); + int (*unmask)(int xce_handle, evtchn_port_t port); +}; +extern struct XenEvtOps xc_evtchn; + +/* ------------------------------------------------------------- */ +/* xenstore interface */ + +struct xs_handle; +struct XenStoreOps { + struct xs_handle *(*daemon_open)(void); + struct xs_handle *(*domain_open)(void); + struct xs_handle *(*daemon_open_readonly)(void); + int (*domid)(struct xs_handle *h, int domid); + void (*daemon_close)(struct xs_handle *); + char **(*directory)(struct xs_handle *h, xs_transaction_t t, + const char *path, unsigned int *num); + void *(*read)(struct xs_handle *h, xs_transaction_t t, + const char *path, unsigned int *len); + bool (*write)(struct xs_handle *h, xs_transaction_t t, + const char *path, const void *data, unsigned int len); + bool (*mkdir)(struct xs_handle *h, xs_transaction_t t, + const char *path); + bool (*rm)(struct xs_handle *h, xs_transaction_t t, + const char *path); + struct xs_permissions *(*get_permissions)(struct xs_handle *h, + xs_transaction_t t, + const char *path, unsigned int *num); + bool (*set_permissions)(struct xs_handle *h, xs_transaction_t t, + const char *path, struct xs_permissions *perms, + unsigned int num_perms); + bool (*watch)(struct xs_handle *h, const char *path, const char *token); + int (*fileno)(struct xs_handle *h); + char **(*read_watch)(struct xs_handle *h, unsigned int *num); + bool (*unwatch)(struct xs_handle *h, const char *path, const char *token); + xs_transaction_t (*transaction_start)(struct xs_handle *h); + bool (*transaction_end)(struct xs_handle *h, xs_transaction_t t, + bool abort); + bool (*introduce_domain)(struct xs_handle *h, + unsigned int domid, + unsigned long mfn, + unsigned int eventchn); + bool (*resume_domain)(struct xs_handle *h, unsigned int domid); + bool (*release_domain)(struct xs_handle *h, unsigned int domid); + char *(*get_domain_path)(struct xs_handle *h, unsigned int domid); + bool (*is_domain_introduced)(struct xs_handle *h, unsigned int domid); +}; +extern struct XenStoreOps xs; + +/* ------------------------------------------------------------- */ +/* xen grant table interface */ + +struct XenGnttabOps { + int (*open)(void); + int (*close)(int xcg_handle); + void *(*map_grant_ref)(int xcg_handle, uint32_t domid, + uint32_t ref, int prot); + void *(*map_grant_refs)(int xcg_handle, uint32_t count, + uint32_t *domids, uint32_t *refs, int prot); + int (*munmap)(int xcg_handle, void *start_address, uint32_t count); +}; +extern struct XenGnttabOps xc_gnttab; + +/* ------------------------------------------------------------- */ +/* xen hypercall interface */ + +struct XenIfOps { + int (*interface_open)(void); + int (*interface_close)(int xc_handle); + void *(*map_foreign_range)(int xc_handle, uint32_t dom, + int size, int prot, + unsigned long mfn); + void *(*map_foreign_batch)(int xc_handle, uint32_t dom, int prot, + xen_pfn_t *arr, int num); + void *(*map_foreign_pages)(int xc_handle, uint32_t dom, int prot, + const xen_pfn_t *arr, int num); +}; +extern struct XenIfOps xc; + +/* ------------------------------------------------------------- */ + +#ifdef CONFIG_XENNER +extern struct XenEvtOps xc_evtchn_xenner; +extern struct XenGnttabOps xc_gnttab_xenner; +extern struct XenIfOps xc_xenner; +extern struct XenStoreOps xs_xenner; +#endif + +void xen_interfaces_init(void); + +#endif /* QEMU_HW_XEN_INTERFACES_H */ diff --git a/hw/xen_redirect.h b/hw/xen_redirect.h new file mode 100644 index 0000000..491eaf8 --- /dev/null +++ b/hw/xen_redirect.h @@ -0,0 +1,56 @@ +#ifndef QEMU_HW_XEN_REDIRECT_H +#define QEMU_HW_XEN_REDIRECT_H 1 + +#include "xen_interfaces.h" + +/* xen event channel interface */ +#define xc_evtchn_open xc_evtchn.open +#define xc_evtchn_close xc_evtchn.close +#define xc_evtchn_fd xc_evtchn.fd +#define xc_evtchn_notify xc_evtchn.notify +#define xc_evtchn_bind_unbound_port xc_evtchn.bind_unbound_port +#define xc_evtchn_bind_interdomain xc_evtchn.bind_interdomain +#define xc_evtchn_bind_virq xc_evtchn.bind_virq +#define xc_evtchn_unbind xc_evtchn.unbind +#define xc_evtchn_pending xc_evtchn.pending +#define xc_evtchn_unmask xc_evtchn.unmask + +/* grant table interface */ +#define xc_gnttab_open xc_gnttab.open +#define xc_gnttab_close xc_gnttab.close +#define xc_gnttab_map_grant_ref xc_gnttab.map_grant_ref +#define xc_gnttab_map_grant_refs xc_gnttab.map_grant_refs +#define xc_gnttab_munmap xc_gnttab.munmap + +/* xen hypercall interface */ +#define xc_interface_open xc.interface_open +#define xc_interface_close xc.interface_close +#define xc_map_foreign_range xc.map_foreign_range +#define xc_map_foreign_batch xc.map_foreign_batch +#define xc_map_foreign_pages xc.map_foreign_pages + +/* xenstore interface */ +#define xs_daemon_open xs.daemon_open +#define xs_domain_open xs.domain_open +#define xs_daemon_open_readonly xs.daemon_open_readonly +#define xs_daemon_close xs.daemon_close +#define xs_directory xs.directory +#define xs_read xs.read +#define xs_write xs.write +#define xs_mkdir xs.mkdir +#define xs_rm xs.rm +#define xs_get_permissions xs.get_permissions +#define xs_set_permissions xs.set_permissions +#define xs_watch xs.watch +#define xs_fileno xs.fileno +#define xs_read_watch xs.read_watch +#define xs_unwatch xs.unwatch +#define xs_transaction_start xs.transaction_start +#define xs_transaction_end xs.transaction_end +#define xs_introduce_domain xs.introduce_domain +#define xs_resume_domain xs.resume_domain +#define xs_release_domain xs.release_domain +#define xs_get_domain_path xs.get_domain_path +#define xs_is_domain_introduced xs.is_domain_introduced + +#endif /* QEMU_HW_XEN_REDIRECT_H */