From f7ec35430685595784788569e178793fe9067307 Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Thu, 1 Jun 2006 16:31:37 +0100 Subject: [PATCH 01/38] Fix negation of unsigned quantities in the Xen x86 emulator. This fixes the problems left behind by c/s 10171. Again pointed out by Jan Beulich; and again different from his suggested patch. Hopefully this one will be less embarrassing. Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 4 ++-- xen/arch/x86/x86_emulate.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 32c69624e4..86bb175523 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -876,7 +876,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) PAGE_FAULT(regs->edi, USER_WRITE_FAULT); break; } - regs->edi += (regs->eflags & EF_DF) ? -(int)op_bytes : op_bytes; + regs->edi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); break; case 0x6e: /* OUTSB */ @@ -902,7 +902,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) outl_user((u32)data, (u16)regs->edx, v, regs); break; } - regs->esi += (regs->eflags & EF_DF) ? -(int)op_bytes : op_bytes; + regs->esi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); break; } diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index 5bdafa9192..a33391f1a7 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -380,11 +380,12 @@ do{ __asm__ __volatile__ ( \ ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) #define register_address_increment(reg, inc) \ do { \ + int _inc = (inc); /* signed type ensures sign extension to long */ \ if ( ad_bytes == sizeof(unsigned long) ) \ - (reg) += (inc); \ + (reg) += _inc; \ else \ (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ - (((reg) + (inc)) & ((1UL << (ad_bytes << 3)) - 1)); \ + (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ } while (0) void * @@ -858,7 +859,7 @@ x86_emulate_memop( &dst.val, 8, ctxt)) != 0 ) goto done; } - register_address_increment(_regs.esp, -(int)dst.bytes); + register_address_increment(_regs.esp, -dst.bytes); if ( (rc = ops->write_std(register_address(_regs.ss, _regs.esp), dst.val, dst.bytes, ctxt)) != 0 ) goto done; @@ -942,9 +943,9 @@ x86_emulate_memop( goto done; } register_address_increment( - _regs.esi, (_regs.eflags & EFLG_DF) ? -(int)dst.bytes : dst.bytes); + _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -(int)dst.bytes : dst.bytes); + _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xa6 ... 0xa7: /* cmps */ DPRINTF("Urk! I don't handle CMPS.\n"); @@ -955,7 +956,7 @@ x86_emulate_memop( dst.ptr = (unsigned long *)cr2; dst.val = _regs.eax; register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -(int)dst.bytes : dst.bytes); + _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xac ... 0xad: /* lods */ dst.type = OP_REG; @@ -964,7 +965,7 @@ x86_emulate_memop( if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0 ) goto done; register_address_increment( - _regs.esi, (_regs.eflags & EFLG_DF) ? -(int)dst.bytes : dst.bytes); + _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xae ... 0xaf: /* scas */ DPRINTF("Urk! I don't handle SCAS.\n"); From cf220cf03b417cd3b2cbfdf3db199acee5ebab0a Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Thu, 1 Jun 2006 16:39:42 +0100 Subject: [PATCH 02/38] Fix dummy domains (DOM_IO and DOM_XEN) creation so that list heads are initialised. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/domain.c | 14 ++------------ xen/arch/x86/mm.c | 12 ++++-------- xen/common/domain.c | 19 +++++-------------- xen/common/schedule.c | 14 +++++++++++--- xen/include/xen/sched.h | 4 ++-- 5 files changed, 24 insertions(+), 39 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 88a2b9c578..b4d53ed6be 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -92,26 +92,16 @@ alloc_dom_xen_and_dom_io(void) * Any Xen-heap pages that we will allow to be mapped will have * their domain field set to dom_xen. */ - dom_xen = alloc_domain(); + dom_xen = alloc_domain(DOMID_XEN); BUG_ON(dom_xen == NULL); - spin_lock_init(&dom_xen->page_alloc_lock); - INIT_LIST_HEAD(&dom_xen->page_list); - INIT_LIST_HEAD(&dom_xen->xenpage_list); - atomic_set(&dom_xen->refcnt, 1); - dom_xen->domain_id = DOMID_XEN; /* * Initialise our DOMID_IO domain. * This domain owns I/O pages that are within the range of the page_info * array. Mappings occur at the priv of the caller. */ - dom_io = alloc_domain(); + dom_io = alloc_domain(DOMID_IO); BUG_ON(dom_io == NULL); - spin_lock_init(&dom_io->page_alloc_lock); - INIT_LIST_HEAD(&dom_io->page_list); - INIT_LIST_HEAD(&dom_io->xenpage_list); - atomic_set(&dom_io->refcnt, 1); - dom_io->domain_id = DOMID_IO; } #endif diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 55c1e78334..594c34bb0a 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -187,20 +187,16 @@ void arch_init_memory(void) * Any Xen-heap pages that we will allow to be mapped will have * their domain field set to dom_xen. */ - dom_xen = alloc_domain(); - spin_lock_init(&dom_xen->page_alloc_lock); - atomic_set(&dom_xen->refcnt, 1); - dom_xen->domain_id = DOMID_XEN; + dom_xen = alloc_domain(DOMID_XEN); + BUG_ON(dom_xen == NULL); /* * Initialise our DOMID_IO domain. * This domain owns I/O pages that are within the range of the page_info * array. Mappings occur at the priv of the caller. */ - dom_io = alloc_domain(); - spin_lock_init(&dom_io->page_alloc_lock); - atomic_set(&dom_io->refcnt, 1); - dom_io->domain_id = DOMID_IO; + dom_io = alloc_domain(DOMID_IO); + BUG_ON(dom_io == NULL); /* First 1MB of RAM is historically marked as I/O. */ for ( i = 0; i < 0x100; i++ ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 19541d41cc..e98ef263f7 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -32,23 +32,14 @@ struct domain *domain_list; struct domain *dom0; -struct domain *domain_create(domid_t dom_id, unsigned int cpu) +struct domain *domain_create(domid_t domid, unsigned int cpu) { struct domain *d, **pd; struct vcpu *v; - if ( (d = alloc_domain()) == NULL ) + if ( (d = alloc_domain(domid)) == NULL ) return NULL; - d->domain_id = dom_id; - - atomic_set(&d->refcnt, 1); - - spin_lock_init(&d->big_lock); - spin_lock_init(&d->page_alloc_lock); - INIT_LIST_HEAD(&d->page_list); - INIT_LIST_HEAD(&d->xenpage_list); - rangeset_domain_initialise(d); if ( !is_idle_domain(d) ) @@ -74,14 +65,14 @@ struct domain *domain_create(domid_t dom_id, unsigned int cpu) if ( !is_idle_domain(d) ) { write_lock(&domlist_lock); - pd = &domain_list; /* NB. domain_list maintained in order of dom_id. */ + pd = &domain_list; /* NB. domain_list maintained in order of domid. */ for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) if ( (*pd)->domain_id > d->domain_id ) break; d->next_in_list = *pd; *pd = d; - d->next_in_hashbucket = domain_hash[DOMAIN_HASH(dom_id)]; - domain_hash[DOMAIN_HASH(dom_id)] = d; + d->next_in_hashbucket = domain_hash[DOMAIN_HASH(domid)]; + domain_hash[DOMAIN_HASH(domid)] = d; write_unlock(&domlist_lock); } diff --git a/xen/common/schedule.c b/xen/common/schedule.c index b2801695c7..bbe273b443 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -99,12 +99,20 @@ void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate) } } -struct domain *alloc_domain(void) +struct domain *alloc_domain(domid_t domid) { struct domain *d; - if ( (d = xmalloc(struct domain)) != NULL ) - memset(d, 0, sizeof(*d)); + if ( (d = xmalloc(struct domain)) == NULL ) + return NULL; + + memset(d, 0, sizeof(*d)); + d->domain_id = domid; + atomic_set(&d->refcnt, 1); + spin_lock_init(&d->big_lock); + spin_lock_init(&d->page_alloc_lock); + INIT_LIST_HEAD(&d->page_list); + INIT_LIST_HEAD(&d->xenpage_list); return d; } diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 0c0c31ad75..f32b78b594 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -189,7 +189,7 @@ extern struct vcpu *idle_vcpu[NR_CPUS]; struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); -struct domain *alloc_domain(void); +struct domain *alloc_domain(domid_t domid); void free_domain(struct domain *d); #define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */ @@ -226,7 +226,7 @@ static inline void get_knownalive_domain(struct domain *d) } extern struct domain *domain_create( - domid_t dom_id, unsigned int cpu); + domid_t domid, unsigned int cpu); extern int construct_dom0( struct domain *d, unsigned long image_start, unsigned long image_len, From d884b107781707cfa9a0120e410d97a4f6fed895 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 18:10:00 +0100 Subject: [PATCH 03/38] Domain creation/destruction cleanups. 1. Move alloc/dealloc routines to domain.[ch] 2. Merge alloc_task/add_vcpu schedops -> init_vcpu 3. Merge free_task/remove_vcpu schedops -> destroy_domain Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/domain.c | 1 + xen/arch/x86/mm.c | 1 + xen/arch/x86/smpboot.c | 1 + xen/common/domain.c | 92 +++++++++++++++++++++++++++---- xen/common/sched_bvt.c | 34 +++++------- xen/common/sched_credit.c | 30 +++++------ xen/common/sched_sedf.c | 33 ++++-------- xen/common/schedule.c | 108 +++++-------------------------------- xen/include/xen/domain.h | 22 ++++---- xen/include/xen/sched-if.h | 11 ++-- xen/include/xen/sched.h | 10 +--- 11 files changed, 154 insertions(+), 189 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index b4d53ed6be..b2e61cb03d 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 594c34bb0a..8ee92799ae 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index d199041d30..7f59d46dd8 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/xen/common/domain.c b/xen/common/domain.c index e98ef263f7..5ea044c3ee 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -32,6 +32,79 @@ struct domain *domain_list; struct domain *dom0; +struct domain *alloc_domain(domid_t domid) +{ + struct domain *d; + + if ( (d = xmalloc(struct domain)) == NULL ) + return NULL; + + memset(d, 0, sizeof(*d)); + d->domain_id = domid; + atomic_set(&d->refcnt, 1); + spin_lock_init(&d->big_lock); + spin_lock_init(&d->page_alloc_lock); + INIT_LIST_HEAD(&d->page_list); + INIT_LIST_HEAD(&d->xenpage_list); + + return d; +} + + +void free_domain(struct domain *d) +{ + struct vcpu *v; + int i; + + sched_destroy_domain(d); + + for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- ) + if ( (v = d->vcpu[i]) != NULL ) + free_vcpu_struct(v); + + xfree(d); +} + + +struct vcpu *alloc_vcpu( + struct domain *d, unsigned int vcpu_id, unsigned int cpu_id) +{ + struct vcpu *v; + + BUG_ON(d->vcpu[vcpu_id] != NULL); + + if ( (v = alloc_vcpu_struct(d, vcpu_id)) == NULL ) + return NULL; + + v->domain = d; + v->vcpu_id = vcpu_id; + v->processor = cpu_id; + atomic_set(&v->pausecnt, 0); + v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; + + v->cpu_affinity = is_idle_domain(d) ? + cpumask_of_cpu(cpu_id) : CPU_MASK_ALL; + + v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; + v->runstate.state_entry_time = NOW(); + + if ( (vcpu_id != 0) && !is_idle_domain(d) ) + set_bit(_VCPUF_down, &v->vcpu_flags); + + if ( sched_init_vcpu(v) < 0 ) + { + free_vcpu_struct(v); + return NULL; + } + + d->vcpu[vcpu_id] = v; + if ( vcpu_id != 0 ) + d->vcpu[v->vcpu_id-1]->next_in_list = v; + + return v; +} + + struct domain *domain_create(domid_t domid, unsigned int cpu) { struct domain *d, **pd; @@ -117,19 +190,16 @@ struct domain *find_domain_by_id(domid_t dom) void domain_kill(struct domain *d) { - struct vcpu *v; - domain_pause(d); - if ( !test_and_set_bit(_DOMF_dying, &d->domain_flags) ) - { - for_each_vcpu(d, v) - sched_rem_domain(v); - gnttab_release_mappings(d); - domain_relinquish_resources(d); - put_domain(d); - send_guest_global_virq(dom0, VIRQ_DOM_EXC); - } + if ( test_and_set_bit(_DOMF_dying, &d->domain_flags) ) + return; + + gnttab_release_mappings(d); + domain_relinquish_resources(d); + put_domain(d); + + send_guest_global_virq(dom0, VIRQ_DOM_EXC); } diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 4b29cf1f22..760d878795 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -160,15 +160,14 @@ static inline u32 calc_evt(struct vcpu *d, u32 avt) } /** - * bvt_alloc_task - allocate BVT private structures for a task - * @p: task to allocate private structures for - * + * bvt_init_vcpu - allocate BVT private structures for a VCPU. * Returns non-zero on failure. */ -static int bvt_alloc_task(struct vcpu *v) +static int bvt_init_vcpu(struct vcpu *v) { struct domain *d = v->domain; struct bvt_dom_info *inf; + struct bvt_vcpu_info *einf; if ( (d->sched_priv == NULL) ) { @@ -199,15 +198,7 @@ static int bvt_alloc_task(struct vcpu *v) init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor); } - return 0; -} - -/* - * Add and remove a domain - */ -static void bvt_add_task(struct vcpu *v) -{ - struct bvt_vcpu_info *einf = EBVT_INFO(v); + einf = EBVT_INFO(v); /* Allocate per-CPU context if this is the first domain to be added. */ if ( CPU_INFO(v->processor) == NULL ) @@ -223,13 +214,15 @@ static void bvt_add_task(struct vcpu *v) einf->avt = einf->evt = ~0U; BUG_ON(__task_on_runqueue(v)); __add_to_runqueue_head(v); - } + } else { /* Set avt and evt to system virtual time. */ einf->avt = CPU_SVT(v->processor); einf->evt = CPU_SVT(v->processor); } + + return 0; } static void bvt_wake(struct vcpu *v) @@ -298,10 +291,9 @@ static int bvt_set_affinity(struct vcpu *v, cpumask_t *affinity) /** - * bvt_free_task - free BVT private structures for a task - * @d: task + * bvt_destroy_domain - free BVT private structures for a domain. */ -static void bvt_free_task(struct domain *d) +static void bvt_destroy_domain(struct domain *d) { struct bvt_dom_info *inf = BVT_INFO(d); @@ -568,10 +560,10 @@ struct scheduler sched_bvt_def = { .name = "Borrowed Virtual Time", .opt_name = "bvt", .sched_id = SCHED_BVT, - - .alloc_task = bvt_alloc_task, - .add_task = bvt_add_task, - .free_task = bvt_free_task, + + .init_vcpu = bvt_init_vcpu, + .destroy_domain = bvt_destroy_domain, + .do_schedule = bvt_do_schedule, .control = bvt_ctl, .adjdom = bvt_adjdom, diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index 110611b3f3..644aee3f09 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -75,14 +75,13 @@ } while ( 0 ); #define CSCHED_STATS_EXPAND_SCHED(_MACRO) \ - _MACRO(vcpu_alloc) \ - _MACRO(vcpu_add) \ + _MACRO(vcpu_init) \ _MACRO(vcpu_sleep) \ _MACRO(vcpu_wake_running) \ _MACRO(vcpu_wake_onrunq) \ _MACRO(vcpu_wake_runnable) \ _MACRO(vcpu_wake_not_runnable) \ - _MACRO(dom_free) \ + _MACRO(dom_destroy) \ _MACRO(schedule) \ _MACRO(tickle_local_idler) \ _MACRO(tickle_local_over) \ @@ -429,14 +428,14 @@ __csched_vcpu_acct_idle_locked(struct csched_vcpu *svc) } static int -csched_vcpu_alloc(struct vcpu *vc) +csched_vcpu_init(struct vcpu *vc) { struct domain * const dom = vc->domain; struct csched_dom *sdom; struct csched_vcpu *svc; int16_t pri; - CSCHED_STAT_CRANK(vcpu_alloc); + CSCHED_STAT_CRANK(vcpu_init); /* Allocate, if appropriate, per-domain info */ if ( is_idle_vcpu(vc) ) @@ -489,19 +488,13 @@ csched_vcpu_alloc(struct vcpu *vc) if ( likely(sdom != NULL) ) csched_vcpu_acct(svc, 0); - return 0; -} - -static void -csched_vcpu_add(struct vcpu *vc) -{ - CSCHED_STAT_CRANK(vcpu_add); - /* Allocate per-PCPU info */ if ( unlikely(!CSCHED_PCPU(vc->processor)) ) csched_pcpu_init(vc->processor); CSCHED_VCPU_CHECK(vc); + + return 0; } static void @@ -644,12 +637,12 @@ csched_dom_cntl( } static void -csched_dom_free(struct domain *dom) +csched_dom_destroy(struct domain *dom) { struct csched_dom * const sdom = CSCHED_DOM(dom); int i; - CSCHED_STAT_CRANK(dom_free); + CSCHED_STAT_CRANK(dom_destroy); for ( i = 0; i < MAX_VIRT_CPUS; i++ ) { @@ -1215,14 +1208,15 @@ struct scheduler sched_credit_def = { .opt_name = "credit", .sched_id = SCHED_CREDIT, - .alloc_task = csched_vcpu_alloc, - .add_task = csched_vcpu_add, + .init_vcpu = csched_vcpu_init, + .destroy_domain = csched_dom_destroy, + .sleep = csched_vcpu_sleep, .wake = csched_vcpu_wake, + .set_affinity = csched_vcpu_set_affinity, .adjdom = csched_dom_cntl, - .free_task = csched_dom_free, .tick = csched_tick, .do_schedule = csched_schedule, diff --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c index 71e6b9ba36..9f7701d12a 100644 --- a/xen/common/sched_sedf.c +++ b/xen/common/sched_sedf.c @@ -328,11 +328,9 @@ static inline void __add_to_runqueue_sort(struct vcpu *v) } -/* Allocates memory for per domain private scheduling data*/ -static int sedf_alloc_task(struct vcpu *v) +static int sedf_init_vcpu(struct vcpu *v) { - PRINT(2, "sedf_alloc_task was called, domain-id %i.%i\n", - v->domain->domain_id, v->vcpu_id); + struct sedf_vcpu_info *inf; if ( v->domain->sched_priv == NULL ) { @@ -344,23 +342,11 @@ static int sedf_alloc_task(struct vcpu *v) if ( (v->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL ) return -1; - memset(v->sched_priv, 0, sizeof(struct sedf_vcpu_info)); - return 0; -} - - -/* Setup the sedf_dom_info */ -static void sedf_add_task(struct vcpu *v) -{ - struct sedf_vcpu_info *inf = EDOM_INFO(v); - + inf = EDOM_INFO(v); inf->vcpu = v; - PRINT(2,"sedf_add_task was called, domain-id %i.%i\n", - v->domain->domain_id, v->vcpu_id); - /* Allocate per-CPU context if this is the first domain to be added. */ if ( unlikely(schedule_data[v->processor].sched_priv == NULL) ) { @@ -408,15 +394,14 @@ static void sedf_add_task(struct vcpu *v) EDOM_INFO(v)->deadl_abs = 0; EDOM_INFO(v)->status &= ~SEDF_ASLEEP; } + + return 0; } -/* Frees memory used by domain info */ -static void sedf_free_task(struct domain *d) +static void sedf_destroy_domain(struct domain *d) { int i; - PRINT(2,"sedf_free_task was called, domain-id %i\n",d->domain_id); - xfree(d->sched_priv); for ( i = 0; i < MAX_VIRT_CPUS; i++ ) @@ -1452,9 +1437,9 @@ struct scheduler sched_sedf_def = { .opt_name = "sedf", .sched_id = SCHED_SEDF, - .alloc_task = sedf_alloc_task, - .add_task = sedf_add_task, - .free_task = sedf_free_task, + .init_vcpu = sedf_init_vcpu, + .destroy_domain = sedf_destroy_domain, + .do_schedule = sedf_do_schedule, .dump_cpu_state = sedf_dump_cpu_state, .sleep = sedf_sleep, diff --git a/xen/common/schedule.c b/xen/common/schedule.c index bbe273b443..32aebd3b83 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -99,82 +99,7 @@ void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate) } } -struct domain *alloc_domain(domid_t domid) -{ - struct domain *d; - - if ( (d = xmalloc(struct domain)) == NULL ) - return NULL; - - memset(d, 0, sizeof(*d)); - d->domain_id = domid; - atomic_set(&d->refcnt, 1); - spin_lock_init(&d->big_lock); - spin_lock_init(&d->page_alloc_lock); - INIT_LIST_HEAD(&d->page_list); - INIT_LIST_HEAD(&d->xenpage_list); - - return d; -} - -void free_domain(struct domain *d) -{ - struct vcpu *v; - int i; - - for_each_vcpu ( d, v ) - sched_rem_domain(v); - - SCHED_OP(free_task, d); - - for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- ) - if ( (v = d->vcpu[i]) != NULL ) - free_vcpu_struct(v); - - xfree(d); -} - -struct vcpu *alloc_vcpu( - struct domain *d, unsigned int vcpu_id, unsigned int cpu_id) -{ - struct vcpu *v; - - BUG_ON(d->vcpu[vcpu_id] != NULL); - - if ( (v = alloc_vcpu_struct(d, vcpu_id)) == NULL ) - return NULL; - - v->domain = d; - v->vcpu_id = vcpu_id; - v->processor = cpu_id; - atomic_set(&v->pausecnt, 0); - v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; - - v->cpu_affinity = is_idle_domain(d) ? - cpumask_of_cpu(cpu_id) : CPU_MASK_ALL; - - v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; - v->runstate.state_entry_time = NOW(); - - if ( (vcpu_id != 0) && !is_idle_domain(d) ) - set_bit(_VCPUF_down, &v->vcpu_flags); - - if ( SCHED_OP(alloc_task, v) < 0 ) - { - free_vcpu_struct(v); - return NULL; - } - - d->vcpu[vcpu_id] = v; - if ( vcpu_id != 0 ) - d->vcpu[v->vcpu_id-1]->next_in_list = v; - - sched_add_domain(v); - - return v; -} - -void sched_add_domain(struct vcpu *v) +int sched_init_vcpu(struct vcpu *v) { /* Initialise the per-domain timers. */ init_timer(&v->timer, vcpu_timer_fn, v, v->processor); @@ -187,17 +112,23 @@ void sched_add_domain(struct vcpu *v) set_bit(_VCPUF_running, &v->vcpu_flags); } - SCHED_OP(add_task, v); TRACE_2D(TRC_SCHED_DOM_ADD, v->domain->domain_id, v->vcpu_id); + + return SCHED_OP(init_vcpu, v); } -void sched_rem_domain(struct vcpu *v) +void sched_destroy_domain(struct domain *d) { - kill_timer(&v->timer); - kill_timer(&v->poll_timer); + struct vcpu *v; - SCHED_OP(rem_task, v); - TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id); + for_each_vcpu ( d, v ) + { + kill_timer(&v->timer); + kill_timer(&v->poll_timer); + TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id); + } + + SCHED_OP(destroy_domain, d); } void vcpu_sleep_nosync(struct vcpu *v) @@ -671,7 +602,7 @@ static void poll_timer_fn(void *data) /* Initialise the data structures. */ void __init scheduler_init(void) { - int i, rc; + int i; open_softirq(SCHEDULE_SOFTIRQ, __enter_scheduler); @@ -694,17 +625,6 @@ void __init scheduler_init(void) printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name); SCHED_OP(init); - - if ( idle_vcpu[0] != NULL ) - { - schedule_data[0].curr = idle_vcpu[0]; - schedule_data[0].idle = idle_vcpu[0]; - - rc = SCHED_OP(alloc_task, idle_vcpu[0]); - BUG_ON(rc < 0); - - sched_add_domain(idle_vcpu[0]); - } } /* diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index aa38ac0fc6..8e6992fea2 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -2,28 +2,32 @@ #ifndef __XEN_DOMAIN_H__ #define __XEN_DOMAIN_H__ -extern int boot_vcpu( +struct vcpu *alloc_vcpu( + struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); +int boot_vcpu( struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt); +struct domain *alloc_domain(domid_t domid); +void free_domain(struct domain *d); + /* * Arch-specifics. */ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id); -extern void free_vcpu_struct(struct vcpu *v); +void free_vcpu_struct(struct vcpu *v); -extern int arch_domain_create(struct domain *d); +int arch_domain_create(struct domain *d); -extern void arch_domain_destroy(struct domain *d); +void arch_domain_destroy(struct domain *d); -extern int arch_set_info_guest( - struct vcpu *v, struct vcpu_guest_context *c); +int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c); -extern void domain_relinquish_resources(struct domain *d); +void domain_relinquish_resources(struct domain *d); -extern void dump_pageframe_info(struct domain *d); +void dump_pageframe_info(struct domain *d); -extern void arch_dump_domain_info(struct domain *d); +void arch_dump_domain_info(struct domain *d); #endif /* __XEN_DOMAIN_H__ */ diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index 4c8232a13b..ec082b37be 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -60,14 +60,17 @@ struct scheduler { void (*init) (void); void (*tick) (unsigned int cpu); - int (*alloc_task) (struct vcpu *); - void (*add_task) (struct vcpu *); - void (*free_task) (struct domain *); - void (*rem_task) (struct vcpu *); + + int (*init_vcpu) (struct vcpu *); + void (*destroy_domain) (struct domain *); + void (*sleep) (struct vcpu *); void (*wake) (struct vcpu *); + int (*set_affinity) (struct vcpu *, cpumask_t *); + struct task_slice (*do_schedule) (s_time_t); + int (*control) (struct sched_ctl_cmd *); int (*adjdom) (struct domain *, struct sched_adjdom_cmd *); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index f32b78b594..e0c71b367a 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -186,12 +186,6 @@ extern struct vcpu *idle_vcpu[NR_CPUS]; #define is_idle_domain(d) ((d)->domain_id == IDLE_DOMAIN_ID) #define is_idle_vcpu(v) (is_idle_domain((v)->domain)) -struct vcpu *alloc_vcpu( - struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); - -struct domain *alloc_domain(domid_t domid); -void free_domain(struct domain *d); - #define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */ #define put_domain(_d) \ if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d) @@ -269,8 +263,8 @@ void new_thread(struct vcpu *d, #define set_current_state(_s) do { current->state = (_s); } while (0) void scheduler_init(void); void schedulers_start(void); -void sched_add_domain(struct vcpu *); -void sched_rem_domain(struct vcpu *); +int sched_init_vcpu(struct vcpu *); +void sched_destroy_domain(struct domain *); long sched_ctl(struct sched_ctl_cmd *); long sched_adjdom(struct sched_adjdom_cmd *); int sched_id(void); From 296d1a2fd4954cb4374df1e1663f1a36c3616ab2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 18:29:23 +0100 Subject: [PATCH 04/38] [LINUX] Converge ia64 versions of xen/drivers Makefiles with general versions. This patch converges the ia64-specific and general versions of xen/drivers/Makefile and xen/drivers/core/Makefile, using Kconfig settings instead to control whether specific pieces are built. Signed-off-by: Aron Griffis --- linux-2.6-xen-sparse/arch/ia64/Kconfig | 36 +++++++++++++++---- .../arch/ia64/xen-mkbuildtree-pre | 6 ---- .../arch/ia64/xen/drivers/Makefile | 22 ------------ .../arch/ia64/xen/drivers/coreMakefile | 20 ----------- linux-2.6-xen-sparse/drivers/xen/Kconfig | 26 ++++++++++++++ linux-2.6-xen-sparse/drivers/xen/Makefile | 9 ++--- .../drivers/xen/core/Makefile | 16 +++++---- 7 files changed, 68 insertions(+), 67 deletions(-) delete mode 100644 linux-2.6-xen-sparse/arch/ia64/xen/drivers/Makefile delete mode 100644 linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile diff --git a/linux-2.6-xen-sparse/arch/ia64/Kconfig b/linux-2.6-xen-sparse/arch/ia64/Kconfig index 763b19ea42..e14f2130b6 100644 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig @@ -73,7 +73,7 @@ config XEN_IA64_DOM0_VP config XEN_IA64_DOM0_NON_VP bool - depends on !(XEN && XEN_IA64_DOM0_VP) + depends on XEN && !XEN_IA64_DOM0_VP default y help dom0 P=M model @@ -496,15 +496,39 @@ source "security/Kconfig" source "crypto/Kconfig" +# # override default values of drivers/xen/Kconfig -if !XEN_IA64_DOM0_VP +# +if XEN +config XEN_UTIL + default n if XEN_IA64_DOM0_VP + config HAVE_ARCH_ALLOC_SKB - bool - default n + default n if !XEN_IA64_DOM0_VP config HAVE_ARCH_DEV_ALLOC_SKB - bool - default n + default n if !XEN_IA64_DOM0_VP + +config XEN_BALLOON + default n if !XEN_IA64_DOM0_VP + +config XEN_SKBUFF + default n if !XEN_IA64_DOM0_VP + +config XEN_NETDEV_BACKEND + default n if !XEN_IA64_DOM0_VP + +config XEN_NETDEV_FRONTEND + default n if !XEN_IA64_DOM0_VP + +config XEN_DEVMEM + default n + +config XEN_REBOOT + default n + +config XEN_SMPBOOT + default n endif source "drivers/xen/Kconfig" diff --git a/linux-2.6-xen-sparse/arch/ia64/xen-mkbuildtree-pre b/linux-2.6-xen-sparse/arch/ia64/xen-mkbuildtree-pre index a7b9302ab8..afc6b542d4 100755 --- a/linux-2.6-xen-sparse/arch/ia64/xen-mkbuildtree-pre +++ b/linux-2.6-xen-sparse/arch/ia64/xen-mkbuildtree-pre @@ -10,12 +10,6 @@ #eventually asm-xsi-offsets needs to be part of hypervisor.h/hypercall.h ln -sf ../../../../xen/include/asm-ia64/asm-xsi-offsets.h include/asm-ia64/xen/ -#ia64 drivers/xen isn't fully functional yet, workaround... -#also ignore core/evtchn.c which uses a different irq mechanism than ia64 -#(warning: there be dragons here if these files diverge) -ln -sf ../../arch/ia64/xen/drivers/Makefile drivers/xen/Makefile -ln -sf ../../../arch/ia64/xen/drivers/coreMakefile drivers/xen/core/Makefile - #not sure where these ia64-specific files will end up in the future ln -sf ../../../arch/ia64/xen/drivers/xenia64_init.c drivers/xen/core diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/Makefile b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/Makefile deleted file mode 100644 index 8602c71d3b..0000000000 --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/Makefile +++ /dev/null @@ -1,22 +0,0 @@ - -ifneq ($(CONFIG_XEN_IA64_DOM0_VP),y) -obj-y += util.o -endif - -obj-y += core/ -#obj-y += char/ -obj-y += console/ -obj-y += evtchn/ -obj-$(CONFIG_XEN_IA64_DOM0_VP) += balloon/ -obj-y += privcmd/ -obj-y += xenbus/ - -obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ -obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ -obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/ -obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/ -obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/ -obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ -obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront/ -obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/ -obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/ diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile deleted file mode 100644 index f396542b44..0000000000 --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-y := gnttab.o features.o -obj-$(CONFIG_PROC_FS) += xen_proc.o - -ifeq ($(ARCH),ia64) -obj-y += evtchn.o -obj-y += xenia64_init.o -ifeq ($(CONFIG_XEN_IA64_DOM0_VP),y) -obj-$(CONFIG_NET) += skbuff.o -endif -else -obj-y += reboot.o evtchn.o fixup.o -obj-$(CONFIG_SMP) += smp.o # setup_profiling_timer def'd in ia64 -obj-$(CONFIG_NET) += skbuff.o # until networking is up on ia64 -endif -obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o -obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index 34fe912fae..a240c96747 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -228,4 +228,30 @@ config NO_IDLE_HZ bool default y +config XEN_UTIL + bool + default y + +config XEN_BALLOON + bool + default y + +config XEN_DEVMEM + bool + default y + +config XEN_SKBUFF + bool + default y + depends on NET + +config XEN_REBOOT + bool + default y + +config XEN_SMPBOOT + bool + default y + depends on SMP + endif diff --git a/linux-2.6-xen-sparse/drivers/xen/Makefile b/linux-2.6-xen-sparse/drivers/xen/Makefile index 924c1fa485..9fd96e5ceb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile @@ -1,14 +1,12 @@ - -obj-y += util.o - obj-y += core/ -obj-y += char/ obj-y += console/ obj-y += evtchn/ -obj-y += balloon/ obj-y += privcmd/ obj-y += xenbus/ +obj-$(CONFIG_XEN_UTIL) += util.o +obj-$(CONFIG_XEN_BALLOON) += balloon/ +obj-$(CONFIG_XEN_DEVMEM) += char/ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/ @@ -17,4 +15,3 @@ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/ obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/ - diff --git a/linux-2.6-xen-sparse/drivers/xen/core/Makefile b/linux-2.6-xen-sparse/drivers/xen/core/Makefile index 85f1e91a17..9ff76674c3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile @@ -2,11 +2,13 @@ # Makefile for the linux kernel. # -obj-y := evtchn.o reboot.o gnttab.o features.o +obj-y := evtchn.o gnttab.o features.o -obj-$(CONFIG_PROC_FS) += xen_proc.o -obj-$(CONFIG_NET) += skbuff.o -obj-$(CONFIG_SMP) += smpboot.o -obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o -obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o -obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o +obj-$(CONFIG_PROC_FS) += xen_proc.o +obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o +obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o +obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o +obj-$(CONFIG_IA64) += xenia64_init.o +obj-$(CONFIG_XEN_SKBUFF) += skbuff.o +obj-$(CONFIG_XEN_REBOOT) += reboot.o +obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o From bf39d68ed80a20770db29e2285966d1139c175dc Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 18:30:28 +0100 Subject: [PATCH 05/38] [SECURITY] Allow domid and ssidref args to get_decision in util/security.py to be either strings or ints (previously only strings would work due to the underlying call to lowlevel.acm). Signed-off-by: Bryan D. Payne Signed-off-by: Reiner Sailer --- tools/python/xen/util/security.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/python/xen/util/security.py b/tools/python/xen/util/security.py index 752ab15e08..6a9e393ca7 100644 --- a/tools/python/xen/util/security.py +++ b/tools/python/xen/util/security.py @@ -426,6 +426,15 @@ def get_decision(arg1, arg2): err("Argument type not supported.") ssidref = label2ssidref(arg2[2][1], arg2[1][1]) arg2 = ['ssidref', str(ssidref)] + + # accept only int or string types for domid and ssidref + if isinstance(arg1[1], int): + arg1[1] = str(arg1[1]) + if isinstance(arg2[1], int): + arg2[1] = str(arg2[1]) + if not isinstance(arg1[1], str) or not isinstance(arg2[1], str): + err("Invalid id or ssidref type, string or int required") + try: decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1]) except: From bee50046c978b6bca682643655c72fc6cf383cba Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 18:32:04 +0100 Subject: [PATCH 06/38] [HVM] Allow more dynamic use of the qemu serial lines by allowing the Summagraphics port to float. qemu will emulate up to 4 serial lines (COM1 - COM4). One of these lines supports a Summagraphics protocol. This has changed recently, and it's now always COM2. This patch allows the user to specify to qemu which lines should be serial lines, and the code will place the Summagraphics compatible line at just above the last specified serial line. qemu defaults serial line 0 (COM1) to be "vc", resulting in the Summagraphics support residing on COM2. This is in keeping with the current behavior. The results, via qemu command line, are: COM2 -serial x COM2 -serial x -serial x COM3 -serial x -serial x -serial x COM4 -serial x -serial x -serial x -serial x The results are deterministic, and allow the use of up to 4 serial lines including none with Summagraphics support. There is no change from current behavior, unless requested. Signed-off-by: Ben Thomas --- tools/ioemu/hw/pc.c | 5 ++++- tools/ioemu/vl.c | 19 +++++++++++++++++-- tools/ioemu/vl.h | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index d762f0e9ee..247375f544 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -537,8 +537,11 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device, for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { sp = serial_init(serial_io[i], serial_irq[i], serial_hds[i]); - if (i == SUMMA_PORT) + if (i == serial_summa_port) { summa_init(sp, serial_hds[i]); + fprintf(stderr, "Serial port %d (COM%d) initialized for Summagraphics\n", + i, i+1); + } } } diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 08e38449bb..a39ff62252 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -146,6 +146,7 @@ int full_screen = 0; int repeat_key = 1; TextConsole *vga_console; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; +int serial_summa_port = -1; int xc_handle; time_t timeoffset = 0; @@ -2588,8 +2589,8 @@ int main(int argc, char **argv) pstrcpy(monitor_device, sizeof(monitor_device), "vc"); pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); - pstrcpy(serial_devices[1], sizeof(serial_devices[1]), "null"); - for(i = 2; i < MAX_SERIAL_PORTS; i++) + serial_summa_port = -1; + for(i = 1; i < MAX_SERIAL_PORTS; i++) serial_devices[i][0] = '\0'; serial_device_index = 0; @@ -3173,6 +3174,20 @@ int main(int argc, char **argv) } monitor_init(monitor_hd, !nographic); + /* Find which port should be the Summagraphics port */ + /* It's the first unspecified serial line. Note that COM1 is set */ + /* by default, so the Summagraphics port would be COM2 or higher */ + + for(i = 0; i < MAX_SERIAL_PORTS; i++) { + if (serial_devices[i][0] != '\0') + continue; + serial_summa_port = i; + pstrcpy(serial_devices[serial_summa_port], sizeof(serial_devices[0]), "null"); + break; + } + + /* Now, open the ports */ + for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_devices[i][0] != '\0') { serial_hds[i] = qemu_chr_open(serial_devices[i]); diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 54a84c6bd4..bb55749753 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -238,9 +238,9 @@ void console_select(unsigned int index); /* serial ports */ #define MAX_SERIAL_PORTS 4 -#define SUMMA_PORT 1 extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; +extern int serial_summa_port; /* network redirectors support */ From 410f6d8716cab8eb402544955e87201ec675d3d7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 19:07:40 +0100 Subject: [PATCH 07/38] [LINUX][X86_64] Fix initial memory mapping code. The temporary mappings needed to set up the 1:1 mappings must be torn down after use; otherwise they may trigger the WARN_ON() in vmap_pte_range() (namely if the chunk allocated to hold kernel and initial page tables gets close to or exceeds 128Mb, or if a sufficiently high mem= argument causes the static allocations to grow beyond 128Mb, which in either case means these mappings extend into the modules area). Signed-off-by: Jan Beulich --- .../arch/x86_64/mm/init-xen.c | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index 1de014d05b..0745c66b08 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -56,6 +56,8 @@ struct dma_mapping_ops* dma_ops; EXPORT_SYMBOL(dma_ops); +int after_bootmem; + extern unsigned long *contiguous_bitmap; static unsigned long dma_reserve __initdata; @@ -74,7 +76,7 @@ extern unsigned long start_pfn; (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) + \ __START_KERNEL_map))) -static void early_make_page_readonly(void *va, unsigned int feature) +static void __meminit early_make_page_readonly(void *va, unsigned int feature) { unsigned long addr, _va = (unsigned long)va; pte_t pte, *ptep; @@ -83,6 +85,11 @@ static void early_make_page_readonly(void *va, unsigned int feature) if (xen_feature(feature)) return; + if (after_bootmem) { + make_page_readonly(va, feature); + return; + } + addr = (unsigned long) page[pgd_index(_va)]; addr_to_page(addr, page); @@ -198,10 +205,6 @@ void show_mem(void) printk(KERN_INFO "%lu pages swap cached\n",cached); } -/* References to section boundaries */ - -int after_bootmem; - static void *spp_getpage(void) { void *ptr; @@ -448,9 +451,9 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) pte = alloc_static_page(&pte_phys); pte_save = pte; for (k = 0; k < PTRS_PER_PTE; pte++, k++, address += PTE_SIZE) { - if ((address >= end) || - ((address >> PAGE_SHIFT) >= - xen_start_info->nr_pages)) { + if (address >= (after_bootmem + ? end + : xen_start_info->nr_pages << PAGE_SHIFT)) { __set_pte(pte, __pte(0)); continue; } @@ -550,7 +553,7 @@ void __init xen_init_pt(void) mk_kernel_pgd(__pa_symbol(level3_user_pgt))); } -void __init extend_init_mapping(unsigned long tables_space) +static void __init extend_init_mapping(unsigned long tables_space) { unsigned long va = __START_KERNEL_map; unsigned long phys, addr, *pte_page; @@ -666,7 +669,18 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end) set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); } - BUG_ON(!after_bootmem && start_pfn != table_end); + if (!after_bootmem) { + BUG_ON(start_pfn != table_end); + + /* Destroy the temporary mappings created above. */ + start = __START_KERNEL_map + (table_start << PAGE_SHIFT); + end = start + tables_space; + for (; start < end; start += PAGE_SIZE) { + /* Should also clear out and reclaim any page table + pages no longer needed... */ + WARN_ON(HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0)); + } + } __flush_tlb_all(); } From a0746b30b07c52fdcd6ee5428b513710cce59853 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 19:14:42 +0100 Subject: [PATCH 08/38] [LINUX] Fix cpu_possible_map initialisation. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c index 5c6a16579b..6396a482d4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c @@ -89,9 +89,8 @@ void __init prefill_possible_map(void) for (i = 0; i < NR_CPUS; i++) { rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); - if (rc == -ENOENT) - break; - cpu_set(i, cpu_possible_map); + if (rc >= 0) + cpu_set(i, cpu_possible_map); } } From 6af99de37cd929601c69ed3232d4411b8564b8fd Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 21:34:47 +0100 Subject: [PATCH 09/38] Allow all trace-buffer hypercalls to be executed even when tracing is currently disabled. From: George Dunlap Signed-off-by: Keir Fraser --- xen/common/trace.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/xen/common/trace.c b/xen/common/trace.c index 0cee7126d2..6a7827299a 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -178,20 +178,12 @@ int tb_control(dom0_tbufcontrol_t *tbc) spin_lock(&lock); - if ( !tb_init_done && - (tbc->op != DOM0_TBUF_SET_SIZE) && - (tbc->op != DOM0_TBUF_ENABLE) ) - { - spin_unlock(&lock); - return -EINVAL; - } - switch ( tbc->op ) { case DOM0_TBUF_GET_INFO: tbc->cpu_mask = tb_cpu_mask; tbc->evt_mask = tb_event_mask; - tbc->buffer_mfn = __pa(t_bufs[0]) >> PAGE_SHIFT; + tbc->buffer_mfn = opt_tbuf_size ? virt_to_mfn(t_bufs[0]) : 0UL; tbc->size = opt_tbuf_size * PAGE_SIZE; break; case DOM0_TBUF_SET_CPU_MASK: From 8cd06eb3230a77ab567a4ebf4ba5876980c8f9e4 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 21:49:25 +0100 Subject: [PATCH 10/38] Use DEFINE_SPINLOCK consistently throughout Xen. Signed-off-by: Keir Fraser --- xen/arch/x86/cpu/mtrr/main.c | 2 +- xen/arch/x86/hvm/svm/svm.c | 18 ++++++++---------- xen/arch/x86/i8259.c | 2 +- xen/arch/x86/microcode.c | 2 +- xen/arch/x86/smp.c | 2 +- xen/arch/x86/time.c | 6 +++--- xen/arch/x86/x86_32/domain_page.c | 2 +- xen/common/dom0_ops.c | 2 +- xen/common/page_alloc.c | 4 ++-- xen/common/perfc.c | 2 +- xen/common/trace.c | 2 +- xen/common/xmalloc.c | 2 +- xen/drivers/char/console.c | 6 +++--- xen/include/xen/console.h | 2 -- 14 files changed, 25 insertions(+), 29 deletions(-) diff --git a/xen/arch/x86/cpu/mtrr/main.c b/xen/arch/x86/cpu/mtrr/main.c index 4737caf8aa..5684d40c89 100644 --- a/xen/arch/x86/cpu/mtrr/main.c +++ b/xen/arch/x86/cpu/mtrr/main.c @@ -43,7 +43,7 @@ #include "mtrr.h" /* No blocking mutexes in Xen. Spin instead. */ -#define DECLARE_MUTEX(_m) spinlock_t _m = SPIN_LOCK_UNLOCKED +#define DECLARE_MUTEX(_m) DEFINE_SPINLOCK(_m) #define down(_m) spin_lock(_m) #define up(_m) spin_unlock(_m) #define lock_cpu_hotplug() ((void)0) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 561ca00a79..4e4c4f568e 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -84,28 +84,26 @@ struct svm_percore_globals svm_globals[NR_CPUS]; /* * Initializes the POOL of ASID used by the guests per core. */ -void asidpool_init( int core ) +void asidpool_init(int core) { int i; - svm_globals[core].ASIDpool.asid_lock = SPIN_LOCK_UNLOCKED; - spin_lock(&svm_globals[core].ASIDpool.asid_lock); + + spin_lock_init(&svm_globals[core].ASIDpool.asid_lock); + /* Host ASID is always in use */ svm_globals[core].ASIDpool.asid[INITIAL_ASID] = ASID_INUSE; - for( i=1; iguest_asid = i; svm_globals[core].ASIDpool.asid[i] = ASID_INUSE; diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c index 17bab16f9c..76c47b5592 100644 --- a/xen/arch/x86/i8259.c +++ b/xen/arch/x86/i8259.c @@ -102,7 +102,7 @@ BUILD_SMP_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR) * moves to arch independent land */ -spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(i8259A_lock); static void disable_8259A_vector(unsigned int vector) { diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 2e31eea480..d1b185e168 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -83,7 +83,7 @@ #include #define pr_debug(x...) ((void)0) -#define DECLARE_MUTEX(_m) spinlock_t _m = SPIN_LOCK_UNLOCKED +#define DECLARE_MUTEX(_m) DEFINE_SPINLOCK(_m) #define down(_m) spin_lock(_m) #define up(_m) spin_unlock(_m) #define vmalloc(_s) xmalloc_bytes(_s) diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index 590e35921e..d56440d8e6 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -161,7 +161,7 @@ void send_IPI_mask_phys(cpumask_t mask, int vector) local_irq_restore(flags); } -static spinlock_t flush_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(flush_lock); static cpumask_t flush_cpumask; static unsigned long flush_va; diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 85f52f4d75..54a3ce41d4 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -40,10 +40,10 @@ boolean_param("hpet_force", opt_hpet_force); unsigned long cpu_khz; /* CPU clock frequency in kHz. */ unsigned long hpet_address; -spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rtc_lock); unsigned long volatile jiffies; static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */ -static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(wc_lock); struct time_scale { int shift; @@ -67,7 +67,7 @@ static struct cpu_time cpu_time[NR_CPUS]; static s_time_t stime_platform_stamp; static u64 platform_timer_stamp; static struct time_scale platform_timer_scale; -static spinlock_t platform_timer_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(platform_timer_lock); static u64 (*read_platform_count)(void); /* diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 243a81fac5..4a7362d7e2 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -183,7 +183,7 @@ void mapcache_init(struct domain *d) static unsigned long inuse[BITS_TO_LONGS(GLOBALMAP_BITS)]; static unsigned long garbage[BITS_TO_LONGS(GLOBALMAP_BITS)]; static unsigned int inuse_cursor; -static spinlock_t globalmap_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(globalmap_lock); void *map_domain_page_global(unsigned long pfn) { diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 49bb47840b..56c1847101 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -95,7 +95,7 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op) long ret = 0; struct dom0_op curop, *op = &curop; void *ssid = NULL; /* save security ptr between pre and post/fail hooks */ - static spinlock_t dom0_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(dom0_lock); if ( !IS_PRIV(current->domain) ) return -EPERM; diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index ab5cd1298a..55fc27a5a3 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -59,7 +59,7 @@ custom_param("lowmem_emergency_pool", parse_lowmem_emergency_pool); #define round_pgdown(_p) ((_p)&PAGE_MASK) #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -static spinlock_t page_scrub_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(page_scrub_lock); LIST_HEAD(page_scrub_list); /********************* @@ -250,7 +250,7 @@ static struct list_head heap[NR_ZONES][MAX_ORDER+1]; static unsigned long avail[NR_ZONES]; -static spinlock_t heap_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(heap_lock); void end_boot_allocator(void) { diff --git a/xen/common/perfc.c b/xen/common/perfc.c index df63c1042b..830e1876b5 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -209,7 +209,7 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) /* Dom0 control of perf counters */ int perfc_control(dom0_perfccontrol_t *pc) { - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(lock); u32 op = pc->op; int rc; diff --git a/xen/common/trace.c b/xen/common/trace.c index 6a7827299a..7e480d0bb4 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -173,7 +173,7 @@ void init_trace_bufs(void) */ int tb_control(dom0_tbufcontrol_t *tbc) { - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(lock); int rc = 0; spin_lock(&lock); diff --git a/xen/common/xmalloc.c b/xen/common/xmalloc.c index 038303960f..019bf9987a 100644 --- a/xen/common/xmalloc.c +++ b/xen/common/xmalloc.c @@ -35,7 +35,7 @@ #include static LIST_HEAD(freelist); -static spinlock_t freelist_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(freelist_lock); struct xmalloc_hdr { diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 12104c1e3c..f3a547038e 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -53,7 +53,7 @@ static char printk_prefix[16] = ""; static int sercon_handle = -1; static int vgacon_enabled = 0; -spinlock_t console_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(console_lock); /* * ******************************************************* @@ -563,7 +563,7 @@ static char *debugtrace_buf; /* Debug-trace buffer */ static unsigned int debugtrace_prd; /* Producer index */ static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes; static unsigned int debugtrace_used; -static spinlock_t debugtrace_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(debugtrace_lock); integer_param("debugtrace", debugtrace_kilobytes); void debugtrace_dump(void) @@ -675,7 +675,7 @@ void panic(const char *fmt, ...) va_list args; char buf[128]; unsigned long flags; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(lock); extern void machine_restart(char *); debugtrace_dump(); diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h index aa93eb32ad..b7232f305f 100644 --- a/xen/include/xen/console.h +++ b/xen/include/xen/console.h @@ -10,8 +10,6 @@ #include #include -extern spinlock_t console_lock; - void set_printk_prefix(const char *prefix); long read_console_ring(XEN_GUEST_HANDLE(char), u32 *, int); From 85bcc12ba742fd366ff1bd7df3c6c2506b4ad3cb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Jun 2006 22:21:39 +0100 Subject: [PATCH 11/38] Fix pagetable accessor macros in Xen to have better names and to preserve top bits of PAE pgdirs situated above 4GB. Signed-off-by: Keir Fraser --- xen/arch/x86/audit.c | 4 +-- xen/arch/x86/domain.c | 8 +++--- xen/arch/x86/domain_build.c | 6 ++-- xen/arch/x86/hvm/svm/svm.c | 54 ++++++++++++++++++------------------ xen/arch/x86/hvm/vmx/vmx.c | 12 ++++---- xen/arch/x86/mm.c | 6 ++-- xen/arch/x86/shadow.c | 2 +- xen/arch/x86/shadow32.c | 14 +++++----- xen/arch/x86/shadow_public.c | 14 +++++----- xen/arch/x86/smpboot.c | 2 +- xen/arch/x86/x86_32/mm.c | 3 +- xen/arch/x86/x86_64/mm.c | 3 +- xen/arch/x86/x86_64/traps.c | 2 +- xen/include/asm-x86/page.h | 11 +++++--- 14 files changed, 73 insertions(+), 68 deletions(-) diff --git a/xen/arch/x86/audit.c b/xen/arch/x86/audit.c index d43da08c82..d7cb84e70b 100644 --- a/xen/arch/x86/audit.c +++ b/xen/arch/x86/audit.c @@ -432,10 +432,10 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) for_each_vcpu(d, v) { - if ( pagetable_get_paddr(v->arch.guest_table) ) + if ( !pagetable_is_null(v->arch.guest_table) ) adjust(mfn_to_page(pagetable_get_pfn(v->arch.guest_table)), !shadow_mode_refcounts(d)); - if ( pagetable_get_paddr(v->arch.shadow_table) ) + if ( !pagetable_is_null(v->arch.shadow_table) ) adjust(mfn_to_page(pagetable_get_pfn(v->arch.shadow_table)), 0); if ( v->arch.monitor_shadow_ref ) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index c550bfc7c4..12721e1c67 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -327,7 +327,7 @@ int arch_set_info_guest( (gmfn_to_mfn(d, phys_basetab >> PAGE_SHIFT) << PAGE_SHIFT) | (phys_basetab & ~PAGE_MASK); - v->arch.guest_table = mk_pagetable(phys_basetab); + v->arch.guest_table = pagetable_from_paddr(phys_basetab); } if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 ) @@ -335,7 +335,7 @@ int arch_set_info_guest( if ( c->flags & VGCF_HVM_GUEST ) { - v->arch.guest_table = mk_pagetable(0); + v->arch.guest_table = pagetable_null(); if ( !hvm_initialize_guest_resources(v) ) return -EINVAL; @@ -935,7 +935,7 @@ void domain_relinquish_resources(struct domain *d) put_page_type(mfn_to_page(pfn)); put_page(mfn_to_page(pfn)); - v->arch.guest_table = mk_pagetable(0); + v->arch.guest_table = pagetable_null(); } if ( (pfn = pagetable_get_pfn(v->arch.guest_table_user)) != 0 ) @@ -944,7 +944,7 @@ void domain_relinquish_resources(struct domain *d) put_page_type(mfn_to_page(pfn)); put_page(mfn_to_page(pfn)); - v->arch.guest_table_user = mk_pagetable(0); + v->arch.guest_table_user = pagetable_null(); } } diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 309ddef558..80fd8513c2 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -443,13 +443,13 @@ int construct_dom0(struct domain *d, l2tab[(LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT)+i] = l2e_from_paddr((u32)l2tab + i*PAGE_SIZE, __PAGE_HYPERVISOR); } - v->arch.guest_table = mk_pagetable((unsigned long)l3start); + v->arch.guest_table = pagetable_from_paddr((unsigned long)l3start); #else l2start = l2tab = (l2_pgentry_t *)mpt_alloc; mpt_alloc += PAGE_SIZE; memcpy(l2tab, idle_pg_table, PAGE_SIZE); l2tab[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = l2e_from_paddr((unsigned long)l2start, __PAGE_HYPERVISOR); - v->arch.guest_table = mk_pagetable((unsigned long)l2start); + v->arch.guest_table = pagetable_from_paddr((unsigned long)l2start); #endif for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) @@ -577,7 +577,7 @@ int construct_dom0(struct domain *d, l4e_from_paddr(__pa(l4start), __PAGE_HYPERVISOR); l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] = l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); - v->arch.guest_table = mk_pagetable(__pa(l4start)); + v->arch.guest_table = pagetable_from_paddr(__pa(l4start)); l4tab += l4_table_offset(dsi.v_start); mfn = alloc_spfn; diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 4e4c4f568e..8d7f6e3ed8 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -744,34 +744,34 @@ static void svm_ctxt_switch_to(struct vcpu *v) void svm_final_setup_guest(struct vcpu *v) { + struct domain *d = v->domain; + struct vcpu *vc; + v->arch.schedule_tail = arch_svm_do_launch; v->arch.ctxt_switch_from = svm_ctxt_switch_from; v->arch.ctxt_switch_to = svm_ctxt_switch_to; - if (v == v->domain->vcpu[0]) - { - struct domain *d = v->domain; - struct vcpu *vc; + if ( v != d->vcpu[0] ) + return; - /* Initialize monitor page table */ - for_each_vcpu(d, vc) - vc->arch.monitor_table = mk_pagetable(0); + /* Initialize monitor page table */ + for_each_vcpu( d, vc ) + vc->arch.monitor_table = pagetable_null(); - /* - * Required to do this once per domain - * TODO: add a seperate function to do these. - */ - memset(&d->shared_info->evtchn_mask[0], 0xff, - sizeof(d->shared_info->evtchn_mask)); + /* + * Required to do this once per domain + * TODO: add a seperate function to do these. + */ + memset(&d->shared_info->evtchn_mask[0], 0xff, + sizeof(d->shared_info->evtchn_mask)); - /* - * Put the domain in shadow mode even though we're going to be using - * the shared 1:1 page table initially. It shouldn't hurt - */ - shadow_mode_enable(d, - SHM_enable|SHM_refcounts| - SHM_translate|SHM_external|SHM_wr_pt_pte); - } + /* + * Put the domain in shadow mode even though we're going to be using + * the shared 1:1 page table initially. It shouldn't hurt + */ + shadow_mode_enable(d, + SHM_enable|SHM_refcounts| + SHM_translate|SHM_external|SHM_wr_pt_pte); } @@ -868,7 +868,7 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) /* Use 1:1 page table to identify MMIO address space */ if (mmio_space(gpa)) { - /* No support for APIC */ + /* No support for APIC */ if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000) { int inst_len; @@ -1568,7 +1568,7 @@ static int svm_set_cr0(unsigned long value) } /* Now arch.guest_table points to machine physical. */ - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); update_pagetables(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", @@ -1588,7 +1588,7 @@ static int svm_set_cr0(unsigned long value) if ( v->arch.hvm_svm.cpu_cr3 ) { put_page(mfn_to_page(get_mfn_from_gpfn( v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))); - v->arch.guest_table = mk_pagetable(0); + v->arch.guest_table = pagetable_null(); } /* @@ -1597,7 +1597,7 @@ static int svm_set_cr0(unsigned long value) * created. */ if ((value & X86_CR0_PE) == 0) { - if (value & X86_CR0_PG) { + if (value & X86_CR0_PG) { svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } @@ -1738,7 +1738,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) } old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); @@ -1795,7 +1795,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) * Now arch.guest_table points to machine physical. */ - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); update_pagetables(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 1082446c02..07ef936ba7 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -66,7 +66,7 @@ void vmx_final_setup_guest(struct vcpu *v) /* Initialize monitor page table */ for_each_vcpu(d, vc) - vc->arch.monitor_table = mk_pagetable(0); + vc->arch.monitor_table = pagetable_null(); /* * Required to do this once per domain @@ -1223,7 +1223,7 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) if(!get_page(mfn_to_page(mfn), v->domain)) return 0; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); /* @@ -1459,7 +1459,7 @@ static int vmx_set_cr0(unsigned long value) /* * Now arch.guest_table points to machine physical. */ - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); update_pagetables(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", @@ -1477,7 +1477,7 @@ static int vmx_set_cr0(unsigned long value) if ( v->arch.hvm_vmx.cpu_cr3 ) { put_page(mfn_to_page(get_mfn_from_gpfn( v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT))); - v->arch.guest_table = mk_pagetable(0); + v->arch.guest_table = pagetable_null(); } /* @@ -1635,7 +1635,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) domain_crash_synchronous(); /* need to take a clean path */ } old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); /* @@ -1690,7 +1690,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) * Now arch.guest_table points to machine physical. */ - v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); update_pagetables(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 8ee92799ae..f53671ace0 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1714,7 +1714,7 @@ int new_guest_cr3(unsigned long mfn) { /* Switch to idle pagetable: this VCPU has no active p.t. now. */ old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = mk_pagetable(0); + v->arch.guest_table = pagetable_null(); update_pagetables(v); write_cr3(__pa(idle_pg_table)); if ( old_base_mfn != 0 ) @@ -1736,7 +1736,7 @@ int new_guest_cr3(unsigned long mfn) invalidate_shadow_ldt(v); old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); + v->arch.guest_table = pagetable_from_pfn(mfn); update_pagetables(v); /* update shadow_table and monitor_table */ write_ptbase(v); @@ -2003,7 +2003,7 @@ int do_mmuext_op( { unsigned long old_mfn = pagetable_get_pfn(v->arch.guest_table_user); - v->arch.guest_table_user = mk_pagetable(mfn << PAGE_SHIFT); + v->arch.guest_table_user = pagetable_from_pfn(mfn); if ( old_mfn != 0 ) put_page_and_type(mfn_to_page(old_mfn)); } diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 583373c34a..0bbc96feb1 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -2472,7 +2472,7 @@ static void shadow_update_pagetables(struct vcpu *v) if ( !get_shadow_ref(smfn) ) BUG(); old_smfn = pagetable_get_pfn(v->arch.shadow_table); - v->arch.shadow_table = mk_pagetable((u64)smfn << PAGE_SHIFT); + v->arch.shadow_table = pagetable_from_pfn(smfn); if ( old_smfn ) put_shadow_ref(old_smfn); diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index 5cefdb70a8..2e13261c50 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -583,7 +583,7 @@ static void free_shadow_pages(struct domain *d) if ( pagetable_get_paddr(v->arch.shadow_table) ) { put_shadow_ref(pagetable_get_pfn(v->arch.shadow_table)); - v->arch.shadow_table = mk_pagetable(0); + v->arch.shadow_table = pagetable_null(); if ( shadow_mode_external(d) ) { @@ -765,7 +765,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) mpl2e[l2_table_offset(SH_LINEAR_PT_VIRT_START)] = l2e_empty(); mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = l2e_empty(); - v->arch.monitor_table = mk_pagetable(mmfn << PAGE_SHIFT); + v->arch.monitor_table = pagetable_from_pfn(mmfn); v->arch.monitor_vtable = mpl2e; if ( v->vcpu_id == 0 ) @@ -830,7 +830,7 @@ void free_monitor_pagetable(struct vcpu *v) unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(mfn_to_page(mfn)); - v->arch.monitor_table = mk_pagetable(0); + v->arch.monitor_table = pagetable_null(); v->arch.monitor_vtable = 0; } @@ -992,7 +992,7 @@ alloc_p2m_table(struct domain *d) l1tab = map_domain_page(page_to_mfn(page)); memset(l1tab, 0, PAGE_SIZE); - d->arch.phys_table = mk_pagetable(page_to_maddr(page)); + d->arch.phys_table = pagetable_from_page(page); } list_ent = d->page_list.next; @@ -1126,7 +1126,7 @@ int shadow_direct_map_init(struct domain *d) memset(root, 0, PAGE_SIZE); unmap_domain_page(root); - d->arch.phys_table = mk_pagetable(page_to_maddr(page)); + d->arch.phys_table = pagetable_from_page(page); return 1; } @@ -1156,7 +1156,7 @@ void shadow_direct_map_clean(struct domain *d) unmap_domain_page(l2e); - d->arch.phys_table = mk_pagetable(0); + d->arch.phys_table = pagetable_null(); } int __shadow_mode_enable(struct domain *d, unsigned int mode) @@ -3231,7 +3231,7 @@ void __update_pagetables(struct vcpu *v) if ( !get_shadow_ref(smfn) ) BUG(); old_smfn = pagetable_get_pfn(v->arch.shadow_table); - v->arch.shadow_table = mk_pagetable(smfn << PAGE_SHIFT); + v->arch.shadow_table = pagetable_from_pfn(smfn); if ( old_smfn ) put_shadow_ref(old_smfn); diff --git a/xen/arch/x86/shadow_public.c b/xen/arch/x86/shadow_public.c index 3f100e4935..e17ab3c830 100644 --- a/xen/arch/x86/shadow_public.c +++ b/xen/arch/x86/shadow_public.c @@ -50,7 +50,7 @@ int shadow_direct_map_init(struct domain *d) memset(root, 0, PAGE_SIZE); root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR); - d->arch.phys_table = mk_pagetable(page_to_maddr(page)); + d->arch.phys_table = pagetable_from_page(page); unmap_domain_page(root); return 1; @@ -92,7 +92,7 @@ void shadow_direct_map_clean(struct domain *d) unmap_domain_page(l3e); - d->arch.phys_table = mk_pagetable(0); + d->arch.phys_table = pagetable_null(); } /****************************************************************************/ @@ -338,7 +338,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) /* map the phys_to_machine map into the per domain Read-Only MPT space */ - v->arch.monitor_table = mk_pagetable(mmfn << PAGE_SHIFT); + v->arch.monitor_table = pagetable_from_pfn(mmfn); v->arch.monitor_vtable = (l2_pgentry_t *) mpl4e; mpl4e[l4_table_offset(RO_MPT_VIRT_START)] = l4e_empty(); @@ -380,7 +380,7 @@ void free_monitor_pagetable(struct vcpu *v) unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(mfn_to_page(mfn)); - v->arch.monitor_table = mk_pagetable(0); + v->arch.monitor_table = pagetable_null(); v->arch.monitor_vtable = 0; } #elif CONFIG_PAGING_LEVELS == 3 @@ -431,7 +431,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) for ( i = 0; i < (MACHPHYS_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ ) mpl2e[l2_table_offset(RO_MPT_VIRT_START) + i] = l2e_empty(); - v->arch.monitor_table = mk_pagetable(m3mfn << PAGE_SHIFT); /* < 4GB */ + v->arch.monitor_table = pagetable_from_pfn(m3mfn); v->arch.monitor_vtable = (l2_pgentry_t *) mpl3e; if ( v->vcpu_id == 0 ) @@ -492,7 +492,7 @@ void free_monitor_pagetable(struct vcpu *v) unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(mfn_to_page(m3mfn)); - v->arch.monitor_table = mk_pagetable(0); + v->arch.monitor_table = pagetable_null(); v->arch.monitor_vtable = 0; } #endif @@ -924,7 +924,7 @@ void free_shadow_pages(struct domain *d) if ( pagetable_get_paddr(v->arch.shadow_table) ) { put_shadow_ref(pagetable_get_pfn(v->arch.shadow_table)); - v->arch.shadow_table = mk_pagetable(0); + v->arch.shadow_table = pagetable_null(); if ( shadow_mode_external(d) ) { diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 7f59d46dd8..8572105325 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -908,7 +908,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu) idle_vcpu[cpu] = v; BUG_ON(v == NULL); - v->arch.monitor_table = mk_pagetable(__pa(idle_pg_table)); + v->arch.monitor_table = pagetable_from_paddr(__pa(idle_pg_table)); /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index 73457ee036..20c2dded23 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -75,7 +75,8 @@ void __init paging_init(void) printk("PAE disabled.\n"); #endif - idle_vcpu[0]->arch.monitor_table = mk_pagetable(__pa(idle_pg_table)); + idle_vcpu[0]->arch.monitor_table = + pagetable_from_paddr(__pa(idle_pg_table)); if ( cpu_has_pge ) { diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index 5560adb858..92e565716f 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -81,7 +81,8 @@ void __init paging_init(void) l2_pgentry_t *l2_ro_mpt; struct page_info *pg; - idle_vcpu[0]->arch.monitor_table = mk_pagetable(__pa(idle_pg_table)); + idle_vcpu[0]->arch.monitor_table = + pagetable_from_paddr(__pa(idle_pg_table)); /* Create user-accessible L2 directory to map the MPT for guests. */ l3_ro_mpt = alloc_xenheap_page(); diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index ca08729953..ad7c347182 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -195,7 +195,7 @@ unsigned long do_iret(void) /* Returning to user mode? */ if ( (iret_saved.cs & 3) == 3 ) { - if ( unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) + if ( unlikely(pagetable_is_null(v->arch.guest_table_user)) ) { DPRINTK("Guest switching to user mode with no user page tables\n"); domain_crash_synchronous(); diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index bac99aedad..b0c14591ef 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -172,10 +172,13 @@ typedef struct { u32 pfn; } pagetable_t; /* x86_64 */ typedef struct { u64 pfn; } pagetable_t; #endif -#define pagetable_get_paddr(x) ((paddr_t)(x).pfn << PAGE_SHIFT) -#define pagetable_get_pfn(x) ((x).pfn) -#define mk_pagetable(pa) \ - ({ pagetable_t __p; __p.pfn = (pa) >> PAGE_SHIFT; __p; }) +#define pagetable_get_paddr(x) ((paddr_t)(x).pfn << PAGE_SHIFT) +#define pagetable_get_pfn(x) ((x).pfn) +#define pagetable_is_null(x) ((x).pfn == 0) +#define pagetable_from_pfn(pfn) ((pagetable_t) { (pfn) }) +#define pagetable_from_page(pg) pagetable_from_pfn(page_to_mfn(pg)) +#define pagetable_from_paddr(p) pagetable_from_pfn((p)>>PAGE_SHIFT) +#define pagetable_null() pagetable_from_pfn(0) #endif #define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE) From 8b6787faa7872318de4262892b2eddd7d38aafd1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 07:56:41 +0100 Subject: [PATCH 12/38] [IA64] Fix Xen running on IA64. Some function prototypes were moved to domain.h and hence undefined in some source files. This meant that some return types defaulted to int, resulting in corruption. Signed-off-by: Kevin Tian --- xen/arch/ia64/linux-xen/smpboot.c | 1 + xen/arch/ia64/xen/domain.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c index cfb96987cc..493488ba1f 100644 --- a/xen/arch/ia64/linux-xen/smpboot.c +++ b/xen/arch/ia64/linux-xen/smpboot.c @@ -62,6 +62,7 @@ #include #ifdef XEN +#include #include int ht_per_core = 1; #ifndef CONFIG_SMP diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index b2e61cb03d..6b3b200529 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include /* for function declarations */ #include +#include #include #include #include From 5d30fd9f10bcb19eebab66ce25a7c3463f615970 Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Fri, 2 Jun 2006 09:15:51 +0100 Subject: [PATCH 13/38] Build breakage: revert 10247:2fd7f4fb7d1453e4ff418c06961b0bd9fcb71129. Signed-off-by: Keir Fraser --- .../arch/x86_64/mm/init-xen.c | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index 0745c66b08..1de014d05b 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -56,8 +56,6 @@ struct dma_mapping_ops* dma_ops; EXPORT_SYMBOL(dma_ops); -int after_bootmem; - extern unsigned long *contiguous_bitmap; static unsigned long dma_reserve __initdata; @@ -76,7 +74,7 @@ extern unsigned long start_pfn; (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) + \ __START_KERNEL_map))) -static void __meminit early_make_page_readonly(void *va, unsigned int feature) +static void early_make_page_readonly(void *va, unsigned int feature) { unsigned long addr, _va = (unsigned long)va; pte_t pte, *ptep; @@ -85,11 +83,6 @@ static void __meminit early_make_page_readonly(void *va, unsigned int feature) if (xen_feature(feature)) return; - if (after_bootmem) { - make_page_readonly(va, feature); - return; - } - addr = (unsigned long) page[pgd_index(_va)]; addr_to_page(addr, page); @@ -205,6 +198,10 @@ void show_mem(void) printk(KERN_INFO "%lu pages swap cached\n",cached); } +/* References to section boundaries */ + +int after_bootmem; + static void *spp_getpage(void) { void *ptr; @@ -451,9 +448,9 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) pte = alloc_static_page(&pte_phys); pte_save = pte; for (k = 0; k < PTRS_PER_PTE; pte++, k++, address += PTE_SIZE) { - if (address >= (after_bootmem - ? end - : xen_start_info->nr_pages << PAGE_SHIFT)) { + if ((address >= end) || + ((address >> PAGE_SHIFT) >= + xen_start_info->nr_pages)) { __set_pte(pte, __pte(0)); continue; } @@ -553,7 +550,7 @@ void __init xen_init_pt(void) mk_kernel_pgd(__pa_symbol(level3_user_pgt))); } -static void __init extend_init_mapping(unsigned long tables_space) +void __init extend_init_mapping(unsigned long tables_space) { unsigned long va = __START_KERNEL_map; unsigned long phys, addr, *pte_page; @@ -669,18 +666,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end) set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); } - if (!after_bootmem) { - BUG_ON(start_pfn != table_end); - - /* Destroy the temporary mappings created above. */ - start = __START_KERNEL_map + (table_start << PAGE_SHIFT); - end = start + tables_space; - for (; start < end; start += PAGE_SIZE) { - /* Should also clear out and reclaim any page table - pages no longer needed... */ - WARN_ON(HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0)); - } - } + BUG_ON(!after_bootmem && start_pfn != table_end); __flush_tlb_all(); } From 78f168bc8d34a9cfe488f7808895294f007a900c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 09:20:58 +0100 Subject: [PATCH 14/38] [IA64][HVM] Enable CGA acceleration for VTI. Signed-off-by: Kevin Tian --- tools/ioemu/hw/cirrus_vga.c | 5 ----- tools/ioemu/hw/vga.c | 2 +- tools/ioemu/vl.c | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 8f3ac73d26..689bbacf4d 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -2460,7 +2460,6 @@ static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { }; extern FILE *logfile; -#if defined(__i386__) || defined (__x86_64__) static void * set_vram_mapping(unsigned long begin, unsigned long end) { unsigned long * extent_start = NULL; @@ -2540,10 +2539,6 @@ static int unset_vram_mapping(unsigned long begin, unsigned long end) return 0; } -#elif defined(__ia64__) -static void * set_vram_mapping(unsigned long addr, unsigned long end) {} -static int unset_vram_mapping(unsigned long addr, unsigned long end) {} -#endif extern int vga_accelerate; /* Compute the memory access functions */ diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index 2d9e6449bf..42d4327ddb 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1995,6 +1995,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, s->get_resolution = vga_get_resolution; /* XXX: currently needed for display */ vga_state = s; + vga_bios_init(s); } @@ -2082,7 +2083,6 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, #endif } - vga_bios_init(s); return 0; } diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index a39ff62252..2692ea5d80 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2499,7 +2499,7 @@ int set_mm_mapping(int xc_handle, xc_domain_getinfo(xc_handle, domid, 1, &info); if ( xc_domain_setmaxmem(xc_handle, domid, - (info.nr_pages + nr_pages) * PAGE_SIZE/1024) != 0) + info.max_memkb + nr_pages * PAGE_SIZE/1024) !=0) { fprintf(logfile, "set maxmem returned error %d\n", errno); return -1; From 32ede0e12b4760907ab0f5a2e4a976b181e12c32 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 09:31:35 +0100 Subject: [PATCH 15/38] Move idle-vcpu allocation logic to a common function. Signed-off-by: Kevin Tian --- xen/arch/ia64/linux-xen/smpboot.c | 2 +- xen/arch/ia64/xen/xensetup.c | 2 -- xen/arch/x86/setup.c | 2 -- xen/arch/x86/smpboot.c | 14 +------------- xen/common/domain.c | 25 +++++++++++++++++++++++++ xen/include/xen/domain.h | 1 + 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c index 493488ba1f..11e1b1bbc3 100644 --- a/xen/arch/ia64/linux-xen/smpboot.c +++ b/xen/arch/ia64/linux-xen/smpboot.c @@ -488,7 +488,7 @@ do_rest: #else struct vcpu *v; - v = idle_vcpu[cpu] = alloc_vcpu(idle_vcpu[0]->domain, cpu, cpu); + v = alloc_idle_vcpu(cpu); BUG_ON(v == NULL); //printf ("do_boot_cpu: cpu=%d, domain=%p, vcpu=%p\n", cpu, idle, v); diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 8040fd5222..60ad3b179d 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -35,8 +35,6 @@ unsigned long xenheap_phys_end, total_pages; char saved_command_line[COMMAND_LINE_SIZE]; char dom0_command_line[COMMAND_LINE_SIZE]; -struct vcpu *idle_vcpu[NR_CPUS]; - cpumask_t cpu_present_map; extern unsigned long domain0_ready; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 944bdb2e00..7c0ff9890d 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -85,8 +85,6 @@ extern void early_cpu_init(void); struct tss_struct init_tss[NR_CPUS]; -struct vcpu *idle_vcpu[NR_CPUS]; - extern unsigned long cpu0_stack[]; struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 8572105325..f75c01f7b2 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -887,25 +887,13 @@ static int __devinit do_boot_cpu(int apicid, int cpu) int timeout; unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; - struct domain *d; struct vcpu *v; - int vcpu_id; ++cpucount; booting_cpu = cpu; - if ((vcpu_id = cpu % MAX_VIRT_CPUS) == 0) { - d = domain_create(IDLE_DOMAIN_ID, cpu); - BUG_ON(d == NULL); - v = d->vcpu[0]; - } else { - d = idle_vcpu[cpu - vcpu_id]->domain; - BUG_ON(d == NULL); - v = alloc_vcpu(d, vcpu_id, cpu); - } - - idle_vcpu[cpu] = v; + v = alloc_idle_vcpu(cpu); BUG_ON(v == NULL); v->arch.monitor_table = pagetable_from_paddr(__pa(idle_pg_table)); diff --git a/xen/common/domain.c b/xen/common/domain.c index 5ea044c3ee..48a2b32162 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -32,6 +32,8 @@ struct domain *domain_list; struct domain *dom0; +struct vcpu *idle_vcpu[NR_CPUS]; + struct domain *alloc_domain(domid_t domid) { struct domain *d; @@ -104,6 +106,29 @@ struct vcpu *alloc_vcpu( return v; } +struct vcpu *alloc_idle_vcpu(unsigned int cpu_id) +{ + struct domain *d; + struct vcpu *v; + unsigned int vcpu_id; + + if ((vcpu_id = cpu_id % MAX_VIRT_CPUS) == 0) + { + d = domain_create(IDLE_DOMAIN_ID, cpu_id); + BUG_ON(d == NULL); + v = d->vcpu[0]; + } + else + { + d = idle_vcpu[cpu_id - vcpu_id]->domain; + BUG_ON(d == NULL); + v = alloc_vcpu(d, vcpu_id, cpu_id); + } + + idle_vcpu[cpu_id] = v; + + return v; +} struct domain *domain_create(domid_t domid, unsigned int cpu) { diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 8e6992fea2..e421c8442d 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -6,6 +6,7 @@ struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); int boot_vcpu( struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt); +struct vcpu *alloc_idle_vcpu(unsigned int cpu_id); struct domain *alloc_domain(domid_t domid); void free_domain(struct domain *d); From f365408b0dc31410cab14460a8dcd718d511c3ec Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Fri, 2 Jun 2006 09:36:28 +0100 Subject: [PATCH 16/38] [HVM] Fix a problem when destroying a Windows guest. From: Jun Nakajima Signed-off-by: Tom Woller --- xen/arch/x86/shadow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 0bbc96feb1..802f551b99 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -3481,15 +3481,16 @@ static void shadow_set_l2e_64(unsigned long va, l2_pgentry_t sl2e, __shadow_get_l3e(v, va, &sl3e); if (!(l3e_get_flags(sl3e) & _PAGE_PRESENT)) { - if (create_l2_shadow) { + if (create_l2_shadow) { perfc_incrc(shadow_set_l2e_force_map); shadow_map_into_current(v, va, PAGING_L2, PAGING_L3); __shadow_get_l3e(v, va, &sl3e); } else { printk("For non HVM shadow, create_l1_shadow:%d\n", create_l2_shadow); } - shadow_update_min_max(l4e_get_pfn(sl4e), l3_table_offset(va)); + if ( v->domain->arch.ops->guest_paging_levels == PAGING_L4 ) + shadow_update_min_max(l4e_get_pfn(sl4e), l3_table_offset(va)); } if ( put_ref_check ) { From 6d747ccc8ff9239c5fb609154305f51a3cd9efdb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 11:46:24 +0100 Subject: [PATCH 17/38] [PAE] Fix support for pgdirs above 4GB. Requires an interface change so that %cr3 is extended to include high-order address bits at bottom of %cr3 value. Guests who understand this interface change publish the fact by setting the option 'PAE=yes[extended-cr3]' in their __xen_guest section. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S | 2 +- linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 4 ++-- .../include/asm-i386/mach-xen/asm/system.h | 6 ++++-- xen/arch/x86/dom0_ops.c | 2 +- xen/arch/x86/domain.c | 14 +++++--------- xen/arch/x86/traps.c | 6 +++--- xen/include/public/arch-x86_32.h | 8 ++++++++ xen/include/public/arch-x86_64.h | 3 +++ 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S index 00ec0c2a5e..25ce03247b 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S @@ -173,7 +173,7 @@ ENTRY(cpu_gdt_table) .ascii "|pae_pgdir_above_4gb" .ascii "|supervisor_mode_kernel" #ifdef CONFIG_X86_PAE - .ascii ",PAE=yes" + .ascii ",PAE=yes[extended-cr3]" #else .ascii ",PAE=no" #endif diff --git a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c index 6396a482d4..613f835f3f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c @@ -208,7 +208,7 @@ void cpu_initialize_context(unsigned int cpu) ctxt.failsafe_callback_cs = __KERNEL_CS; ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; - ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT; + ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir)); #else /* __x86_64__ */ ctxt.user_regs.cs = __KERNEL_CS; ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs); @@ -220,7 +220,7 @@ void cpu_initialize_context(unsigned int cpu) ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; ctxt.syscall_callback_eip = (unsigned long)system_call; - ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT; + ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt)); ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu)); #endif diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h index 2626b98908..3b7ce63148 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h @@ -116,10 +116,12 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ __asm__ ( \ "movl %%cr3,%0\n\t" \ :"=r" (__dummy)); \ - machine_to_phys(__dummy); \ + __dummy = xen_cr3_to_pfn(__dummy); \ + mfn_to_pfn(__dummy) << PAGE_SHIFT; \ }) #define write_cr3(x) ({ \ - maddr_t __dummy = phys_to_machine(x); \ + unsigned int __dummy = pfn_to_mfn((x) >> PAGE_SHIFT); \ + __dummy = xen_pfn_to_cr3(__dummy); \ __asm__ __volatile__("movl %0,%%cr3": :"r" (__dummy)); \ }) diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index a88e1889e9..bfd491f25d 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -467,7 +467,7 @@ void arch_getdomaininfo_ctxt( if ( hvm_guest(v) ) c->flags |= VGCF_HVM_GUEST; - c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table); + c->ctrlreg[3] = xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table)); c->vm_assist = v->domain->vm_assist; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 12721e1c67..e8b2d647a7 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -259,7 +259,7 @@ int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c) { struct domain *d = v->domain; - unsigned long phys_basetab = INVALID_MFN; + unsigned long cr3_pfn; int i, rc; if ( !(c->flags & VGCF_HVM_GUEST) ) @@ -322,12 +322,8 @@ int arch_set_info_guest( if ( !(c->flags & VGCF_HVM_GUEST) ) { - phys_basetab = c->ctrlreg[3]; - phys_basetab = - (gmfn_to_mfn(d, phys_basetab >> PAGE_SHIFT) << PAGE_SHIFT) | - (phys_basetab & ~PAGE_MASK); - - v->arch.guest_table = pagetable_from_paddr(phys_basetab); + cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c->ctrlreg[3])); + v->arch.guest_table = pagetable_from_pfn(cr3_pfn); } if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 ) @@ -342,7 +338,7 @@ int arch_set_info_guest( } else if ( shadow_mode_refcounts(d) ) { - if ( !get_page(mfn_to_page(phys_basetab>>PAGE_SHIFT), d) ) + if ( !get_page(mfn_to_page(cr3_pfn), d) ) { destroy_gdt(v); return -EINVAL; @@ -350,7 +346,7 @@ int arch_set_info_guest( } else { - if ( !get_page_and_type(mfn_to_page(phys_basetab>>PAGE_SHIFT), d, + if ( !get_page_and_type(mfn_to_page(cr3_pfn), d, PGT_base_page_table) ) { destroy_gdt(v); diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 86bb175523..74de928a37 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1034,8 +1034,8 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) break; case 3: /* Read CR3 */ - *reg = pfn_to_paddr(mfn_to_gmfn(v->domain, - pagetable_get_pfn(v->arch.guest_table))); + *reg = xen_pfn_to_cr3(mfn_to_gmfn( + v->domain, pagetable_get_pfn(v->arch.guest_table))); break; case 4: /* Read CR4 */ @@ -1085,7 +1085,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) case 3: /* Write CR3 */ LOCK_BIGLOCK(v->domain); cleanup_writable_pagetable(v->domain); - (void)new_guest_cr3(gmfn_to_mfn(v->domain, paddr_to_pfn(*reg))); + (void)new_guest_cr3(gmfn_to_mfn(v->domain, xen_cr3_to_pfn(*reg))); UNLOCK_BIGLOCK(v->domain); break; diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 1dd1d52baf..2a43ae53ac 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -158,6 +158,14 @@ struct vcpu_guest_context { typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); +/* + * Page-directory addresses above 4GB do not fit into architectural %cr3. + * When accessing %cr3, or equivalent field in vcpu_guest_context, guests + * must use the following accessor macros to pack/unpack valid MFNs. + */ +#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) +#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) + struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 409d0d0efb..0b0ca809ca 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -234,6 +234,9 @@ struct vcpu_guest_context { typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); +#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12) +#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12) + struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ From 413629e69f0b7941568ca81715b37763e6a4be24 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 12:13:34 +0100 Subject: [PATCH 18/38] Add backing support for HDIO_GETGEO ioctl to blkfront. Inspired by an earlier patch from Charles Coffing. Signed-Off-By: Jan Beulich --- .../drivers/xen/blkfront/blkfront.c | 21 +++++++++++++++---- .../drivers/xen/blkfront/block.h | 1 + .../drivers/xen/blkfront/vbd.c | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index a61b0765d4..d7d408082a 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -452,10 +452,6 @@ int blkif_ioctl(struct inode *inode, struct file *filep, command, (long)argument, inode->i_rdev); switch (command) { - case HDIO_GETGEO: - /* return ENOSYS to use defaults */ - return -ENOSYS; - case CDROMMULTISESSION: DPRINTK("FIXME: support multisession CDs later\n"); for (i = 0; i < sizeof(struct cdrom_multisession); i++) @@ -473,6 +469,23 @@ int blkif_ioctl(struct inode *inode, struct file *filep, } +int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) +{ + /* We don't have real geometry info, but let's at least return + values consistent with the size of the device */ + sector_t nsect = get_capacity(bd->bd_disk); + sector_t cylinders = nsect; + + hg->heads = 0xff; + hg->sectors = 0x3f; + sector_div(cylinders, hg->heads * hg->sectors); + hg->cylinders = cylinders; + if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) + hg->cylinders = 0xffff; + return 0; +} + + /* * blkif_queue_request * diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 7ffd68b3b7..91f152dacf 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -140,6 +140,7 @@ extern int blkif_open(struct inode *inode, struct file *filep); extern int blkif_release(struct inode *inode, struct file *filep); extern int blkif_ioctl(struct inode *inode, struct file *filep, unsigned command, unsigned long argument); +extern int blkif_getgeo(struct block_device *, struct hd_geometry *); extern int blkif_check(dev_t dev); extern int blkif_revalidate(dev_t dev); extern void do_blkif_request (request_queue_t *rq); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c index efa396142a..8aa453d3a0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c @@ -91,6 +91,7 @@ static struct block_device_operations xlvbd_block_fops = .open = blkif_open, .release = blkif_release, .ioctl = blkif_ioctl, + .getgeo = blkif_getgeo }; DEFINE_SPINLOCK(blkif_io_lock); From cf7e961ca7fe9787c2e9b320d9e9564d01daeea6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 12:14:27 +0100 Subject: [PATCH 19/38] Use halt() instead of asm("hlt"). Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/arch/x86_64/kernel/smp-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/smp-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/smp-xen.c index 148bb939f2..0406973b1d 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/smp-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/smp-xen.c @@ -488,7 +488,7 @@ static void smp_really_stop_cpu(void *dummy) { smp_stop_cpu(); for (;;) - asm("hlt"); + halt(); } void smp_send_stop(void) From e16b4fa8fe1ac5ffb95a76eb7aed40e3082160bc Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 12:19:33 +0100 Subject: [PATCH 20/38] [NET] loopback: Added support for SG Just like the standard loopback device, SG support here is innate. So all we need to do is mark it as such and zero the change_mtu method so that the MTU can be changed at will. Signed-off-by: Herbert Xu --- linux-2.6-xen-sparse/drivers/xen/netback/loopback.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c index 7e8c4b0bc0..e9337b0005 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @@ -146,11 +146,13 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo) dev->hard_start_xmit = loopback_start_xmit; dev->get_stats = loopback_get_stats; dev->set_multicast_list = loopback_set_multicast_list; + dev->change_mtu = NULL; /* allow arbitrary mtu */ dev->tx_queue_len = 0; dev->features = (NETIF_F_HIGHDMA | NETIF_F_LLTX | + NETIF_F_SG | NETIF_F_IP_CSUM); SET_ETHTOOL_OPS(dev, &network_ethtool_ops); From dd9f789cb6ce7f512a06fb2ebd013a52ca6cbf9f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 13:36:29 +0100 Subject: [PATCH 21/38] A few put_cpu() calls were missed when adding CONFIG_X86_NO_TSS. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/arch/i386/kernel/vm86.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/vm86.c b/linux-2.6-xen-sparse/arch/i386/kernel/vm86.c index c1e240926d..0e3a0d46c8 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/vm86.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/vm86.c @@ -132,7 +132,9 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) current->thread.sysenter_cs = __KERNEL_CS; load_esp0(tss, ¤t->thread); current->thread.saved_esp0 = 0; +#ifndef CONFIG_X86_NO_TSS put_cpu(); +#endif loadsegment(fs, current->thread.saved_fs); loadsegment(gs, current->thread.saved_gs); @@ -310,7 +312,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk if (cpu_has_sep) tsk->thread.sysenter_cs = 0; load_esp0(tss, &tsk->thread); +#ifndef CONFIG_X86_NO_TSS put_cpu(); +#endif tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) From 4f7f661224a7e496548c154c1cbe022be25561d9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 14:16:43 +0100 Subject: [PATCH 22/38] [PAE] Fix tools to properly pack/unpack >4GB PAE CR3 values. Signed-off-by: Keir Fraser --- tools/debugger/libxendebug/xendebug.c | 5 +++-- tools/libxc/xc_linux_build.c | 18 +++++++++--------- tools/libxc/xc_linux_restore.c | 4 ++-- tools/libxc/xc_linux_save.c | 6 +++--- tools/libxc/xc_pagetab.c | 2 +- tools/libxc/xc_ptrace.c | 11 +++++++---- tools/libxc/xc_ptrace_core.c | 15 +++++++-------- 7 files changed, 32 insertions(+), 29 deletions(-) diff --git a/tools/debugger/libxendebug/xendebug.c b/tools/debugger/libxendebug/xendebug.c index 8a4160637c..1a12848f5d 100644 --- a/tools/debugger/libxendebug/xendebug.c +++ b/tools/debugger/libxendebug/xendebug.c @@ -346,8 +346,9 @@ xendebug_memory_page (domain_context_p ctxt, int xc_handle, uint32_t vcpu, ctxt->cr3_phys[vcpu] = vcpu_ctxt->ctrlreg[3]; if ( ctxt->cr3_virt[vcpu] ) munmap(ctxt->cr3_virt[vcpu], PAGE_SIZE); - ctxt->cr3_virt[vcpu] = xc_map_foreign_range(xc_handle, ctxt->domid, - PAGE_SIZE, PROT_READ, ctxt->cr3_phys[vcpu] >> PAGE_SHIFT); + ctxt->cr3_virt[vcpu] = xc_map_foreign_range( + xc_handle, ctxt->domid, PAGE_SIZE, PROT_READ, + xen_cr3_to_pfn(ctxt->cr3_phys[vcpu])); if ( ctxt->cr3_virt[vcpu] == NULL ) return 0; } diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 1db2d904d3..7d45c02942 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -205,9 +205,9 @@ static int setup_pg_tables(int xc_handle, uint32_t dom, alloc_pt(l2tab, vl2tab, pl2tab); vl2e = &vl2tab[l2_table_offset(dsi_v_start)]; if (shadow_mode_enabled) - ctxt->ctrlreg[3] = pl2tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl2tab >> PAGE_SHIFT); else - ctxt->ctrlreg[3] = l2tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT); for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ ) { @@ -268,9 +268,9 @@ static int setup_pg_tables_pae(int xc_handle, uint32_t dom, alloc_pt(l3tab, vl3tab, pl3tab); vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; if (shadow_mode_enabled) - ctxt->ctrlreg[3] = pl3tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl3tab >> PAGE_SHIFT); else - ctxt->ctrlreg[3] = l3tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT); for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++) { @@ -361,9 +361,9 @@ static int setup_pg_tables_64(int xc_handle, uint32_t dom, alloc_pt(l4tab, vl4tab, pl4tab); vl4e = &vl4tab[l4_table_offset(dsi_v_start)]; if (shadow_mode_enabled) - ctxt->ctrlreg[3] = pl4tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl4tab >> PAGE_SHIFT); else - ctxt->ctrlreg[3] = l4tab; + ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT); for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++) { @@ -827,13 +827,13 @@ static int setup_guest(int xc_handle, if ( dsi.pae_kernel ) { if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE, - ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) ) + xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) goto error_out; } else { if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, - ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) ) + xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) goto error_out; } } @@ -845,7 +845,7 @@ static int setup_guest(int xc_handle, * correct protection for the page */ if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, - ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) ) + xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) goto error_out; #endif diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 353e0c7d63..dd53999211 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -536,7 +536,7 @@ int xc_linux_restore(int xc_handle, int io_fd, } /* Uncanonicalise the page table base pointer. */ - pfn = ctxt.ctrlreg[3] >> PAGE_SHIFT; + pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]); if (pfn >= max_pfn) { ERR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx", @@ -552,7 +552,7 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } - ctxt.ctrlreg[3] = p2m[pfn] << PAGE_SHIFT; + ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]); /* clear any pending events and the selector */ memset(&(shared_info->evtchn_pending[0]), 0, diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 34387abd07..7e6cc8b641 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -1129,12 +1129,12 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } /* Canonicalise the page table base pointer. */ - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.ctrlreg[3] >> PAGE_SHIFT) ) { + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) { ERR("PT base is not in range of pseudophys map"); goto out; } - ctxt.ctrlreg[3] = mfn_to_pfn(ctxt.ctrlreg[3] >> PAGE_SHIFT) << - PAGE_SHIFT; + ctxt.ctrlreg[3] = + xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3]))); if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) || !write_exact(io_fd, live_shinfo, PAGE_SIZE)) { diff --git a/tools/libxc/xc_pagetab.c b/tools/libxc/xc_pagetab.c index 02a19b5527..64c05c74e6 100644 --- a/tools/libxc/xc_pagetab.c +++ b/tools/libxc/xc_pagetab.c @@ -78,7 +78,7 @@ unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, fprintf(stderr, "failed to retreive vcpu context\n"); goto out; } - cr3 = ctx.ctrlreg[3]; + cr3 = ((unsigned long long)xen_cr3_to_pfn(ctx.ctrlreg[3])) << PAGE_SHIFT; /* Page Map Level 4 */ diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c index aacbf3db26..e39f3fc775 100644 --- a/tools/libxc/xc_ptrace.c +++ b/tools/libxc/xc_ptrace.c @@ -190,7 +190,8 @@ map_domain_va_32( static void *v[MAX_VIRT_CPUS]; l2 = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); + xc_handle, current_domid, PAGE_SIZE, PROT_READ, + xen_cr3_to_pfn(ctxt[cpu].ctrlreg[3])); if ( l2 == NULL ) return NULL; @@ -230,7 +231,8 @@ map_domain_va_pae( static void *v[MAX_VIRT_CPUS]; l3 = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); + xc_handle, current_domid, PAGE_SIZE, PROT_READ, + xen_cr3_to_pfn(ctxt[cpu].ctrlreg[3])); if ( l3 == NULL ) return NULL; @@ -282,8 +284,9 @@ map_domain_va_64( if ((ctxt[cpu].ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */ return map_domain_va_32(xc_handle, cpu, guest_va, perm); - l4 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, - PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); + l4 = xc_map_foreign_range( + xc_handle, current_domid, PAGE_SIZE, PROT_READ, + xen_cr3_to_pfn(ctxt[cpu].ctrlreg[3])); if ( l4 == NULL ) return NULL; diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c index 454349b3b0..b413c6c658 100644 --- a/tools/libxc/xc_ptrace_core.c +++ b/tools/libxc/xc_ptrace_core.c @@ -12,8 +12,8 @@ static long nr_pages = 0; static unsigned long *p2m_array = NULL; static unsigned long *m2p_array = NULL; -static unsigned long pages_offset; -static unsigned long cr3[MAX_VIRT_CPUS]; +static unsigned long pages_offset; +static unsigned long cr3[MAX_VIRT_CPUS]; /* --------------------- */ @@ -47,7 +47,7 @@ map_domain_va_core(unsigned long domfd, int cpu, void * guest_va, munmap(cr3_virt[cpu], PAGE_SIZE); v = mmap( NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, - map_mtop_offset(cr3_phys[cpu])); + map_mtop_offset(xen_cr3_to_pfn(cr3_phys[cpu]))); if (v == MAP_FAILED) { perror("mmap failed"); @@ -127,14 +127,15 @@ xc_waitdomain_core( sizeof(vcpu_guest_context_t)*nr_vcpus) return -1; - for (i = 0; i < nr_vcpus; i++) { + for (i = 0; i < nr_vcpus; i++) cr3[i] = ctxt[i].ctrlreg[3]; - } + if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { printf("Could not allocate p2m_array\n"); return -1; } + if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) != sizeof(unsigned long)*nr_pages) return -1; @@ -146,10 +147,8 @@ xc_waitdomain_core( } bzero(m2p_array, sizeof(unsigned long)* 1 << 20); - for (i = 0; i < nr_pages; i++) { + for (i = 0; i < nr_pages; i++) m2p_array[p2m_array[i]] = i; - } - } return 0; } From 7ec31d2960d0f5e4c1dfbd3d0d003860f51c6054 Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Fri, 2 Jun 2006 17:54:55 +0100 Subject: [PATCH 23/38] Fix Xen build with some versions of gcc. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index e8b2d647a7..7c6297b917 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -259,7 +259,7 @@ int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c) { struct domain *d = v->domain; - unsigned long cr3_pfn; + unsigned long cr3_pfn = INVALID_MFN; int i, rc; if ( !(c->flags & VGCF_HVM_GUEST) ) From 585c0a452871849b8a8d1e428b50983cf1c4692c Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Fri, 2 Jun 2006 18:06:50 +0100 Subject: [PATCH 24/38] [LINUX][X86_64] Destroy initial page-table mappings to avoid overlap with modules. The temporary mappings needed to set up the 1:1 mappings must be torn down after use; otherwise they may trigger the WARN_ON() in vmap_pte_range() (namely if the chunk allocated to hold kernel and initial page tables gets close to or exceeds 128Mb, or if a sufficiently high mem= argument causes the static allocations to grow beyond 128Mb, which in either case means these mappings extend into the modules area). Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index 1de014d05b..9646f60598 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -666,7 +666,18 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end) set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); } - BUG_ON(!after_bootmem && start_pfn != table_end); + if (!after_bootmem) { + BUG_ON(start_pfn != table_end); + /* + * Destroy the temporary mappings created above. Prevents + * overlap with modules area (if init mapping is very big). + */ + start = __START_KERNEL_map + (table_start << PAGE_SHIFT); + end = __START_KERNEL_map + (table_end << PAGE_SHIFT); + for (; start < end; start += PAGE_SIZE) + WARN_ON(HYPERVISOR_update_va_mapping( + start, __pte_ma(0), 0)); + } __flush_tlb_all(); } From 44beffcd619b6cfea4afb3875258de6245fb2ab9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Jun 2006 19:14:44 +0100 Subject: [PATCH 25/38] [LINUX] Simply shared_info mapping code. Always use a fixmap. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/mm/init-xen.c | 14 +++++--------- .../arch/x86_64/kernel/setup-xen.c | 7 ------- linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 14 +++++--------- .../include/asm-i386/mach-xen/setup_arch_post.h | 7 ------- 4 files changed, 10 insertions(+), 32 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c index e2487b326f..b0f325ef87 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c @@ -558,15 +558,11 @@ void __init paging_init(void) kmap_init(); - if (!xen_feature(XENFEAT_auto_translated_physmap) || - xen_start_info->shared_info >= xen_start_info->nr_pages) { - /* Switch to the real shared_info page, and clear the - * dummy page. */ - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - HYPERVISOR_shared_info = - (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - memset(empty_zero_page, 0, sizeof(empty_zero_page)); - } + /* Switch to the real shared_info page, and clear the + * dummy page. */ + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + memset(empty_zero_page, 0, sizeof(empty_zero_page)); /* Setup mapping of lower 1st MB */ for (i = 0; i < NR_FIX_ISAMAPS; i++) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c index adfd37d048..e02aba7b34 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c @@ -665,13 +665,6 @@ void __init setup_arch(char **cmdline_p) setup_xen_features(); - if (xen_feature(XENFEAT_auto_translated_physmap) && - xen_start_info->shared_info < xen_start_info->nr_pages) { - HYPERVISOR_shared_info = - (shared_info_t *)__va(xen_start_info->shared_info); - memset(empty_zero_page, 0, sizeof(empty_zero_page)); - } - HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index 9646f60598..3882686049 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -763,15 +763,11 @@ void __init paging_init(void) free_area_init_node(0, NODE_DATA(0), zones, __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); - if (!xen_feature(XENFEAT_auto_translated_physmap) || - xen_start_info->shared_info >= xen_start_info->nr_pages) { - /* Switch to the real shared_info page, and clear the - * dummy page. */ - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - HYPERVISOR_shared_info = - (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - memset(empty_zero_page, 0, sizeof(empty_zero_page)); - } + /* Switch to the real shared_info page, and clear the + * dummy page. */ + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + memset(empty_zero_page, 0, sizeof(empty_zero_page)); init_mm.context.pinned = 1; diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h index bf93a85439..18a2a6c140 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h @@ -61,13 +61,6 @@ static void __init machine_specific_arch_setup(void) .address = { __KERNEL_CS, (unsigned long)nmi }, }; - if (xen_feature(XENFEAT_auto_translated_physmap) && - xen_start_info->shared_info < xen_start_info->nr_pages) { - HYPERVISOR_shared_info = - (shared_info_t *)__va(xen_start_info->shared_info); - memset(empty_zero_page, 0, sizeof(empty_zero_page)); - } - ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event); if (ret == 0) ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); From ad2de846762c7af9b3661f5ef9e9d7414dd4ccb5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 10:42:40 +0100 Subject: [PATCH 26/38] Create new vmassist type 'pae_extended_cr3'. Only advertise pae_pgdir_above_4gb tp guests that have enabled this vmassist. Control tools ensure all PAE page directories are below 4GB unless the vmassist is enabled (triggered via an extended-cr3 option in guest Elf header). Signed-off-by: Keir Fraser --- tools/libxc/xc_linux_build.c | 37 +++++-- tools/libxc/xc_linux_restore.c | 196 ++++++++++++++++++++++++++++++--- tools/libxc/xc_linux_save.c | 25 ++++- tools/libxc/xc_load_elf.c | 11 +- tools/libxc/xc_private.c | 22 ++++ tools/libxc/xenctrl.h | 3 + tools/libxc/xg_private.h | 3 + xen/arch/x86/domain_build.c | 3 + xen/arch/x86/mm.c | 15 +++ xen/common/kernel.c | 5 +- xen/common/keyhandler.c | 5 +- xen/include/public/xen.h | 16 ++- 12 files changed, 306 insertions(+), 35 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 7d45c02942..8dd7f4928c 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -254,17 +254,33 @@ static int setup_pg_tables_pae(int xc_handle, uint32_t dom, unsigned long *page_array, unsigned long vpt_start, unsigned long vpt_end, - unsigned shadow_mode_enabled) + unsigned shadow_mode_enabled, + unsigned pae_mode) { l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL; l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL; l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL; uint64_t l1tab, l2tab, l3tab, pl1tab, pl2tab, pl3tab; - unsigned long ppt_alloc, count; + unsigned long ppt_alloc, count, nmfn; /* First allocate page for page dir. */ ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; + if ( pae_mode == PAEKERN_extended_cr3 ) + { + ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); + } + else if ( page_array[ppt_alloc] > 0xfffff ) + { + nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]); + if ( nmfn == 0 ) + { + fprintf(stderr, "Couldn't get a page below 4GB :-(\n"); + goto error_out; + } + page_array[ppt_alloc] = nmfn; + } + alloc_pt(l3tab, vl3tab, pl3tab); vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; if (shadow_mode_enabled) @@ -579,11 +595,11 @@ static int compat_check(int xc_handle, struct domain_setup_info *dsi) } if (strstr(xen_caps, "xen-3.0-x86_32p")) { - if (!dsi->pae_kernel) { + if (dsi->pae_kernel == PAEKERN_no) { ERROR("Non PAE-kernel on PAE host."); return 0; } - } else if (dsi->pae_kernel) { + } else if (dsi->pae_kernel != PAEKERN_no) { ERROR("PAE-kernel on non-PAE host."); return 0; } @@ -673,7 +689,8 @@ static int setup_guest(int xc_handle, for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ ) { - if ( (supported_features[i]&required_features[i]) != required_features[i] ) + if ( (supported_features[i] & required_features[i]) != + required_features[i] ) { ERROR("Guest kernel does not support a required feature."); goto error_out; @@ -719,7 +736,7 @@ static int setup_guest(int xc_handle, (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ ((_l) & ~((1UL<<(_s))-1))) >> (_s)) #if defined(__i386__) - if ( dsi.pae_kernel ) + if ( dsi.pae_kernel != PAEKERN_no ) { if ( (1 + /* # L3 */ NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */ @@ -797,11 +814,11 @@ static int setup_guest(int xc_handle, /* setup page tables */ #if defined(__i386__) - if (dsi.pae_kernel) + if (dsi.pae_kernel != PAEKERN_no) rc = setup_pg_tables_pae(xc_handle, dom, ctxt, dsi.v_start, v_end, page_array, vpt_start, vpt_end, - shadow_mode_enabled); + shadow_mode_enabled, dsi.pae_kernel); else rc = setup_pg_tables(xc_handle, dom, ctxt, dsi.v_start, v_end, @@ -824,7 +841,7 @@ static int setup_guest(int xc_handle, */ if ( !shadow_mode_enabled ) { - if ( dsi.pae_kernel ) + if ( dsi.pae_kernel != PAEKERN_no ) { if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE, xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) @@ -958,7 +975,7 @@ static int setup_guest(int xc_handle, rc = xc_version(xc_handle, XENVER_version, NULL); sprintf(start_info->magic, "xen-%i.%i-x86_%d%s", rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8, - dsi.pae_kernel ? "p" : ""); + (dsi.pae_kernel != PAEKERN_no) ? "p" : ""); start_info->nr_pages = nr_pages; start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT; start_info->flags = flags; diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index dd53999211..86f880bb13 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -108,7 +108,7 @@ int xc_linux_restore(int xc_handle, int io_fd, unsigned int console_evtchn, unsigned long *console_mfn) { DECLARE_DOM0_OP; - int rc = 1, i, n; + int rc = 1, i, n, pae_extended_cr3 = 0; unsigned long mfn, pfn; unsigned int prev_pc, this_pc; int verify = 0; @@ -162,25 +162,83 @@ int xc_linux_restore(int xc_handle, int io_fd, return 1; } - if (mlock(&ctxt, sizeof(ctxt))) { /* needed for build dom0 op, but might as well do early */ ERR("Unable to mlock ctxt"); return 1; } - - /* Read the saved P2M frame list */ - if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) { + if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) { ERR("Couldn't allocate p2m_frame_list array"); goto out; } - if (!read_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) { - ERR("read p2m_frame_list failed"); + /* Read first entry of P2M list, or extended-info signature (~0UL). */ + if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) { + ERR("read extended-info signature failed"); goto out; } + if (p2m_frame_list[0] == ~0UL) { + uint32_t tot_bytes; + + /* Next 4 bytes: total size of following extended info. */ + if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) { + ERR("read extended-info size failed"); + goto out; + } + + while (tot_bytes) { + uint32_t chunk_bytes; + char chunk_sig[4]; + + /* 4-character chunk signature + 4-byte remaining chunk size. */ + if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) || + !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) { + ERR("read extended-info chunk signature failed"); + goto out; + } + tot_bytes -= 8; + + /* VCPU context structure? */ + if (!strncmp(chunk_sig, "vcpu", 4)) { + if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) { + ERR("read extended-info vcpu context failed"); + goto out; + } + tot_bytes -= sizeof(struct vcpu_guest_context); + chunk_bytes -= sizeof(struct vcpu_guest_context); + + if (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) + pae_extended_cr3 = 1; + } + + /* Any remaining bytes of this chunk: read and discard. */ + while (chunk_bytes) { + unsigned long sz = chunk_bytes; + if ( sz > P2M_FL_SIZE ) + sz = P2M_FL_SIZE; + if (!read_exact(io_fd, p2m_frame_list, sz)) { + ERR("read-and-discard extended-info chunk bytes failed"); + goto out; + } + chunk_bytes -= sz; + tot_bytes -= sz; + } + } + + /* Now read the real first entry of P2M list. */ + if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) { + ERR("read first entry of p2m_frame_list failed"); + goto out; + } + } + + /* First entry is already read into the p2m array. */ + if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) { + ERR("read p2m_frame_list failed"); + goto out; + } /* We want zeroed memory so use calloc rather than malloc. */ p2m = calloc(max_pfn, sizeof(unsigned long)); @@ -331,17 +389,27 @@ int xc_linux_restore(int xc_handle, int io_fd, ** A page table page - need to 'uncanonicalize' it, i.e. ** replace all the references to pfns with the corresponding ** mfns for the new domain. + ** + ** On PAE we need to ensure that PGDs are in MFNs < 4G, and + ** so we may need to update the p2m after the main loop. + ** Hence we defer canonicalization of L1s until then. */ - if(!uncanonicalize_pagetable(pagetype, page)) { - /* - ** Failing to uncanonicalize a page table can be ok - ** under live migration since the pages type may have - ** changed by now (and we'll get an update later). - */ - DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n", - pagetype >> 28, pfn, mfn); - nraces++; - continue; + if ((pt_levels != 3) || + pae_extended_cr3 || + (pagetype != L1TAB)) { + + if (!uncanonicalize_pagetable(pagetype, page)) { + /* + ** Failing to uncanonicalize a page table can be ok + ** under live migration since the pages type may have + ** changed by now (and we'll get an update later). + */ + DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n", + pagetype >> 28, pfn, mfn); + nraces++; + continue; + } + } } else if(pagetype != NOTAB) { @@ -390,6 +458,100 @@ int xc_linux_restore(int xc_handle, int io_fd, DPRINTF("Received all pages (%d races)\n", nraces); + if ((pt_levels == 3) && !pae_extended_cr3) { + + /* + ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This + ** is a little awkward and involves (a) finding all such PGDs and + ** replacing them with 'lowmem' versions; (b) upating the p2m[] + ** with the new info; and (c) canonicalizing all the L1s using the + ** (potentially updated) p2m[]. + ** + ** This is relatively slow (and currently involves two passes through + ** the pfn_type[] array), but at least seems to be correct. May wish + ** to consider more complex approaches to optimize this later. + */ + + int j, k; + + /* First pass: find all L3TABs current in > 4G mfns and get new mfns */ + for (i = 0; i < max_pfn; i++) { + + if (((pfn_type[i] & LTABTYPE_MASK)==L3TAB) && (p2m[i]>0xfffffUL)) { + + unsigned long new_mfn; + uint64_t l3ptes[4]; + uint64_t *l3tab; + + l3tab = (uint64_t *) + xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ, p2m[i]); + + for(j = 0; j < 4; j++) + l3ptes[j] = l3tab[j]; + + munmap(l3tab, PAGE_SIZE); + + if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) { + ERR("Couldn't get a page below 4GB :-("); + goto out; + } + + p2m[i] = new_mfn; + if (xc_add_mmu_update(xc_handle, mmu, + (((unsigned long long)new_mfn) + << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, i)) { + ERR("Couldn't m2p on PAE root pgdir"); + goto out; + } + + l3tab = (uint64_t *) + xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, p2m[i]); + + for(j = 0; j < 4; j++) + l3tab[j] = l3ptes[j]; + + munmap(l3tab, PAGE_SIZE); + + } + } + + /* Second pass: find all L1TABs and uncanonicalize them */ + j = 0; + + for(i = 0; i < max_pfn; i++) { + + if (((pfn_type[i] & LTABTYPE_MASK)==L1TAB)) { + region_mfn[j] = p2m[i]; + j++; + } + + if(i == (max_pfn-1) || j == MAX_BATCH_SIZE) { + + if (!(region_base = xc_map_foreign_batch( + xc_handle, dom, PROT_READ | PROT_WRITE, + region_mfn, j))) { + ERR("map batch failed"); + goto out; + } + + for(k = 0; k < j; k++) { + if(!uncanonicalize_pagetable(L1TAB, + region_base + k*PAGE_SIZE)) { + ERR("failed uncanonicalize pt!"); + goto out; + } + } + + munmap(region_base, j*PAGE_SIZE); + j = 0; + } + } + + } + if (xc_finish_mmu_updates(xc_handle, mmu)) { ERR("Error doing finish_mmu_updates()"); diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 7e6cc8b641..8f110c2223 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -818,12 +818,33 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Start writing out the saved-domain record. */ - if(!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { + if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { ERR("write: max_pfn"); goto out; } - if(!write_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) { + /* + * Write an extended-info structure to inform the restore code that + * a PAE guest understands extended CR3 (PDPTs above 4GB). Turns off + * slow paths in the restore code. + */ + if ((pt_levels == 3) && + (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3))) { + unsigned long signature = ~0UL; + uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8; + uint32_t chunk_sz = sizeof(struct vcpu_guest_context); + char chunk_sig[] = "vcpu"; + if (!write_exact(io_fd, &signature, sizeof(signature)) || + !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) || + !write_exact(io_fd, &chunk_sig, 4) || + !write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) || + !write_exact(io_fd, &ctxt, sizeof(ctxt))) { + ERR("write: extended info"); + goto out; + } + } + + if (!write_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) { ERR("write: p2m_frame_list"); goto out; } diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c index 89396efd14..422e7a4a8b 100644 --- a/tools/libxc/xc_load_elf.c +++ b/tools/libxc/xc_load_elf.c @@ -122,8 +122,15 @@ static int parseelfimage(const char *image, ERROR("Actually saw: '%s'", guestinfo); return -EINVAL; } - if ( (strstr(guestinfo, "PAE=yes") != NULL) ) - dsi->pae_kernel = 1; + + dsi->pae_kernel = PAEKERN_no; + p = strstr(guestinfo, "PAE=yes"); + if ( p != NULL ) + { + dsi->pae_kernel = PAEKERN_yes; + if ( !strncmp(p+7, "[extended-cr3]", 14) ) + dsi->pae_kernel = PAEKERN_extended_cr3; + } break; } diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 0c7df9f83f..f776d2ff0a 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -430,6 +430,28 @@ int xc_version(int xc_handle, int cmd, void *arg) return rc; } +unsigned long xc_make_page_below_4G( + int xc_handle, uint32_t domid, unsigned long mfn) +{ + unsigned long new_mfn; + + if ( xc_domain_memory_decrease_reservation( + xc_handle, domid, 1, 0, &mfn) != 0 ) + { + fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn); + return 0; + } + + if ( xc_domain_memory_increase_reservation( + xc_handle, domid, 1, 0, 32, &new_mfn) != 0 ) + { + fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn); + return 0; + } + + return new_mfn; +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index a5471bc70b..2a1a86d7f5 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -453,6 +453,9 @@ int xc_domain_iomem_permission(int xc_handle, unsigned long nr_mfns, uint8_t allow_access); +unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, + unsigned long mfn); + typedef dom0_perfc_desc_t xc_perfc_desc_t; /* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ int xc_perfc_control(int xc_handle, diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index 8fbf047d17..affd6a07df 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -156,6 +156,9 @@ struct domain_setup_info unsigned long elf_paddr_offset; +#define PAEKERN_no 0 +#define PAEKERN_yes 1 +#define PAEKERN_extended_cr3 2 unsigned int pae_kernel; unsigned int load_symtab; diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 80fd8513c2..723731e37c 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -302,6 +302,9 @@ int construct_dom0(struct domain *d, return -EINVAL; } + if ( xen_pae && !!strstr(dsi.xen_section_string, "PAE=yes[extended-cr3]") ) + set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist); + if ( (p = strstr(dsi.xen_section_string, "FEATURES=")) != NULL ) { parse_features( diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f53671ace0..624fc2ec37 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -997,6 +997,21 @@ static int alloc_l3_table(struct page_info *page, unsigned long type) ASSERT(!shadow_mode_refcounts(d)); +#ifdef CONFIG_X86_PAE + /* + * PAE pgdirs above 4GB are unacceptable if the guest does not understand + * the weird 'extended cr3' format for dealing with high-order address + * bits. We cut some slack for control tools (before vcpu0 is initialised). + */ + if ( (pfn >= 0x100000) && + unlikely(!VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3)) && + d->vcpu[0] && test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) ) + { + MEM_LOG("PAE pgd must be below 4GB (0x%lx >= 0x100000)", pfn); + return 0; + } +#endif + pl3e = map_domain_page(pfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) { diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 480138a065..8930c53d5c 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -184,6 +184,7 @@ long do_xen_version(int cmd, XEN_GUEST_HANDLE(void) arg) case XENVER_get_features: { xen_feature_info_t fi; + struct domain *d = current->domain; if ( copy_from_guest(&fi, arg, 1) ) return -EFAULT; @@ -191,7 +192,9 @@ long do_xen_version(int cmd, XEN_GUEST_HANDLE(void) arg) switch ( fi.submap_idx ) { case 0: - fi.submap = (1U << XENFEAT_pae_pgdir_above_4gb); + fi.submap = 0; + if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) ) + fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb); if ( shadow_mode_translate(current->domain) ) fi.submap |= (1U << XENFEAT_writable_page_tables) | diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index a80de73840..433efcd6ee 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -128,11 +128,12 @@ static void dump_domains(unsigned char key) d->domain_flags, atomic_read(&d->refcnt), d->tot_pages, d->xenheap_pages, cpuset); printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x\n", + "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n", d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3], d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7], d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11], - d->handle[12], d->handle[13], d->handle[14], d->handle[15]); + d->handle[12], d->handle[13], d->handle[14], d->handle[15], + d->vm_assist); arch_dump_domain_info(d); diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 3e2e9b005d..9cf5bdd2a5 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -234,10 +234,24 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t); */ #define VMASST_CMD_enable 0 #define VMASST_CMD_disable 1 + +/* x86/32 guests: simulate full 4GB segment limits. */ #define VMASST_TYPE_4gb_segments 0 + +/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */ #define VMASST_TYPE_4gb_segments_notify 1 + +/* + * x86 guests: support writes to bottom-level PTEs. + * NB1. Page-directory entries cannot be written. + * NB2. Guest must continue to remove all writable mappings of PTEs. + */ #define VMASST_TYPE_writable_pagetables 2 -#define MAX_VMASST_TYPE 2 + +/* x86/PAE guests: support PDPTs above 4GB. */ +#define VMASST_TYPE_pae_extended_cr3 3 + +#define MAX_VMASST_TYPE 3 #ifndef __ASSEMBLY__ From d3a5ffe775160fb42bee1be875b5d0c3da11129d Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 14:35:22 +0100 Subject: [PATCH 27/38] Extend callback-registration hypercall to take a flags argument. This can currently be used to request that event delivery be disabled during callback processing. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 19 ++++++++++++++++--- xen/arch/x86/x86_32/asm-offsets.c | 2 ++ xen/arch/x86/x86_32/entry.S | 5 ++++- xen/arch/x86/x86_32/traps.c | 6 ++++++ xen/arch/x86/x86_64/asm-offsets.c | 3 +++ xen/arch/x86/x86_64/entry.S | 10 ++++++++-- xen/arch/x86/x86_64/traps.c | 12 ++++++++++++ xen/include/public/arch-x86_32.h | 14 +++++++++++--- xen/include/public/arch-x86_64.h | 16 +++++++++++++--- xen/include/public/callback.h | 15 ++++++++++++--- 10 files changed, 87 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 7c6297b917..1890956916 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -524,20 +524,29 @@ static void load_segments(struct vcpu *n) if ( unlikely(!all_segs_okay) ) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - unsigned long *rsp = + unsigned long *rsp = (n->arch.flags & TF_kernel_mode) ? (unsigned long *)regs->rsp : (unsigned long *)nctxt->kernel_sp; + unsigned long cs_and_mask, rflags; if ( !(n->arch.flags & TF_kernel_mode) ) toggle_guest_mode(n); else regs->cs &= ~3; + /* CS longword also contains full evtchn_upcall_mask. */ + cs_and_mask = (unsigned long)regs->cs | + ((unsigned long)n->vcpu_info->evtchn_upcall_mask << 32); + + /* Fold upcall mask into RFLAGS.IF. */ + rflags = regs->rflags & ~X86_EFLAGS_IF; + rflags |= !n->vcpu_info->evtchn_upcall_mask << 9; + if ( put_user(regs->ss, rsp- 1) | put_user(regs->rsp, rsp- 2) | - put_user(regs->rflags, rsp- 3) | - put_user(regs->cs, rsp- 4) | + put_user(rflags, rsp- 3) | + put_user(cs_and_mask, rsp- 4) | put_user(regs->rip, rsp- 5) | put_user(nctxt->user_regs.gs, rsp- 6) | put_user(nctxt->user_regs.fs, rsp- 7) | @@ -550,6 +559,10 @@ static void load_segments(struct vcpu *n) domain_crash(n->domain); } + if ( test_bit(_VGCF_failsafe_disables_events, + &n->arch.guest_context.flags) ) + n->vcpu_info->evtchn_upcall_mask = 1; + regs->entry_vector = TRAP_syscall; regs->rflags &= 0xFFFCBEFFUL; regs->ss = __GUEST_SS; diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c index 07830746be..f03556ef8d 100644 --- a/xen/arch/x86/x86_32/asm-offsets.c +++ b/xen/arch/x86/x86_32/asm-offsets.c @@ -64,11 +64,13 @@ void __dummy__(void) arch.guest_context.kernel_ss); OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp); + OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags); OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt); OFFSET(VCPU_flags, struct vcpu, vcpu_flags); OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr); DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending); DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked); + DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events); BLANK(); OFFSET(TSS_ss0, struct tss_struct, ss0); diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 1a4ac5367e..c0bc7e4e01 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -130,7 +130,10 @@ failsafe_callback: movl VCPU_failsafe_sel(%ebx),%eax movw %ax,TRAPBOUNCE_cs(%edx) movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%edx) - call create_bounce_frame + bt $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%ebx) + jnc 1f + orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) +1: call create_bounce_frame xorl %eax,%eax movl %eax,UREGS_ds(%esp) movl %eax,UREGS_es(%esp) diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 64c038c4ee..6fce183a17 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -346,6 +346,12 @@ static long register_guest_callback(struct callback_register *reg) case CALLBACKTYPE_failsafe: v->arch.guest_context.failsafe_callback_cs = reg->address.cs; v->arch.guest_context.failsafe_callback_eip = reg->address.eip; + if ( reg->flags & CALLBACKF_mask_events ) + set_bit(_VGCF_failsafe_disables_events, + &v->arch.guest_context.flags); + else + clear_bit(_VGCF_failsafe_disables_events, + &v->arch.guest_context.flags); break; #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index ebc3059a9c..1719c50a05 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -64,11 +64,14 @@ void __dummy__(void) arch.guest_context.syscall_callback_eip); OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp); + OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags); OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt); OFFSET(VCPU_flags, struct vcpu, vcpu_flags); OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr); DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending); DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked); + DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events); + DEFINE(_VGCF_syscall_disables_events, _VGCF_syscall_disables_events); BLANK(); OFFSET(VCPU_svm_vmcb_pa, struct vcpu, arch.hvm_svm.vmcb_pa); diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 110c34a417..62bb86510b 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -30,7 +30,10 @@ switch_to_kernel: movq VCPU_syscall_addr(%rbx),%rax movq %rax,TRAPBOUNCE_eip(%rdx) movw $0,TRAPBOUNCE_flags(%rdx) - call create_bounce_frame + bt $_VGCF_syscall_disables_events,VCPU_guest_context_flags(%rbx) + jnc 1f + orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) +1: call create_bounce_frame jmp test_all_events /* %rbx: struct vcpu, interrupts disabled */ @@ -77,7 +80,10 @@ failsafe_callback: movq VCPU_failsafe_addr(%rbx),%rax movq %rax,TRAPBOUNCE_eip(%rdx) movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx) - call create_bounce_frame + bt $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx) + jnc 1f + orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) +1: call create_bounce_frame jmp test_all_events .previous .section __pre_ex_table,"a" diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index ad7c347182..8c11a5ef4f 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -334,10 +334,22 @@ static long register_guest_callback(struct callback_register *reg) case CALLBACKTYPE_failsafe: v->arch.guest_context.failsafe_callback_eip = reg->address; + if ( reg->flags & CALLBACKF_mask_events ) + set_bit(_VGCF_failsafe_disables_events, + &v->arch.guest_context.flags); + else + clear_bit(_VGCF_failsafe_disables_events, + &v->arch.guest_context.flags); break; case CALLBACKTYPE_syscall: v->arch.guest_context.syscall_callback_eip = reg->address; + if ( reg->flags & CALLBACKF_mask_events ) + set_bit(_VGCF_syscall_disables_events, + &v->arch.guest_context.flags); + else + clear_bit(_VGCF_syscall_disables_events, + &v->arch.guest_context.flags); break; case CALLBACKTYPE_nmi: diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 2a43ae53ac..c5237ca5c8 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -138,9 +138,17 @@ typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ struct vcpu_guest_context { /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */ -#define VGCF_I387_VALID (1<<0) -#define VGCF_HVM_GUEST (1<<1) -#define VGCF_IN_KERNEL (1<<2) +#define VGCF_I387_VALID (1<<0) +#define VGCF_HVM_GUEST (1<<1) +#define VGCF_IN_KERNEL (1<<2) +#define _VGCF_i387_valid 0 +#define VGCF_i387_valid (1<<_VGCF_i387_valid) +#define _VGCF_hvm_guest 1 +#define VGCF_hvm_guest (1<<_VGCF_hvm_guest) +#define _VGCF_in_kernel 2 +#define VGCF_in_kernel (1<<_VGCF_in_kernel) +#define _VGCF_failsafe_disables_events 3 +#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) unsigned long flags; /* VGCF_* flags */ struct cpu_user_regs user_regs; /* User-level CPU registers */ struct trap_info trap_ctxt[256]; /* Virtual IDT */ diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 0b0ca809ca..bea67d4b0c 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -211,9 +211,19 @@ typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ struct vcpu_guest_context { /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */ -#define VGCF_I387_VALID (1<<0) -#define VGCF_HVM_GUEST (1<<1) -#define VGCF_IN_KERNEL (1<<2) +#define VGCF_I387_VALID (1<<0) +#define VGCF_HVM_GUEST (1<<1) +#define VGCF_IN_KERNEL (1<<2) +#define _VGCF_i387_valid 0 +#define VGCF_i387_valid (1<<_VGCF_i387_valid) +#define _VGCF_hvm_guest 1 +#define VGCF_hvm_guest (1<<_VGCF_hvm_guest) +#define _VGCF_in_kernel 2 +#define VGCF_in_kernel (1<<_VGCF_in_kernel) +#define _VGCF_failsafe_disables_events 3 +#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) +#define _VGCF_syscall_disables_events 4 +#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events) unsigned long flags; /* VGCF_* flags */ struct cpu_user_regs user_regs; /* User-level CPU registers */ struct trap_info trap_ctxt[256]; /* Virtual IDT */ diff --git a/xen/include/public/callback.h b/xen/include/public/callback.h index a9f4168dda..b497d99317 100644 --- a/xen/include/public/callback.h +++ b/xen/include/public/callback.h @@ -28,13 +28,21 @@ #define CALLBACKTYPE_sysenter 3 #define CALLBACKTYPE_nmi 4 +/* + * Disable event deliver during callback? This flag is ignored for event and + * NMI callbacks: event delivery is unconditionally disabled. + */ +#define _CALLBACKF_mask_events 0 +#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events) + /* * Register a callback. */ #define CALLBACKOP_register 0 struct callback_register { - int type; - xen_callback_t address; + uint16_t type; + uint16_t flags; + xen_callback_t address; }; typedef struct callback_register callback_register_t; DEFINE_XEN_GUEST_HANDLE(callback_register_t); @@ -47,7 +55,8 @@ DEFINE_XEN_GUEST_HANDLE(callback_register_t); */ #define CALLBACKOP_unregister 1 struct callback_unregister { - int type; + uint16_t type; + uint16_t _unused; }; typedef struct callback_unregister callback_unregister_t; DEFINE_XEN_GUEST_HANDLE(callback_unregister_t); From 08f2d66ff68e069cc7cc6f6ec3097aa545568527 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 15:14:58 +0100 Subject: [PATCH 28/38] [NET] back: fix synchronisation of access to deallocation buffer ring. Must ensure ring is written to before producer index is incremented. Bug diagnosed by Ky Srinivasan Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index fb6b88e5e2..238565f1bb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -458,6 +458,9 @@ inline static void net_tx_action_dealloc(void) dc = dealloc_cons; dp = dealloc_prod; + /* Ensure we see all indexes enqueued by netif_idx_release(). */ + smp_rmb(); + /* * Free up any grants we have finished using */ @@ -695,7 +698,10 @@ static void netif_idx_release(u16 pending_idx) unsigned long flags; spin_lock_irqsave(&_lock, flags); - dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx; + dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx; + /* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */ + smp_wmb(); + dealloc_prod++; spin_unlock_irqrestore(&_lock, flags); tasklet_schedule(&net_tx_tasklet); From 3e19af6e66e439c5297a8c885f256674c17aff50 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 15:18:13 +0100 Subject: [PATCH 29/38] [VMXASSIST] Extensions to vmxassist to handle additional mode switch cases. Extends vmxassist to handle two cases related to mode switching found while experimenting with different boot loaders. The first case is use of the JMP instruction with memory location operands to complete a switch to protected mode. This patch adds emulation for this form of the JMP instruction to vmxassist. The second case is where boot loader code does not save/restore a non-zero SS register across a protected mode traversal. Zeroing the SS register in vmxassist results in all sorts of problems in the domU after returning back to real mode. This patch stores segment register values before entering protected mode and correctly restores the old values (instead of an incorrect zero value) when reentering real mode. Signed-off-by: Kevin Tronkowski --- tools/firmware/vmxassist/vm86.c | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c index e18efc1c64..edb7dd685b 100644 --- a/tools/firmware/vmxassist/vm86.c +++ b/tools/firmware/vmxassist/vm86.c @@ -37,6 +37,8 @@ static unsigned prev_eip = 0; enum vm86_mode mode = 0; +static struct regs saved_rm_regs; + #ifdef DEBUG int traceset = 0; @@ -795,6 +797,8 @@ protected_mode(struct regs *regs) oldctx.esp = regs->uesp; oldctx.eflags = regs->eflags; + memset(&saved_rm_regs, 0, sizeof(struct regs)); + /* reload all segment registers */ if (!load_seg(regs->cs, &oldctx.cs_base, &oldctx.cs_limit, &oldctx.cs_arbytes)) @@ -808,6 +812,7 @@ protected_mode(struct regs *regs) load_seg(0, &oldctx.es_base, &oldctx.es_limit, &oldctx.es_arbytes); oldctx.es_sel = 0; + saved_rm_regs.ves = regs->ves; } if (load_seg(regs->uss, &oldctx.ss_base, @@ -817,6 +822,7 @@ protected_mode(struct regs *regs) load_seg(0, &oldctx.ss_base, &oldctx.ss_limit, &oldctx.ss_arbytes); oldctx.ss_sel = 0; + saved_rm_regs.uss = regs->uss; } if (load_seg(regs->vds, &oldctx.ds_base, @@ -826,6 +832,7 @@ protected_mode(struct regs *regs) load_seg(0, &oldctx.ds_base, &oldctx.ds_limit, &oldctx.ds_arbytes); oldctx.ds_sel = 0; + saved_rm_regs.vds = regs->vds; } if (load_seg(regs->vfs, &oldctx.fs_base, @@ -835,6 +842,7 @@ protected_mode(struct regs *regs) load_seg(0, &oldctx.fs_base, &oldctx.fs_limit, &oldctx.fs_arbytes); oldctx.fs_sel = 0; + saved_rm_regs.vfs = regs->vfs; } if (load_seg(regs->vgs, &oldctx.gs_base, @@ -844,6 +852,7 @@ protected_mode(struct regs *regs) load_seg(0, &oldctx.gs_base, &oldctx.gs_limit, &oldctx.gs_arbytes); oldctx.gs_sel = 0; + saved_rm_regs.vgs = regs->vgs; } /* initialize jump environment to warp back to protected mode */ @@ -880,16 +889,22 @@ real_mode(struct regs *regs) if (regs->uss >= HIGHMEM) panic("%%ss 0x%lx higher than 1MB", regs->uss); regs->uss = address(regs, regs->uss, 0) >> 4; + } else { + regs->uss = saved_rm_regs.uss; } if (regs->vds != 0) { if (regs->vds >= HIGHMEM) panic("%%ds 0x%lx higher than 1MB", regs->vds); regs->vds = address(regs, regs->vds, 0) >> 4; + } else { + regs->vds = saved_rm_regs.vds; } if (regs->ves != 0) { if (regs->ves >= HIGHMEM) panic("%%es 0x%lx higher than 1MB", regs->ves); regs->ves = address(regs, regs->ves, 0) >> 4; + } else { + regs->ves = saved_rm_regs.ves; } /* this should get us into 16-bit mode */ @@ -981,6 +996,39 @@ jmpl(struct regs *regs, int prefix) panic("jmpl"); } +static void +jmpl_indirect(struct regs *regs, int prefix, unsigned modrm) +{ + unsigned n = regs->eip; + unsigned cs, eip; + unsigned addr; + + addr = operand(prefix, regs, modrm); + + if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */ + eip = (prefix & DATA32) ? read32(addr) : read16(addr); + addr += (prefix & DATA32) ? 4 : 2; + cs = read16(addr); + + TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); + + regs->cs = cs; + regs->eip = eip; + set_mode(regs, VM86_PROTECTED); + } else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */ + eip = (prefix & DATA32) ? read32(addr) : read16(addr); + addr += (prefix & DATA32) ? 4 : 2; + cs = read16(addr); + + TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); + + regs->cs = cs; + regs->eip = eip; + set_mode(regs, VM86_REAL); + } else + panic("jmpl"); +} + static void retl(struct regs *regs, int prefix) { @@ -1306,6 +1354,23 @@ opcode(struct regs *regs) } goto invalid; + case 0xFF: /* jmpl (indirect) */ + if ((mode == VM86_REAL_TO_PROTECTED) || + (mode == VM86_PROTECTED_TO_REAL)) { + unsigned modrm = fetch8(regs); + + switch((modrm >> 3) & 7) { + case 5: + jmpl_indirect(regs, prefix, modrm); + return OPC_INVALID; + + default: + break; + } + + } + goto invalid; + case 0xEB: /* short jump */ if ((mode == VM86_REAL_TO_PROTECTED) || (mode == VM86_PROTECTED_TO_REAL)) { From 99812f4013c542f82026f94e12f416ced00c8c1c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 16:13:47 +0100 Subject: [PATCH 30/38] [NET] back: Add SG support This patch adds scatter-and-gather support to the backend. It also advertises this fact through xenbus so that the frontend can detect this and send through SG requests only if it is supported. SG support is required to support skb's larger than one page. This in turn is needed for either jumbo MTU or TSO. One of these is required to bring local networking performance up to a level that is acceptable. Signed-off-by: Herbert Xu --- .../drivers/xen/netback/netback.c | 273 ++++++++++++++---- .../drivers/xen/netback/xenbus.c | 26 ++ xen/include/public/io/netif.h | 4 + xen/include/public/io/ring.h | 10 +- 4 files changed, 260 insertions(+), 53 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 238565f1bb..ca712d2a61 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -490,6 +490,178 @@ inline static void net_tx_action_dealloc(void) } } +static void netbk_tx_err(netif_t *netif, RING_IDX end) +{ + RING_IDX cons = netif->tx.req_cons; + + do { + netif_tx_request_t *txp = RING_GET_REQUEST(&netif->tx, cons); + make_tx_response(netif, txp->id, NETIF_RSP_ERROR); + } while (++cons < end); + netif->tx.req_cons = cons; + netif_schedule_work(netif); + netif_put(netif); +} + +static int netbk_count_requests(netif_t *netif, netif_tx_request_t *txp, + int work_to_do) +{ + netif_tx_request_t *first = txp; + RING_IDX cons = netif->tx.req_cons; + int frags = 1; + + while (txp->flags & NETTXF_more_data) { + if (frags >= work_to_do) { + DPRINTK("Need more frags\n"); + return -frags; + } + + txp = RING_GET_REQUEST(&netif->tx, cons + frags); + if (txp->size > first->size) { + DPRINTK("Frags galore\n"); + return -frags; + } + + first->size -= txp->size; + frags++; + + if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { + DPRINTK("txp->offset: %x, size: %u\n", + txp->offset, txp->size); + return -frags; + } + } + + return frags; +} + +static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif, + struct sk_buff *skb, + gnttab_map_grant_ref_t *mop) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + skb_frag_t *frags = shinfo->frags; + netif_tx_request_t *txp; + unsigned long pending_idx = *((u16 *)skb->data); + int nr_frags = shinfo->nr_frags; + RING_IDX cons = netif->tx.req_cons + 1; + int i; + + if ((unsigned long)shinfo->frags[0].page == pending_idx) { + frags++; + nr_frags--; + } + + for (i = 0; i < nr_frags; i++) { + txp = RING_GET_REQUEST(&netif->tx, cons + i); + pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)]; + + gnttab_set_map_op(mop++, MMAP_VADDR(pending_idx), + GNTMAP_host_map | GNTMAP_readonly, + txp->gref, netif->domid); + + memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp)); + netif_get(netif); + pending_tx_info[pending_idx].netif = netif; + frags[i].page = (void *)pending_idx; + } + + return mop; +} + +static int netbk_tx_check_mop(struct sk_buff *skb, + gnttab_map_grant_ref_t **mopp) +{ + gnttab_map_grant_ref_t *mop = *mopp; + int pending_idx = *((u16 *)skb->data); + netif_t *netif = pending_tx_info[pending_idx].netif; + netif_tx_request_t *txp; + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int start; + int err; + int i; + + err = mop->status; + if (unlikely(err)) { + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp->id, NETIF_RSP_ERROR); + pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + netif_put(netif); + } else { + set_phys_to_machine( + __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT, + FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); + grant_tx_handle[pending_idx] = mop->handle; + } + + start = 0; + if ((unsigned long)shinfo->frags[0].page == pending_idx) + start++; + + for (i = start; i < nr_frags; i++) { + int newerr; + int j; + + pending_idx = (unsigned long)shinfo->frags[i].page; + + newerr = (++mop)->status; + if (likely(!newerr)) { + set_phys_to_machine( + __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT, + FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); + grant_tx_handle[pending_idx] = mop->handle; + + if (unlikely(err)) + netif_idx_release(pending_idx); + continue; + } + + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp->id, NETIF_RSP_ERROR); + pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + netif_put(netif); + + if (err) + continue; + + pending_idx = *((u16 *)skb->data); + netif_idx_release(pending_idx); + + for (j = start; j < i; j++) { + pending_idx = (unsigned long)shinfo->frags[i].page; + netif_idx_release(pending_idx); + } + err |= newerr; + } + + *mopp = mop + 1; + return err; +} + +static void netbk_fill_frags(struct sk_buff *skb) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int i; + + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = shinfo->frags + i; + netif_tx_request_t *txp; + unsigned long pending_idx; + + pending_idx = (unsigned long)frag->page; + txp = &pending_tx_info[pending_idx].req; + frag->page = virt_to_page(MMAP_VADDR(pending_idx)); + frag->size = txp->size; + frag->page_offset = txp->offset; + + skb->len += txp->size; + skb->data_len += txp->size; + skb->truesize += txp->size; + } +} + /* Called after netfront has transmitted */ static void net_tx_action(unsigned long unused) { @@ -507,7 +679,7 @@ static void net_tx_action(unsigned long unused) net_tx_action_dealloc(); mop = tx_map_ops; - while ((NR_PENDING_REQS < MAX_PENDING_REQS) && + while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) && !list_empty(&net_schedule_list)) { /* Get a netif from the list with work to do. */ ent = net_schedule_list.next; @@ -555,38 +727,44 @@ static void net_tx_action(unsigned long unused) } netif->remaining_credit -= txreq.size; - netif->tx.req_cons++; + ret = netbk_count_requests(netif, &txreq, work_to_do); + if (unlikely(ret < 0)) { + netbk_tx_err(netif, i - ret); + continue; + } + i += ret; - netif_schedule_work(netif); + if (unlikely(ret > MAX_SKB_FRAGS + 1)) { + DPRINTK("Too many frags\n"); + netbk_tx_err(netif, i); + continue; + } - if (unlikely(txreq.size < ETH_HLEN) || - unlikely(txreq.size > ETH_FRAME_LEN)) { + if (unlikely(txreq.size < ETH_HLEN)) { DPRINTK("Bad packet size: %d\n", txreq.size); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); + netbk_tx_err(netif, i); continue; } /* No crossing a page as the payload mustn't fragment. */ - if (unlikely((txreq.offset + txreq.size) >= PAGE_SIZE)) { + if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { DPRINTK("txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset &~PAGE_MASK) + txreq.size); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); + netbk_tx_err(netif, i); continue; } pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - data_len = (txreq.size > PKT_PROT_LEN) ? + data_len = (txreq.size > PKT_PROT_LEN && + ret < MAX_SKB_FRAGS + 1) ? PKT_PROT_LEN : txreq.size; skb = alloc_skb(data_len+16, GFP_ATOMIC); if (unlikely(skb == NULL)) { DPRINTK("Can't allocate a skb in start_xmit.\n"); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); + netbk_tx_err(netif, i); break; } @@ -603,10 +781,24 @@ static void net_tx_action(unsigned long unused) pending_tx_info[pending_idx].netif = netif; *((u16 *)skb->data) = pending_idx; + __skb_put(skb, data_len); + + skb_shinfo(skb)->nr_frags = ret - 1; + if (data_len < txreq.size) { + skb_shinfo(skb)->nr_frags++; + skb_shinfo(skb)->frags[0].page = + (void *)(unsigned long)pending_idx; + } + __skb_queue_tail(&tx_queue, skb); pending_cons++; + mop = netbk_get_requests(netif, skb, mop); + + netif->tx.req_cons = i; + netif_schedule_work(netif); + if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops)) break; } @@ -620,75 +812,56 @@ static void net_tx_action(unsigned long unused) mop = tx_map_ops; while ((skb = __skb_dequeue(&tx_queue)) != NULL) { + netif_tx_request_t *txp; + pending_idx = *((u16 *)skb->data); netif = pending_tx_info[pending_idx].netif; - memcpy(&txreq, &pending_tx_info[pending_idx].req, - sizeof(txreq)); + txp = &pending_tx_info[pending_idx].req; /* Check the remap error code. */ - if (unlikely(mop->status)) { + if (unlikely(netbk_tx_check_mop(skb, &mop))) { printk(KERN_ALERT "#### netback grant fails\n"); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); + skb_shinfo(skb)->nr_frags = 0; kfree_skb(skb); - mop++; - pending_ring[MASK_PEND_IDX(pending_prod++)] = - pending_idx; continue; } - set_phys_to_machine( - __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT, - FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); - grant_tx_handle[pending_idx] = mop->handle; - data_len = (txreq.size > PKT_PROT_LEN) ? - PKT_PROT_LEN : txreq.size; - - __skb_put(skb, data_len); + data_len = skb->len; memcpy(skb->data, - (void *)(MMAP_VADDR(pending_idx)|txreq.offset), + (void *)(MMAP_VADDR(pending_idx)|txp->offset), data_len); - if (data_len < txreq.size) { + if (data_len < txp->size) { /* Append the packet payload as a fragment. */ - skb_shinfo(skb)->frags[0].page = - virt_to_page(MMAP_VADDR(pending_idx)); - skb_shinfo(skb)->frags[0].size = - txreq.size - data_len; - skb_shinfo(skb)->frags[0].page_offset = - txreq.offset + data_len; - skb_shinfo(skb)->nr_frags = 1; + txp->offset += data_len; + txp->size -= data_len; } else { /* Schedule a response immediately. */ netif_idx_release(pending_idx); } - skb->data_len = txreq.size - data_len; - skb->len += skb->data_len; - skb->truesize += skb->data_len; - - skb->dev = netif->dev; - skb->protocol = eth_type_trans(skb, skb->dev); - /* * Old frontends do not assert data_validated but we * can infer it from csum_blank so test both flags. */ - if (txreq.flags & (NETTXF_data_validated|NETTXF_csum_blank)) { + if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) { skb->ip_summed = CHECKSUM_UNNECESSARY; skb->proto_data_valid = 1; } else { skb->ip_summed = CHECKSUM_NONE; skb->proto_data_valid = 0; } - skb->proto_csum_blank = !!(txreq.flags & NETTXF_csum_blank); + skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank); - netif->stats.rx_bytes += txreq.size; + netbk_fill_frags(skb); + + skb->dev = netif->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + + netif->stats.rx_bytes += skb->len; netif->stats.rx_packets++; netif_rx(skb); netif->dev->last_rx = jiffies; - - mop++; } } diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 334433c548..ffa4923706 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -69,6 +69,8 @@ static int netback_remove(struct xenbus_device *dev) static int netback_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { + const char *message; + xenbus_transaction_t xbt; int err; struct backend_info *be = kzalloc(sizeof(struct backend_info), GFP_KERNEL); @@ -86,6 +88,27 @@ static int netback_probe(struct xenbus_device *dev, if (err) goto fail; + do { + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + goto fail; + } + + err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); + if (err) { + message = "writing feature-sg"; + goto abort_transaction; + } + + err = xenbus_transaction_end(xbt, 0); + } while (err == -EAGAIN); + + if (err) { + xenbus_dev_fatal(dev, err, "completing transaction"); + goto fail; + } + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) { goto fail; @@ -93,6 +116,9 @@ static int netback_probe(struct xenbus_device *dev, return 0; +abort_transaction: + xenbus_transaction_end(xbt, 1); + xenbus_dev_fatal(dev, err, "%s", message); fail: DPRINTK("failed"); netback_remove(dev); diff --git a/xen/include/public/io/netif.h b/xen/include/public/io/netif.h index f728726840..eac6149423 100644 --- a/xen/include/public/io/netif.h +++ b/xen/include/public/io/netif.h @@ -27,6 +27,10 @@ #define _NETTXF_data_validated (1) #define NETTXF_data_validated (1U<<_NETTXF_data_validated) +/* Packet continues in the request. */ +#define _NETTXF_more_data (2) +#define NETTXF_more_data (1U<<_NETTXF_more_data) + struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ uint16_t offset; /* Offset within buffer page */ diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h index d9aac23785..65619e52d3 100644 --- a/xen/include/public/io/ring.h +++ b/xen/include/public/io/ring.h @@ -159,11 +159,15 @@ typedef struct __name##_back_ring __name##_back_ring_t /* Test if there are outstanding messages to be processed on a ring. */ #define RING_HAS_UNCONSUMED_RESPONSES(_r) \ - ((_r)->rsp_cons != (_r)->sring->rsp_prod) + ((_r)->sring->rsp_prod - (_r)->rsp_cons) #define RING_HAS_UNCONSUMED_REQUESTS(_r) \ - (((_r)->req_cons != (_r)->sring->req_prod) && \ - (((_r)->req_cons - (_r)->rsp_prod_pvt) != RING_SIZE(_r))) + ({ \ + unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \ + unsigned int rsp = RING_SIZE(_r) - \ + ((_r)->req_cons - (_r)->rsp_prod_pvt); \ + req < rsp ? req : rsp; \ + }) /* Direct access to individual ring elements, by index. */ #define RING_GET_REQUEST(_r, _idx) \ From 8267025532ab65a497476426f1caec8391f607bd Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 16:33:49 +0100 Subject: [PATCH 31/38] [NET] front: Transmit SG packets if supported This patch adds scatter-and-gather transmission support to the frontend. This allows the MTU to be raised right now and the potential for TSO in future. Signed-off-by: Herbert Xu --- .../drivers/xen/netfront/netfront.c | 169 +++++++++++++++--- xen/include/public/io/ring.h | 6 +- 2 files changed, 146 insertions(+), 29 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index e0d4b6a764..7d56adede9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,11 @@ static void xennet_sysfs_delif(struct net_device *netdev); #define xennet_sysfs_delif(dev) do { } while(0) #endif +static inline int xennet_can_sg(struct net_device *dev) +{ + return dev->features & NETIF_F_SG; +} + /** * Entry point to this code when a new device is created. Allocate the basic * structures and the ring buffers for communication with the backend, and @@ -307,8 +313,6 @@ again: goto destroy_ring; } - xenbus_switch_state(dev, XenbusStateConnected); - return 0; abort_transaction: @@ -370,12 +374,9 @@ static int setup_device(struct xenbus_device *dev, struct netfront_info *info) goto fail; memcpy(netdev->dev_addr, info->mac, ETH_ALEN); - network_connect(netdev); info->irq = bind_evtchn_to_irqhandler( info->evtchn, netif_int, SA_SAMPLE_RANDOM, netdev->name, netdev); - (void)send_fake_arp(netdev); - show_device(info); return 0; @@ -391,17 +392,26 @@ static int setup_device(struct xenbus_device *dev, struct netfront_info *info) static void backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { + struct netfront_info *np = dev->data; + struct net_device *netdev = np->netdev; + DPRINTK("\n"); switch (backend_state) { case XenbusStateInitialising: - case XenbusStateInitWait: case XenbusStateInitialised: case XenbusStateConnected: case XenbusStateUnknown: case XenbusStateClosed: break; + case XenbusStateInitWait: + network_connect(netdev); + xenbus_switch_state(dev, XenbusStateConnected); + (void)send_fake_arp(netdev); + show_device(np); + break; + case XenbusStateClosing: netfront_closing(dev); break; @@ -452,13 +462,17 @@ static int network_open(struct net_device *dev) return 0; } +static inline int netfront_tx_slot_available(struct netfront_info *np) +{ + return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1; +} + static inline void network_maybe_wake_tx(struct net_device *dev) { struct netfront_info *np = netdev_priv(dev); if (unlikely(netif_queue_stopped(dev)) && - !RING_FULL(&np->tx) && - !gnttab_empty_grant_references(&np->gref_tx_head) && + netfront_tx_slot_available(np) && likely(netif_running(dev))) netif_wake_queue(dev); } @@ -638,36 +652,95 @@ static void network_alloc_rx_buffers(struct net_device *dev) RING_PUSH_REQUESTS(&np->rx); } +static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + struct netif_tx_request *tx) +{ + struct netfront_info *np = netdev_priv(dev); + char *data = skb->data; + unsigned long mfn; + RING_IDX prod = np->tx.req_prod_pvt; + int frags = skb_shinfo(skb)->nr_frags; + unsigned int offset = offset_in_page(data); + unsigned int len = skb_headlen(skb); + unsigned int id; + grant_ref_t ref; + int i; + + while (len > PAGE_SIZE - offset) { + tx->size = PAGE_SIZE - offset; + tx->flags |= NETTXF_more_data; + len -= tx->size; + data += tx->size; + offset = 0; + + id = get_id_from_freelist(np->tx_skbs); + np->tx_skbs[id] = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = virt_to_mfn(data); + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = len; + tx->flags = 0; + } + + for (i = 0; i < frags; i++) { + skb_frag_t *frag = skb_shinfo(skb)->frags + i; + + tx->flags |= NETTXF_more_data; + + id = get_id_from_freelist(np->tx_skbs); + np->tx_skbs[id] = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(frag->page)); + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = frag->page_offset; + tx->size = frag->size; + tx->flags = 0; + } + + np->tx.req_prod_pvt = prod; +} static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned short id; struct netfront_info *np = netdev_priv(dev); struct netif_tx_request *tx; + char *data = skb->data; RING_IDX i; grant_ref_t ref; unsigned long mfn; int notify; + int frags = skb_shinfo(skb)->nr_frags; + unsigned int offset = offset_in_page(data); + unsigned int len = skb_headlen(skb); - if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= - PAGE_SIZE)) { - struct sk_buff *nskb; - nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC|__GFP_NOWARN); - if (unlikely(nskb == NULL)) - goto drop; - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - /* Copy only the header fields we use in this driver. */ - nskb->dev = skb->dev; - nskb->ip_summed = skb->ip_summed; - nskb->proto_data_valid = skb->proto_data_valid; - dev_kfree_skb(skb); - skb = nskb; + frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE; + if (unlikely(frags > MAX_SKB_FRAGS + 1)) { + printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", + frags); + dump_stack(); + goto drop; } spin_lock_irq(&np->tx_lock); - if (unlikely(!netif_carrier_ok(dev))) { + if (unlikely(!netif_carrier_ok(dev) || + (frags > 1 && !xennet_can_sg(dev)))) { spin_unlock_irq(&np->tx_lock); goto drop; } @@ -682,12 +755,12 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->id = id; ref = gnttab_claim_grant_reference(&np->gref_tx_head); BUG_ON((signed short)ref < 0); - mfn = virt_to_mfn(skb->data); + mfn = virt_to_mfn(data); gnttab_grant_foreign_access_ref( ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly); tx->gref = np->grant_tx_ref[id] = ref; - tx->offset = (unsigned long)skb->data & ~PAGE_MASK; - tx->size = skb->len; + tx->offset = offset; + tx->size = len; tx->flags = 0; if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ @@ -696,14 +769,17 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->flags |= NETTXF_data_validated; np->tx.req_prod_pvt = i + 1; + + xennet_make_frags(skb, dev, tx); + tx->size = skb->len; + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify); if (notify) notify_remote_via_irq(np->irq); network_tx_buf_gc(dev); - if (RING_FULL(&np->tx) || - gnttab_empty_grant_references(&np->gref_tx_head)) + if (!netfront_tx_slot_available(np)) netif_stop_queue(dev); spin_unlock_irq(&np->tx_lock); @@ -963,6 +1039,38 @@ static struct net_device_stats *network_get_stats(struct net_device *dev) return &np->stats; } +static int xennet_change_mtu(struct net_device *dev, int mtu) +{ + int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN; + + if (mtu > max) + return -EINVAL; + dev->mtu = mtu; + return 0; +} + +static int xennet_set_sg(struct net_device *dev, u32 data) +{ + if (data) { + struct netfront_info *np = netdev_priv(dev); + int val; + + if (xenbus_scanf(XBT_NULL, np->xbdev->otherend, "feature-sg", + "%d", &val) < 0) + val = 0; + if (!val) + return -ENOSYS; + } else if (dev->mtu > ETH_DATA_LEN) + dev->mtu = ETH_DATA_LEN; + + return ethtool_op_set_sg(dev, data); +} + +static void xennet_set_features(struct net_device *dev) +{ + xennet_set_sg(dev, 1); +} + static void network_connect(struct net_device *dev) { struct netfront_info *np; @@ -970,6 +1078,8 @@ static void network_connect(struct net_device *dev) struct netif_tx_request *tx; struct sk_buff *skb; + xennet_set_features(dev); + np = netdev_priv(dev); spin_lock_irq(&np->tx_lock); spin_lock(&np->rx_lock); @@ -1081,6 +1191,8 @@ static struct ethtool_ops network_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = xennet_set_sg, }; #ifdef CONFIG_SYSFS @@ -1297,6 +1409,7 @@ static struct net_device * __devinit create_netdev(int handle, netdev->poll = netif_poll; netdev->set_multicast_list = network_set_multicast_list; netdev->uninit = netif_uninit; + netdev->change_mtu = xennet_change_mtu; netdev->weight = 64; netdev->features = NETIF_F_IP_CSUM; diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h index 65619e52d3..3723ef359d 100644 --- a/xen/include/public/io/ring.h +++ b/xen/include/public/io/ring.h @@ -151,11 +151,15 @@ typedef struct __name##_back_ring __name##_back_ring_t #define RING_SIZE(_r) \ ((_r)->nr_ents) +/* Number of free requests (for use on front side only). */ +#define RING_FREE_REQUESTS(_r) \ + (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons)) + /* Test if there is an empty slot available on the front ring. * (This is only meaningful from the front. ) */ #define RING_FULL(_r) \ - (((_r)->req_prod_pvt - (_r)->rsp_cons) == RING_SIZE(_r)) + (RING_FREE_REQUESTS(_r) == 0) /* Test if there are outstanding messages to be processed on a ring. */ #define RING_HAS_UNCONSUMED_RESPONSES(_r) \ From 42d838e49b9d7ed27ce5b4ef48e8d921cd0726fc Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 17:03:19 +0100 Subject: [PATCH 32/38] [NET] back: Add a few comments to the goriest parts of the scatter-gather patch. Signed-off-by: Keir Fraser --- .../drivers/xen/netback/netback.c | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index ca712d2a61..828b771d29 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -543,17 +543,14 @@ static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif, skb_frag_t *frags = shinfo->frags; netif_tx_request_t *txp; unsigned long pending_idx = *((u16 *)skb->data); - int nr_frags = shinfo->nr_frags; RING_IDX cons = netif->tx.req_cons + 1; - int i; + int i, start; - if ((unsigned long)shinfo->frags[0].page == pending_idx) { - frags++; - nr_frags--; - } + /* Skip first skb fragment if it is on same page as header fragment. */ + start = ((unsigned long)shinfo->frags[0].page == pending_idx); - for (i = 0; i < nr_frags; i++) { - txp = RING_GET_REQUEST(&netif->tx, cons + i); + for (i = start; i < shinfo->nr_frags; i++) { + txp = RING_GET_REQUEST(&netif->tx, cons++); pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)]; gnttab_set_map_op(mop++, MMAP_VADDR(pending_idx), @@ -578,10 +575,9 @@ static int netbk_tx_check_mop(struct sk_buff *skb, netif_tx_request_t *txp; struct skb_shared_info *shinfo = skb_shinfo(skb); int nr_frags = shinfo->nr_frags; - int start; - int err; - int i; + int i, err, start; + /* Check status of header. */ err = mop->status; if (unlikely(err)) { txp = &pending_tx_info[pending_idx].req; @@ -595,44 +591,47 @@ static int netbk_tx_check_mop(struct sk_buff *skb, grant_tx_handle[pending_idx] = mop->handle; } - start = 0; - if ((unsigned long)shinfo->frags[0].page == pending_idx) - start++; + /* Skip first skb fragment if it is on same page as header fragment. */ + start = ((unsigned long)shinfo->frags[0].page == pending_idx); for (i = start; i < nr_frags; i++) { - int newerr; - int j; + int j, newerr; pending_idx = (unsigned long)shinfo->frags[i].page; + /* Check error status: if okay then remember grant handle. */ newerr = (++mop)->status; if (likely(!newerr)) { set_phys_to_machine( - __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT, - FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); + __pa(MMAP_VADDR(pending_idx))>>PAGE_SHIFT, + FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT)); grant_tx_handle[pending_idx] = mop->handle; - + /* Had a previous error? Invalidate this fragment. */ if (unlikely(err)) netif_idx_release(pending_idx); continue; } + /* Error on this fragment: respond to client with an error. */ txp = &pending_tx_info[pending_idx].req; make_tx_response(netif, txp->id, NETIF_RSP_ERROR); pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; netif_put(netif); + /* Not the first error? Preceding frags already invalidated. */ if (err) continue; + /* First error: invalidate header and preceding fragments. */ pending_idx = *((u16 *)skb->data); netif_idx_release(pending_idx); - for (j = start; j < i; j++) { pending_idx = (unsigned long)shinfo->frags[i].page; netif_idx_release(pending_idx); } - err |= newerr; + + /* Remember the error: invalidate all subsequent fragments. */ + err = newerr; } *mopp = mop + 1; From ff476d8ed1e0a5742efea9bde70ea0b8c4db157e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 5 Jun 2006 17:17:27 +0100 Subject: [PATCH 33/38] [HVM][VMX] Interrupts must be kept disabled when entering Xen for external interrupt processing. Remove code that immediately reenabled interrupt delivery on VMEXIT. Signed-off-by: Seteven Smith Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vmx/vmx.c | 22 +++++---- xen/arch/x86/hvm/vmx/x86_32/exits.S | 35 +++++++------- xen/arch/x86/hvm/vmx/x86_64/exits.S | 71 ++++++++++++++--------------- 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 07ef936ba7..de0fb2b444 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1970,7 +1970,6 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs) __hvm_bug(regs); vector &= INTR_INFO_VECTOR_MASK; - local_irq_disable(); TRACE_VMEXIT(1,vector); switch(vector) { @@ -2065,30 +2064,33 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) struct vcpu *v = current; int error; - if ((error = __vmread(VM_EXIT_REASON, &exit_reason))) - __hvm_bug(®s); + error = __vmread(VM_EXIT_REASON, &exit_reason); + BUG_ON(error); perfc_incra(vmexits, exit_reason); - /* don't bother H/W interrutps */ - if (exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT && - exit_reason != EXIT_REASON_VMCALL && - exit_reason != EXIT_REASON_IO_INSTRUCTION) + if ( (exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT) && + (exit_reason != EXIT_REASON_VMCALL) && + (exit_reason != EXIT_REASON_IO_INSTRUCTION) ) HVM_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason); - if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) { + if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT ) + local_irq_enable(); + + if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) + { printk("Failed vm entry (reason 0x%x)\n", exit_reason); printk("*********** VMCS Area **************\n"); vmcs_dump_vcpu(); printk("**************************************\n"); domain_crash_synchronous(); - return; } __vmread(GUEST_RIP, &eip); TRACE_VMEXIT(0,exit_reason); - switch (exit_reason) { + switch ( exit_reason ) + { case EXIT_REASON_EXCEPTION_NMI: { /* diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S index 28a10807cb..cb20f1280d 100644 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S @@ -55,29 +55,26 @@ * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers. */ -#define HVM_MONITOR_EFLAGS 0x202 /* IF on */ #define NR_SKIPPED_REGS 6 /* See the above explanation */ -#define HVM_SAVE_ALL_NOSEGREGS \ - pushl $HVM_MONITOR_EFLAGS; \ - popf; \ - subl $(NR_SKIPPED_REGS*4), %esp; \ +#define HVM_SAVE_ALL_NOSEGREGS \ + subl $(NR_SKIPPED_REGS*4), %esp; \ movl $0, 0xc(%esp); /* XXX why do we need to force eflags==0 ?? */ \ - pushl %eax; \ - pushl %ebp; \ - pushl %edi; \ - pushl %esi; \ - pushl %edx; \ - pushl %ecx; \ + pushl %eax; \ + pushl %ebp; \ + pushl %edi; \ + pushl %esi; \ + pushl %edx; \ + pushl %ecx; \ pushl %ebx; -#define HVM_RESTORE_ALL_NOSEGREGS \ - popl %ebx; \ - popl %ecx; \ - popl %edx; \ - popl %esi; \ - popl %edi; \ - popl %ebp; \ - popl %eax; \ +#define HVM_RESTORE_ALL_NOSEGREGS \ + popl %ebx; \ + popl %ecx; \ + popl %edx; \ + popl %esi; \ + popl %edi; \ + popl %ebp; \ + popl %eax; \ addl $(NR_SKIPPED_REGS*4), %esp ALIGN diff --git a/xen/arch/x86/hvm/vmx/x86_64/exits.S b/xen/arch/x86/hvm/vmx/x86_64/exits.S index 8bea8654b4..d6b5904fb4 100644 --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S @@ -51,45 +51,42 @@ * (2/1) u32 entry_vector; * (1/1) u32 error_code; */ -#define HVM_MONITOR_RFLAGS 0x202 /* IF on */ #define NR_SKIPPED_REGS 6 /* See the above explanation */ -#define HVM_SAVE_ALL_NOSEGREGS \ - pushq $HVM_MONITOR_RFLAGS; \ - popfq; \ - subq $(NR_SKIPPED_REGS*8), %rsp; \ - pushq %rdi; \ - pushq %rsi; \ - pushq %rdx; \ - pushq %rcx; \ - pushq %rax; \ - pushq %r8; \ - pushq %r9; \ - pushq %r10; \ - pushq %r11; \ - pushq %rbx; \ - pushq %rbp; \ - pushq %r12; \ - pushq %r13; \ - pushq %r14; \ - pushq %r15; \ +#define HVM_SAVE_ALL_NOSEGREGS \ + subq $(NR_SKIPPED_REGS*8), %rsp; \ + pushq %rdi; \ + pushq %rsi; \ + pushq %rdx; \ + pushq %rcx; \ + pushq %rax; \ + pushq %r8; \ + pushq %r9; \ + pushq %r10; \ + pushq %r11; \ + pushq %rbx; \ + pushq %rbp; \ + pushq %r12; \ + pushq %r13; \ + pushq %r14; \ + pushq %r15; -#define HVM_RESTORE_ALL_NOSEGREGS \ - popq %r15; \ - popq %r14; \ - popq %r13; \ - popq %r12; \ - popq %rbp; \ - popq %rbx; \ - popq %r11; \ - popq %r10; \ - popq %r9; \ - popq %r8; \ - popq %rax; \ - popq %rcx; \ - popq %rdx; \ - popq %rsi; \ - popq %rdi; \ - addq $(NR_SKIPPED_REGS*8), %rsp; \ +#define HVM_RESTORE_ALL_NOSEGREGS \ + popq %r15; \ + popq %r14; \ + popq %r13; \ + popq %r12; \ + popq %rbp; \ + popq %rbx; \ + popq %r11; \ + popq %r10; \ + popq %r9; \ + popq %r8; \ + popq %rax; \ + popq %rcx; \ + popq %rdx; \ + popq %rsi; \ + popq %rdi; \ + addq $(NR_SKIPPED_REGS*8), %rsp; ENTRY(vmx_asm_vmexit_handler) /* selectors are restored/saved by VMX */ From d82a7836f687b820d1fc0df8e78f67685adafc6f Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Tue, 6 Jun 2006 08:05:13 +0100 Subject: [PATCH 34/38] [X86EMUL] Mark MOV instruction as not needing writeback. Fix the test harness for x86/64 -- map emulated addresses to low 4GB of address space. Signed-off-by: Keir Fraser --- tools/tests/test_x86_emulator.c | 103 ++++++++++++++++++++------------ xen/arch/x86/x86_emulate.c | 4 +- 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c index 5fef349fab..11755c3373 100644 --- a/tools/tests/test_x86_emulator.c +++ b/tools/tests/test_x86_emulator.c @@ -13,6 +13,7 @@ typedef int32_t s32; typedef int64_t s64; #include #include +#include static int read_any( unsigned long addr, @@ -85,23 +86,30 @@ int main(int argc, char **argv) struct x86_emulate_ctxt ctxt; struct cpu_user_regs regs; char instr[20] = { 0x01, 0x08 }; /* add %ecx,(%eax) */ - unsigned int res = 0x7FFFFFFF; - u32 cmpxchg8b_res[2] = { 0x12345678, 0x87654321 }; + unsigned int *res; int rc; ctxt.regs = ®s; ctxt.mode = X86EMUL_MODE_PROT32; + res = mmap((void *)0x100000, 0x1000, PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + if ( res == MAP_FAILED ) + { + fprintf(stderr, "mmap to low address failed\n"); + exit(1); + } + printf("%-40s", "Testing addl %%ecx,(%%eax)..."); instr[0] = 0x01; instr[1] = 0x08; regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)&res; - res = 0x7FFFFFFF; + ctxt.cr2 = (unsigned long)res; + *res = 0x7FFFFFFF; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x92345677) || + (*res != 0x92345677) || (regs.eflags != 0xa94) || (regs.eip != (unsigned long)&instr[2]) ) goto fail; @@ -116,25 +124,39 @@ int main(int argc, char **argv) #else regs.ecx = 0x12345678UL; #endif - ctxt.cr2 = (unsigned long)&res; + ctxt.cr2 = (unsigned long)res; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x92345677) || + (*res != 0x92345677) || (regs.ecx != 0x8000000FUL) || (regs.eip != (unsigned long)&instr[2]) ) goto fail; printf("okay\n"); + printf("%-40s", "Testing movl (%%eax),%%ecx..."); + instr[0] = 0x8b; instr[1] = 0x08; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.ecx = ~0UL; + ctxt.cr2 = (unsigned long)res; + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || + (*res != 0x92345677) || + (regs.ecx != 0x92345677UL) || + (regs.eip != (unsigned long)&instr[2]) ) + goto fail; + printf("okay\n"); + printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)..."); instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08; regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.eax = 0x92345677UL; regs.ecx = 0xAA; - ctxt.cr2 = (unsigned long)&res; + ctxt.cr2 = (unsigned long)res; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x923456AA) || + (*res != 0x923456AA) || (regs.eflags != 0x244) || (regs.eax != 0x92345677UL) || (regs.eip != (unsigned long)&instr[4]) ) @@ -147,10 +169,10 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.eax = 0xAABBCC77UL; regs.ecx = 0xFF; - ctxt.cr2 = (unsigned long)&res; + ctxt.cr2 = (unsigned long)res; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x923456AA) || + (*res != 0x923456AA) || ((regs.eflags&0x240) != 0x200) || (regs.eax != 0xAABBCCAA) || (regs.ecx != 0xFF) || @@ -163,10 +185,10 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)&res; + ctxt.cr2 = (unsigned long)res; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x12345678) || + (*res != 0x12345678) || (regs.eflags != 0x200) || (regs.ecx != 0x923456AA) || (regs.eip != (unsigned long)&instr[2]) ) @@ -176,14 +198,14 @@ int main(int argc, char **argv) printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%eax)..."); instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x08; regs.eflags = 0x200; - res = 0x923456AA; + *res = 0x923456AA; regs.eip = (unsigned long)&instr[0]; regs.eax = 0x923456AAUL; regs.ecx = 0xDDEEFF00L; - ctxt.cr2 = (unsigned long)&res; + ctxt.cr2 = (unsigned long)res; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0xDDEEFF00) || + (*res != 0xDDEEFF00) || (regs.eflags != 0x244) || (regs.eax != 0x923456AAUL) || (regs.eip != (unsigned long)&instr[4]) ) @@ -192,54 +214,57 @@ int main(int argc, char **argv) printf("%-40s", "Testing rep movsw..."); instr[0] = 0xf3; instr[1] = 0x66; instr[2] = 0xa5; - res = 0x22334455; + *res = 0x22334455; regs.eflags = 0x200; regs.ecx = 23; regs.eip = (unsigned long)&instr[0]; - regs.esi = (unsigned long)&res + 0; - regs.edi = (unsigned long)&res + 2; + regs.esi = (unsigned long)res + 0; + regs.edi = (unsigned long)res + 2; regs.error_code = 0; /* read fault */ ctxt.cr2 = regs.esi; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x44554455) || + (*res != 0x44554455) || (regs.eflags != 0x200) || (regs.ecx != 22) || - (regs.esi != ((unsigned long)&res + 2)) || - (regs.edi != ((unsigned long)&res + 4)) || + (regs.esi != ((unsigned long)res + 2)) || + (regs.edi != ((unsigned long)res + 4)) || (regs.eip != (unsigned long)&instr[0]) ) goto fail; printf("okay\n"); printf("%-40s", "Testing btrl $0x1,(%edi)..."); instr[0] = 0x0f; instr[1] = 0xba; instr[2] = 0x37; instr[3] = 0x01; - res = 0x2233445F; + *res = 0x2233445F; regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; - regs.edi = (unsigned long)&res; + regs.edi = (unsigned long)res; ctxt.cr2 = regs.edi; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x2233445D) || + (*res != 0x2233445D) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[4]) ) goto fail; printf("okay\n"); + res[0] = 0x12345678; + res[1] = 0x87654321; + printf("%-40s", "Testing cmpxchg8b (%edi) [succeeding]..."); instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f; regs.eflags = 0x200; - regs.eax = cmpxchg8b_res[0]; - regs.edx = cmpxchg8b_res[1]; + regs.eax = res[0]; + regs.edx = res[1]; regs.ebx = 0x9999AAAA; regs.ecx = 0xCCCCFFFF; regs.eip = (unsigned long)&instr[0]; - regs.edi = (unsigned long)cmpxchg8b_res; + regs.edi = (unsigned long)res; ctxt.cr2 = regs.edi; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (cmpxchg8b_res[0] != 0x9999AAAA) || - (cmpxchg8b_res[1] != 0xCCCCFFFF) || + (res[0] != 0x9999AAAA) || + (res[1] != 0xCCCCFFFF) || ((regs.eflags&0x240) != 0x240) || (regs.eip != (unsigned long)&instr[3]) ) goto fail; @@ -248,12 +273,12 @@ int main(int argc, char **argv) printf("%-40s", "Testing cmpxchg8b (%edi) [failing]..."); instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f; regs.eip = (unsigned long)&instr[0]; - regs.edi = (unsigned long)cmpxchg8b_res; + regs.edi = (unsigned long)res; ctxt.cr2 = regs.edi; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (cmpxchg8b_res[0] != 0x9999AAAA) || - (cmpxchg8b_res[1] != 0xCCCCFFFF) || + (res[0] != 0x9999AAAA) || + (res[1] != 0xCCCCFFFF) || (regs.eax != 0x9999AAAA) || (regs.edx != 0xCCCCFFFF) || ((regs.eflags&0x240) != 0x200) || @@ -265,11 +290,11 @@ int main(int argc, char **argv) instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)&res; - res = 0x82; + ctxt.cr2 = (unsigned long)res; + *res = 0x82; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x82) || + (*res != 0x82) || (regs.ecx != 0xFFFFFF82) || ((regs.eflags&0x240) != 0x200) || (regs.eip != (unsigned long)&instr[3]) ) @@ -280,11 +305,11 @@ int main(int argc, char **argv) instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)&res; - res = 0x1234aa82; + ctxt.cr2 = (unsigned long)res; + *res = 0x1234aa82; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || - (res != 0x1234aa82) || + (*res != 0x1234aa82) || (regs.ecx != 0xaa82) || ((regs.eflags&0x240) != 0x200) || (regs.eip != (unsigned long)&instr[3]) ) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index a33391f1a7..e48c911058 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -100,8 +100,8 @@ static uint8_t opcode_table[256] = { ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, /* 0x88 - 0x8F */ - ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, - ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, + ByteOp|DstMem|SrcReg|ModRM|Mov, DstMem|SrcReg|ModRM|Mov, + ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, 0, 0, 0, DstMem|SrcNone|ModRM|Mov, /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From 542ad2f200de2e7f94a74bbce59579b58d99c8b6 Mon Sep 17 00:00:00 2001 From: "kfraser@dhcp93.uk.xensource.com" Date: Tue, 6 Jun 2006 08:21:31 +0100 Subject: [PATCH 35/38] [NET] front: Turn grant-ref error into a fatal bug. That's the best we can do until we have a backend driver recovery method. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 7d56adede9..fec3a4ea4a 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -499,7 +499,7 @@ static void network_tx_buf_gc(struct net_device *dev) printk(KERN_ALERT "network_tx_buf_gc: warning " "-- grant still in use by backend " "domain.\n"); - break; /* bail immediately */ + BUG(); } gnttab_end_foreign_access_ref( np->grant_tx_ref[id], GNTMAP_readonly); From ab8096f27d7223c01fcf862118cd628b4a255c18 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 6 Jun 2006 09:48:17 +0100 Subject: [PATCH 36/38] Represent PFNs with their own type, rather than 'unsigned long'. ('long' changes size and alignment between 32- and 64-bit ABIs.) Signed-off-by: Hollis Blanchard --- .../drivers/xen/privcmd/privcmd.c | 2 +- .../include/xen/public/privcmd.h | 2 +- tools/debugger/libxendebug/xendebug.c | 2 +- tools/ioemu/hw/cirrus_vga.c | 12 +++--- tools/ioemu/vl.c | 15 +++---- tools/libxc/xc_core.c | 8 ++-- tools/libxc/xc_domain.c | 10 ++--- tools/libxc/xc_hvm_build.c | 6 +-- tools/libxc/xc_ia64_stubs.c | 12 +++--- tools/libxc/xc_linux.c | 2 +- tools/libxc/xc_linux_build.c | 21 +++++----- tools/libxc/xc_linux_restore.c | 14 +++---- tools/libxc/xc_linux_save.c | 26 ++++++------ tools/libxc/xc_load_aout9.c | 4 +- tools/libxc/xc_load_bin.c | 4 +- tools/libxc/xc_load_elf.c | 8 ++-- tools/libxc/xc_private.c | 40 ++++++++++--------- tools/libxc/xenctrl.h | 16 ++++---- tools/libxc/xg_private.h | 4 +- tools/libxc/xg_save_restore.h | 12 +++--- xen/common/memory.c | 20 ++++++---- xen/include/public/arch-ia64.h | 3 ++ xen/include/public/arch-x86_32.h | 5 ++- xen/include/public/arch-x86_64.h | 5 ++- xen/include/public/dom0_ops.h | 16 ++++---- xen/include/public/grant_table.h | 2 +- xen/include/public/memory.h | 10 ++--- xen/include/public/xen.h | 6 +-- 28 files changed, 153 insertions(+), 134 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index 9292c13a71..f41bb11b67 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -161,7 +161,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, case IOCTL_PRIVCMD_MMAPBATCH: { privcmd_mmapbatch_t m; struct vm_area_struct *vma = NULL; - unsigned long __user *p; + xen_pfn_t __user *p; unsigned long addr, mfn; int i; diff --git a/linux-2.6-xen-sparse/include/xen/public/privcmd.h b/linux-2.6-xen-sparse/include/xen/public/privcmd.h index 5e0bd7d817..df9650ca41 100644 --- a/linux-2.6-xen-sparse/include/xen/public/privcmd.h +++ b/linux-2.6-xen-sparse/include/xen/public/privcmd.h @@ -59,7 +59,7 @@ typedef struct privcmd_mmapbatch { int num; /* number of pages to populate */ domid_t dom; /* target domain */ unsigned long addr; /* virtual address */ - unsigned long __user *arr; /* array of mfns - top nibble set on err */ + xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */ } privcmd_mmapbatch_t; /* diff --git a/tools/debugger/libxendebug/xendebug.c b/tools/debugger/libxendebug/xendebug.c index 1a12848f5d..c5d6143b77 100644 --- a/tools/debugger/libxendebug/xendebug.c +++ b/tools/debugger/libxendebug/xendebug.c @@ -57,7 +57,7 @@ typedef struct domain_context /* local cache of domain state */ vcpu_guest_context_t context[MAX_VIRT_CPUS]; long total_pages; - unsigned long *page_array; + xen_pfn_t *page_array; unsigned long cr3_phys[MAX_VIRT_CPUS]; unsigned long *cr3_virt[MAX_VIRT_CPUS]; diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 689bbacf4d..503e23b763 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -2462,7 +2462,7 @@ static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { extern FILE *logfile; static void * set_vram_mapping(unsigned long begin, unsigned long end) { - unsigned long * extent_start = NULL; + xen_pfn_t *extent_start = NULL; unsigned long nr_extents; void *vram_pointer = NULL; int i; @@ -2473,14 +2473,14 @@ static void * set_vram_mapping(unsigned long begin, unsigned long end) end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; nr_extents = (end - begin) >> TARGET_PAGE_BITS; - extent_start = malloc(sizeof(unsigned long) * nr_extents ); + extent_start = malloc(sizeof(xen_pfn_t) * nr_extents ); if (extent_start == NULL) { fprintf(stderr, "Failed malloc on set_vram_mapping\n"); return NULL; } - memset(extent_start, 0, sizeof(unsigned long) * nr_extents); + memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents); for (i = 0; i < nr_extents; i++) { @@ -2508,7 +2508,7 @@ static void * set_vram_mapping(unsigned long begin, unsigned long end) static int unset_vram_mapping(unsigned long begin, unsigned long end) { - unsigned long * extent_start = NULL; + xen_pfn_t *extent_start = NULL; unsigned long nr_extents; int i; @@ -2519,7 +2519,7 @@ static int unset_vram_mapping(unsigned long begin, unsigned long end) end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; nr_extents = (end - begin) >> TARGET_PAGE_BITS; - extent_start = malloc(sizeof(unsigned long) * nr_extents ); + extent_start = malloc(sizeof(xen_pfn_t) * nr_extents ); if (extent_start == NULL) { @@ -2527,7 +2527,7 @@ static int unset_vram_mapping(unsigned long begin, unsigned long end) return -1; } - memset(extent_start, 0, sizeof(unsigned long) * nr_extents); + memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents); for (i = 0; i < nr_extents; i++) extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS; diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 2692ea5d80..0de9a4b18d 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2458,7 +2458,7 @@ int unset_mm_mapping(int xc_handle, uint32_t domid, unsigned long nr_pages, unsigned int address_bits, - unsigned long *extent_start) + xen_pfn_t *extent_start) { int err = 0; xc_dominfo_t info; @@ -2491,7 +2491,7 @@ int set_mm_mapping(int xc_handle, uint32_t domid, unsigned long nr_pages, unsigned int address_bits, - unsigned long *extent_start) + xen_pfn_t *extent_start) { xc_dominfo_t info; int err = 0; @@ -2557,7 +2557,8 @@ int main(int argc, char **argv) int serial_device_index; char qemu_dm_logfilename[64]; const char *loadvm = NULL; - unsigned long nr_pages, *page_array; + unsigned long nr_pages; + xen_pfn_t *page_array; extern void *shared_page; #if !defined(CONFIG_SOFTMMU) @@ -3023,8 +3024,8 @@ int main(int argc, char **argv) xc_handle = xc_interface_open(); - if ( (page_array = (unsigned long *) - malloc(nr_pages * sizeof(unsigned long))) == NULL) + if ( (page_array = (xen_pfn_t *) + malloc(nr_pages * sizeof(xen_pfn_t))) == NULL) { fprintf(logfile, "malloc returned error %d\n", errno); exit(-1); @@ -3079,8 +3080,8 @@ int main(int argc, char **argv) page_array[0]); #endif - fprintf(logfile, "shared page at pfn:%lx, mfn: %lx\n", (nr_pages-1), - (page_array[nr_pages - 1])); + fprintf(logfile, "shared page at pfn:%lx, mfn: %"PRIx64"\n", (nr_pages-1), + (uint64_t)(page_array[nr_pages - 1])); /* we always create the cdrom drive, even if no disk is there */ bdrv_init(); diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index c5ddeb37ec..ca2ad0bfb5 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -28,7 +28,7 @@ xc_domain_dumpcore_via_callback(int xc_handle, dumpcore_rtn_t dump_rtn) { unsigned long nr_pages; - unsigned long *page_array = NULL; + xen_pfn_t *page_array = NULL; xc_dominfo_t info; int i, nr_vcpus = 0; char *dump_mem, *dump_mem_start = NULL; @@ -70,7 +70,7 @@ xc_domain_dumpcore_via_callback(int xc_handle, sizeof(vcpu_guest_context_t)*nr_vcpus; dummy_len = (sizeof(struct xc_core_header) + (sizeof(vcpu_guest_context_t) * nr_vcpus) + - (nr_pages * sizeof(unsigned long))); + (nr_pages * sizeof(xen_pfn_t))); header.xch_pages_offset = round_pgup(dummy_len); sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header)); @@ -81,7 +81,7 @@ xc_domain_dumpcore_via_callback(int xc_handle, if ( sts != 0 ) goto error_out; - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) + if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) { printf("Could not allocate memory\n"); goto error_out; @@ -91,7 +91,7 @@ xc_domain_dumpcore_via_callback(int xc_handle, printf("Could not get the page frame list\n"); goto error_out; } - sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(unsigned long)); + sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(xen_pfn_t)); if ( sts != 0 ) goto error_out; diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 6d51b23bcb..da508f7435 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -291,7 +291,7 @@ int xc_domain_memory_increase_reservation(int xc_handle, unsigned long nr_extents, unsigned int extent_order, unsigned int address_bits, - unsigned long *extent_start) + xen_pfn_t *extent_start) { int err; struct xen_memory_reservation reservation = { @@ -324,7 +324,7 @@ int xc_domain_memory_decrease_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, unsigned int extent_order, - unsigned long *extent_start) + xen_pfn_t *extent_start) { int err; struct xen_memory_reservation reservation = { @@ -363,7 +363,7 @@ int xc_domain_memory_populate_physmap(int xc_handle, unsigned long nr_extents, unsigned int extent_order, unsigned int address_bits, - unsigned long *extent_start) + xen_pfn_t *extent_start) { int err; struct xen_memory_reservation reservation = { @@ -392,8 +392,8 @@ int xc_domain_memory_populate_physmap(int xc_handle, int xc_domain_translate_gpfn_list(int xc_handle, uint32_t domid, unsigned long nr_gpfns, - unsigned long *gpfn_list, - unsigned long *mfn_list) + xen_pfn_t *gpfn_list, + xen_pfn_t *mfn_list) { struct xen_translate_gpfn_list op = { .domid = domid, diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 135b0f0736..ac2749ccbd 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -135,7 +135,7 @@ static void set_hvm_info_checksum(struct hvm_info_table *t) * hvmloader will use this info to set BIOS accordingly */ static int set_hvm_info(int xc_handle, uint32_t dom, - unsigned long *pfn_list, unsigned int vcpus, + xen_pfn_t *pfn_list, unsigned int vcpus, unsigned int pae, unsigned int acpi, unsigned int apic) { char *va_map; @@ -178,7 +178,7 @@ static int setup_guest(int xc_handle, unsigned int store_evtchn, unsigned long *store_mfn) { - unsigned long *page_array = NULL; + xen_pfn_t *page_array = NULL; unsigned long count, i; unsigned long long ptr; xc_mmu_t *mmu = NULL; @@ -223,7 +223,7 @@ static int setup_guest(int xc_handle, goto error_out; } - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) + if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) { PERROR("Could not allocate memory.\n"); goto error_out; diff --git a/tools/libxc/xc_ia64_stubs.c b/tools/libxc/xc_ia64_stubs.c index 58d07477cc..abb3c1f44c 100644 --- a/tools/libxc/xc_ia64_stubs.c +++ b/tools/libxc/xc_ia64_stubs.c @@ -57,7 +57,7 @@ xc_plan9_build(int xc_handle, int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, - unsigned long *pfn_buf, + xen_pfn_t *pfn_buf, unsigned int start_page, unsigned int nr_pages) { @@ -65,7 +65,7 @@ int xc_ia64_get_pfn_list(int xc_handle, int num_pfns,ret; unsigned int __start_page, __nr_pages; unsigned long max_pfns; - unsigned long *__pfn_buf; + xen_pfn_t *__pfn_buf; __start_page = start_page; __nr_pages = nr_pages; @@ -80,7 +80,7 @@ int xc_ia64_get_pfn_list(int xc_handle, set_xen_guest_handle(op.u.getmemlist.buffer, __pfn_buf); if ( (max_pfns != -1UL) - && mlock(__pfn_buf, __nr_pages * sizeof(unsigned long)) != 0 ) + && mlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)) != 0 ) { PERROR("Could not lock pfn list buffer"); return -1; @@ -89,7 +89,7 @@ int xc_ia64_get_pfn_list(int xc_handle, ret = do_dom0_op(xc_handle, &op); if (max_pfns != -1UL) - (void)munlock(__pfn_buf, __nr_pages * sizeof(unsigned long)); + (void)munlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)); if (max_pfns == -1UL) return 0; @@ -122,10 +122,10 @@ int xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid, { // N.B. gva should be page aligned - unsigned long *page_array = NULL; + xen_pfn_t *page_array = NULL; int i; - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ){ + if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ){ PERROR("Could not allocate memory"); goto error_out; } diff --git a/tools/libxc/xc_linux.c b/tools/libxc/xc_linux.c index 4f7c78ad38..6c280a316d 100644 --- a/tools/libxc/xc_linux.c +++ b/tools/libxc/xc_linux.c @@ -28,7 +28,7 @@ int xc_interface_close(int xc_handle) } void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, - unsigned long *arr, int num) + xen_pfn_t *arr, int num) { privcmd_mmapbatch_t ioctlx; void *addr; diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 8dd7f4928c..40ae8fbd5e 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -10,6 +10,7 @@ #include "xc_aout9.h" #include #include +#include #include #if defined(__i386__) @@ -136,7 +137,7 @@ static int probeimageformat(const char *image, int load_initrd(int xc_handle, domid_t dom, struct initrd_info *initrd, unsigned long physbase, - unsigned long *phys_to_mach) + xen_pfn_t *phys_to_mach) { char page[PAGE_SIZE]; unsigned long pfn_start, pfn, nr_pages; @@ -189,7 +190,7 @@ static int setup_pg_tables(int xc_handle, uint32_t dom, vcpu_guest_context_t *ctxt, unsigned long dsi_v_start, unsigned long v_end, - unsigned long *page_array, + xen_pfn_t *page_array, unsigned long vpt_start, unsigned long vpt_end, unsigned shadow_mode_enabled) @@ -251,7 +252,7 @@ static int setup_pg_tables_pae(int xc_handle, uint32_t dom, vcpu_guest_context_t *ctxt, unsigned long dsi_v_start, unsigned long v_end, - unsigned long *page_array, + xen_pfn_t *page_array, unsigned long vpt_start, unsigned long vpt_end, unsigned shadow_mode_enabled, @@ -356,7 +357,7 @@ static int setup_pg_tables_64(int xc_handle, uint32_t dom, vcpu_guest_context_t *ctxt, unsigned long dsi_v_start, unsigned long v_end, - unsigned long *page_array, + xen_pfn_t *page_array, unsigned long vpt_start, unsigned long vpt_end, int shadow_mode_enabled) @@ -467,7 +468,7 @@ static int setup_guest(int xc_handle, unsigned int console_evtchn, unsigned long *console_mfn, uint32_t required_features[XENFEAT_NR_SUBMAPS]) { - unsigned long *page_array = NULL; + xen_pfn_t *page_array = NULL; struct load_funcs load_funcs; struct domain_setup_info dsi; unsigned long vinitrd_start; @@ -494,7 +495,7 @@ static int setup_guest(int xc_handle, start_page = dsi.v_start >> PAGE_SHIFT; pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT; - if ( (page_array = malloc(pgnr * sizeof(unsigned long))) == NULL ) + if ( (page_array = malloc(pgnr * sizeof(xen_pfn_t))) == NULL ) { PERROR("Could not allocate memory"); goto error_out; @@ -622,7 +623,7 @@ static int setup_guest(int xc_handle, unsigned int console_evtchn, unsigned long *console_mfn, uint32_t required_features[XENFEAT_NR_SUBMAPS]) { - unsigned long *page_array = NULL; + xen_pfn_t *page_array = NULL; unsigned long count, i, hypercall_pfn; start_info_t *start_info; shared_info_t *shared_info; @@ -633,7 +634,7 @@ static int setup_guest(int xc_handle, unsigned long nr_pt_pages; unsigned long physmap_pfn; - unsigned long *physmap, *physmap_e; + xen_pfn_t *physmap, *physmap_e; struct load_funcs load_funcs; struct domain_setup_info dsi; @@ -882,8 +883,8 @@ static int setup_guest(int xc_handle, ((uint64_t)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, count) ) { - fprintf(stderr,"m2p update failure p=%lx m=%lx\n", - count, page_array[count]); + fprintf(stderr,"m2p update failure p=%lx m=%"PRIx64"\n", + count, (uint64_t)page_array[count]); munmap(physmap, PAGE_SIZE); goto error_out; } diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 86f880bb13..c15282a376 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -25,10 +25,10 @@ static unsigned int pt_levels; static unsigned long max_pfn; /* Live mapping of the table mapping each PFN to its current MFN. */ -static unsigned long *live_p2m = NULL; +static xen_pfn_t *live_p2m = NULL; /* A table mapping each PFN to its new MFN. */ -static unsigned long *p2m = NULL; +static xen_pfn_t *p2m = NULL; static ssize_t @@ -126,7 +126,7 @@ int xc_linux_restore(int xc_handle, int io_fd, unsigned long *pfn_type = NULL; /* A table of MFNs to map in the current region */ - unsigned long *region_mfn = NULL; + xen_pfn_t *region_mfn = NULL; /* Types of the pfns in the current region */ unsigned long region_pfn_type[MAX_BATCH_SIZE]; @@ -135,7 +135,7 @@ int xc_linux_restore(int xc_handle, int io_fd, unsigned long *page = NULL; /* A copy of the pfn-to-mfn table frame list. */ - unsigned long *p2m_frame_list = NULL; + xen_pfn_t *p2m_frame_list = NULL; /* A temporary mapping of the guest's start_info page. */ start_info_t *start_info; @@ -241,9 +241,9 @@ int xc_linux_restore(int xc_handle, int io_fd, } /* We want zeroed memory so use calloc rather than malloc. */ - p2m = calloc(max_pfn, sizeof(unsigned long)); + p2m = calloc(max_pfn, sizeof(xen_pfn_t)); pfn_type = calloc(max_pfn, sizeof(unsigned long)); - region_mfn = calloc(MAX_BATCH_SIZE, sizeof(unsigned long)); + region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t)); if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) { ERR("memory alloc failed"); @@ -251,7 +251,7 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } - if (mlock(region_mfn, sizeof(unsigned long) * MAX_BATCH_SIZE)) { + if (mlock(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) { ERR("Could not mlock region_mfn"); goto out; } diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 8f110c2223..0a554ee272 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -40,10 +40,10 @@ static unsigned int pt_levels; static unsigned long max_pfn; /* Live mapping of the table mapping each PFN to its current MFN. */ -static unsigned long *live_p2m = NULL; +static xen_pfn_t *live_p2m = NULL; /* Live mapping of system MFN to PFN table. */ -static unsigned long *live_m2p = NULL; +static xen_pfn_t *live_m2p = NULL; /* grep fodder: machine_to_phys */ @@ -501,22 +501,22 @@ void canonicalize_pagetable(unsigned long type, unsigned long pfn, -static unsigned long *xc_map_m2p(int xc_handle, +static xen_pfn_t *xc_map_m2p(int xc_handle, unsigned long max_mfn, int prot) { struct xen_machphys_mfn_list xmml; privcmd_mmap_entry_t *entries; unsigned long m2p_chunks, m2p_size; - unsigned long *m2p; - unsigned long *extent_start; + xen_pfn_t *m2p; + xen_pfn_t *extent_start; int i, rc; m2p_size = M2P_SIZE(max_mfn); m2p_chunks = M2P_CHUNKS(max_mfn); xmml.max_extents = m2p_chunks; - if (!(extent_start = malloc(m2p_chunks * sizeof(unsigned long)))) { + if (!(extent_start = malloc(m2p_chunks * sizeof(xen_pfn_t)))) { ERR("failed to allocate space for m2p mfns"); return NULL; } @@ -583,11 +583,11 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, char page[PAGE_SIZE]; /* Double and single indirect references to the live P2M table */ - unsigned long *live_p2m_frame_list_list = NULL; - unsigned long *live_p2m_frame_list = NULL; + xen_pfn_t *live_p2m_frame_list_list = NULL; + xen_pfn_t *live_p2m_frame_list = NULL; /* A copy of the pfn-to-mfn table frame list. */ - unsigned long *p2m_frame_list = NULL; + xen_pfn_t *p2m_frame_list = NULL; /* Live mapping of shared info structure */ shared_info_t *live_shinfo = NULL; @@ -712,11 +712,11 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE); /* Canonicalise the pfn-to-mfn table frame-number list. */ - for (i = 0; i < max_pfn; i += ulpp) { - if (!translate_mfn_to_pfn(&p2m_frame_list[i/ulpp])) { + for (i = 0; i < max_pfn; i += fpp) { + if (!translate_mfn_to_pfn(&p2m_frame_list[i/fpp])) { ERR("Frame# in pfn-to-mfn frame list is not in pseudophys"); - ERR("entry %d: p2m_frame_list[%ld] is 0x%lx", i, i/ulpp, - p2m_frame_list[i/ulpp]); + ERR("entry %d: p2m_frame_list[%ld] is 0x%"PRIx64, i, i/fpp, + (uint64_t)p2m_frame_list[i/fpp]); goto out; } } diff --git a/tools/libxc/xc_load_aout9.c b/tools/libxc/xc_load_aout9.c index 9601431059..23168d47ba 100644 --- a/tools/libxc/xc_load_aout9.c +++ b/tools/libxc/xc_load_aout9.c @@ -17,7 +17,7 @@ #define KOFFSET(_p) ((_p)&~KZERO) static int parseaout9image(const char *, unsigned long, struct domain_setup_info *); -static int loadaout9image(const char *, unsigned long, int, uint32_t, unsigned long *, struct domain_setup_info *); +static int loadaout9image(const char *, unsigned long, int, uint32_t, xen_pfn_t *, struct domain_setup_info *); static void copyout(int, uint32_t, unsigned long *, unsigned long, const char *, int); struct Exec *get_header(const char *, unsigned long, struct Exec *); @@ -79,7 +79,7 @@ loadaout9image( const char *image, unsigned long image_size, int xch, uint32_t dom, - unsigned long *parray, + xen_pfn_t *parray, struct domain_setup_info *dsi) { struct Exec ehdr; diff --git a/tools/libxc/xc_load_bin.c b/tools/libxc/xc_load_bin.c index 0cbbb0c84b..27fbc1130d 100644 --- a/tools/libxc/xc_load_bin.c +++ b/tools/libxc/xc_load_bin.c @@ -107,7 +107,7 @@ parsebinimage( static int loadbinimage( const char *image, unsigned long image_size, int xch, uint32_t dom, - unsigned long *parray, struct domain_setup_info *dsi); + xen_pfn_t *parray, struct domain_setup_info *dsi); int probe_bin(const char *image, unsigned long image_size, @@ -235,7 +235,7 @@ static int parsebinimage(const char *image, static int loadbinimage( const char *image, unsigned long image_size, int xch, uint32_t dom, - unsigned long *parray, struct domain_setup_info *dsi) + xen_pfn_t *parray, struct domain_setup_info *dsi) { unsigned long size; char *va; diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c index 422e7a4a8b..3cbb2499d9 100644 --- a/tools/libxc/xc_load_elf.c +++ b/tools/libxc/xc_load_elf.c @@ -16,10 +16,10 @@ parseelfimage( static int loadelfimage( const char *image, unsigned long image_size, int xch, uint32_t dom, - unsigned long *parray, struct domain_setup_info *dsi); + xen_pfn_t *parray, struct domain_setup_info *dsi); static int loadelfsymtab( - const char *image, int xch, uint32_t dom, unsigned long *parray, + const char *image, int xch, uint32_t dom, xen_pfn_t *parray, struct domain_setup_info *dsi); int probe_elf(const char *image, @@ -211,7 +211,7 @@ static int parseelfimage(const char *image, static int loadelfimage( const char *image, unsigned long elfsize, int xch, uint32_t dom, - unsigned long *parray, struct domain_setup_info *dsi) + xen_pfn_t *parray, struct domain_setup_info *dsi) { Elf_Ehdr *ehdr = (Elf_Ehdr *)image; Elf_Phdr *phdr; @@ -265,7 +265,7 @@ loadelfimage( static int loadelfsymtab( - const char *image, int xch, uint32_t dom, unsigned long *parray, + const char *image, int xch, uint32_t dom, xen_pfn_t *parray, struct domain_setup_info *dsi) { Elf_Ehdr *ehdr = (Elf_Ehdr *)image, *sym_ehdr; diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index f776d2ff0a..4b238e3a84 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -4,6 +4,7 @@ * Helper functions for the rest of the library. */ +#include #include "xc_private.h" /* NB: arr must be mlock'ed */ @@ -134,9 +135,9 @@ int xc_memory_op(int xc_handle, struct xen_memory_reservation *reservation = arg; struct xen_machphys_mfn_list *xmml = arg; struct xen_translate_gpfn_list *trans = arg; - unsigned long *extent_start; - unsigned long *gpfn_list; - unsigned long *mfn_list; + xen_pfn_t *extent_start; + xen_pfn_t *gpfn_list; + xen_pfn_t *mfn_list; long ret = -EINVAL; hypercall.op = __HYPERVISOR_memory_op; @@ -156,7 +157,7 @@ int xc_memory_op(int xc_handle, get_xen_guest_handle(extent_start, reservation->extent_start); if ( (extent_start != NULL) && (mlock(extent_start, - reservation->nr_extents * sizeof(unsigned long)) != 0) ) + reservation->nr_extents * sizeof(xen_pfn_t)) != 0) ) { PERROR("Could not mlock"); safe_munlock(reservation, sizeof(*reservation)); @@ -171,7 +172,7 @@ int xc_memory_op(int xc_handle, } get_xen_guest_handle(extent_start, xmml->extent_start); if ( mlock(extent_start, - xmml->max_extents * sizeof(unsigned long)) != 0 ) + xmml->max_extents * sizeof(xen_pfn_t)) != 0 ) { PERROR("Could not mlock"); safe_munlock(xmml, sizeof(*xmml)); @@ -192,17 +193,17 @@ int xc_memory_op(int xc_handle, goto out1; } get_xen_guest_handle(gpfn_list, trans->gpfn_list); - if ( mlock(gpfn_list, trans->nr_gpfns * sizeof(long)) != 0 ) + if ( mlock(gpfn_list, trans->nr_gpfns * sizeof(xen_pfn_t)) != 0 ) { PERROR("Could not mlock"); safe_munlock(trans, sizeof(*trans)); goto out1; } get_xen_guest_handle(mfn_list, trans->mfn_list); - if ( mlock(mfn_list, trans->nr_gpfns * sizeof(long)) != 0 ) + if ( mlock(mfn_list, trans->nr_gpfns * sizeof(xen_pfn_t)) != 0 ) { PERROR("Could not mlock"); - safe_munlock(gpfn_list, trans->nr_gpfns * sizeof(long)); + safe_munlock(gpfn_list, trans->nr_gpfns * sizeof(xen_pfn_t)); safe_munlock(trans, sizeof(*trans)); goto out1; } @@ -220,22 +221,22 @@ int xc_memory_op(int xc_handle, get_xen_guest_handle(extent_start, reservation->extent_start); if ( extent_start != NULL ) safe_munlock(extent_start, - reservation->nr_extents * sizeof(unsigned long)); + reservation->nr_extents * sizeof(xen_pfn_t)); break; case XENMEM_machphys_mfn_list: safe_munlock(xmml, sizeof(*xmml)); get_xen_guest_handle(extent_start, xmml->extent_start); safe_munlock(extent_start, - xmml->max_extents * sizeof(unsigned long)); + xmml->max_extents * sizeof(xen_pfn_t)); break; case XENMEM_add_to_physmap: safe_munlock(arg, sizeof(struct xen_add_to_physmap)); break; case XENMEM_translate_gpfn_list: get_xen_guest_handle(mfn_list, trans->mfn_list); - safe_munlock(mfn_list, trans->nr_gpfns * sizeof(long)); + safe_munlock(mfn_list, trans->nr_gpfns * sizeof(xen_pfn_t)); get_xen_guest_handle(gpfn_list, trans->gpfn_list); - safe_munlock(gpfn_list, trans->nr_gpfns * sizeof(long)); + safe_munlock(gpfn_list, trans->nr_gpfns * sizeof(xen_pfn_t)); safe_munlock(trans, sizeof(*trans)); break; } @@ -263,7 +264,7 @@ long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu ) int xc_get_pfn_list(int xc_handle, uint32_t domid, - unsigned long *pfn_buf, + xen_pfn_t *pfn_buf, unsigned long max_pfns) { DECLARE_DOM0_OP; @@ -274,10 +275,10 @@ int xc_get_pfn_list(int xc_handle, set_xen_guest_handle(op.u.getmemlist.buffer, pfn_buf); #ifdef VALGRIND - memset(pfn_buf, 0, max_pfns * sizeof(unsigned long)); + memset(pfn_buf, 0, max_pfns * sizeof(xen_pfn_t)); #endif - if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) + if ( mlock(pfn_buf, max_pfns * sizeof(xen_pfn_t)) != 0 ) { PERROR("xc_get_pfn_list: pfn_buf mlock failed"); return -1; @@ -285,7 +286,7 @@ int xc_get_pfn_list(int xc_handle, ret = do_dom0_op(xc_handle, &op); - safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long)); + safe_munlock(pfn_buf, max_pfns * sizeof(xen_pfn_t)); #if 0 #ifdef DEBUG @@ -364,7 +365,7 @@ unsigned long xc_get_filesz(int fd) } void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, - int xch, uint32_t dom, unsigned long *parray, + int xch, uint32_t dom, xen_pfn_t *parray, unsigned long vstart) { char *va; @@ -433,10 +434,11 @@ int xc_version(int xc_handle, int cmd, void *arg) unsigned long xc_make_page_below_4G( int xc_handle, uint32_t domid, unsigned long mfn) { - unsigned long new_mfn; + xen_pfn_t old_mfn = mfn; + xen_pfn_t new_mfn; if ( xc_domain_memory_decrease_reservation( - xc_handle, domid, 1, 0, &mfn) != 0 ) + xc_handle, domid, 1, 0, &old_mfn) != 0 ) { fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn); return 0; diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 2a1a86d7f5..bd380a5a02 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -415,26 +415,26 @@ int xc_domain_memory_increase_reservation(int xc_handle, unsigned long nr_extents, unsigned int extent_order, unsigned int address_bits, - unsigned long *extent_start); + xen_pfn_t *extent_start); int xc_domain_memory_decrease_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, unsigned int extent_order, - unsigned long *extent_start); + xen_pfn_t *extent_start); int xc_domain_memory_populate_physmap(int xc_handle, uint32_t domid, unsigned long nr_extents, unsigned int extent_order, unsigned int address_bits, - unsigned long *extent_start); + xen_pfn_t *extent_start); int xc_domain_translate_gpfn_list(int xc_handle, uint32_t domid, unsigned long nr_gpfns, - unsigned long *gpfn_list, - unsigned long *mfn_list); + xen_pfn_t *gpfn_list, + xen_pfn_t *mfn_list); int xc_domain_ioport_permission(int xc_handle, uint32_t domid, @@ -487,7 +487,7 @@ void *xc_map_foreign_range(int xc_handle, uint32_t dom, unsigned long mfn ); void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, - unsigned long *arr, int num ); + xen_pfn_t *arr, int num ); /** * Translates a virtual address in the context of a given domain and @@ -502,11 +502,11 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, int vcpu, unsigned long long virt); -int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf, +int xc_get_pfn_list(int xc_handle, uint32_t domid, xen_pfn_t *pfn_buf, unsigned long max_pfns); int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, - unsigned long *pfn_buf, + xen_pfn_t *pfn_buf, unsigned int start_page, unsigned int nr_pages); int xc_copy_to_domain_page(int xc_handle, uint32_t domid, diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index affd6a07df..3dbcf4f51b 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -173,7 +173,7 @@ typedef int (*parseimagefunc)(const char *image, unsigned long image_size, struct domain_setup_info *dsi); typedef int (*loadimagefunc)(const char *image, unsigned long image_size, int xch, - uint32_t dom, unsigned long *parray, + uint32_t dom, xen_pfn_t *parray, struct domain_setup_info *dsi); struct load_funcs @@ -201,7 +201,7 @@ int xc_copy_to_domain_page(int xc_handle, uint32_t domid, unsigned long xc_get_filesz(int fd); void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, - int xch, uint32_t dom, unsigned long *parray, + int xch, uint32_t dom, xen_pfn_t *parray, unsigned long vstart); int pin_table(int xc_handle, unsigned int type, unsigned long mfn, diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index 08a27e99de..e3fd1f2821 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -105,23 +105,23 @@ static int get_platform_info(int xc_handle, uint32_t dom, */ #define M2P_SHIFT L2_PAGETABLE_SHIFT_PAE #define M2P_CHUNK_SIZE (1 << M2P_SHIFT) -#define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(unsigned long)), M2P_SHIFT) +#define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(xen_pfn_t)), M2P_SHIFT) #define M2P_CHUNKS(_m) (M2P_SIZE((_m)) >> M2P_SHIFT) /* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */ -#define P2M_SIZE ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT) +#define P2M_SIZE ROUNDUP((max_pfn * sizeof(xen_pfn_t)), PAGE_SHIFT) -/* Number of unsigned longs in a page */ -#define ulpp (PAGE_SIZE/sizeof(unsigned long)) +/* Number of xen_pfn_t in a page */ +#define fpp (PAGE_SIZE/sizeof(xen_pfn_t)) /* Number of entries in the pfn_to_mfn_frame_list */ -#define P2M_FL_ENTRIES (((max_pfn)+ulpp-1)/ulpp) +#define P2M_FL_ENTRIES (((max_pfn)+fpp-1)/fpp) /* Size in bytes of the pfn_to_mfn_frame_list */ #define P2M_FL_SIZE ((P2M_FL_ENTRIES)*sizeof(unsigned long)) /* Number of entries in the pfn_to_mfn_frame_list_list */ -#define P2M_FLL_ENTRIES (((max_pfn)+(ulpp*ulpp)-1)/(ulpp*ulpp)) +#define P2M_FLL_ENTRIES (((max_pfn)+(fpp*fpp)-1)/(fpp*fpp)) /* Current guests allow 8MB 'slack' in their P2M */ #define NR_SLACK_ENTRIES ((8 * 1024 * 1024) / PAGE_SIZE) diff --git a/xen/common/memory.c b/xen/common/memory.c index d902f85ce9..197308ad3c 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -31,14 +31,15 @@ static long increase_reservation( struct domain *d, - XEN_GUEST_HANDLE(ulong) extent_list, + XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, int *preempted) { struct page_info *page; - unsigned long i, mfn; + unsigned long i; + xen_pfn_t mfn; if ( !guest_handle_is_null(extent_list) && !guest_handle_okay(extent_list, nr_extents) ) @@ -80,14 +81,16 @@ increase_reservation( static long populate_physmap( struct domain *d, - XEN_GUEST_HANDLE(ulong) extent_list, + XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, int *preempted) { struct page_info *page; - unsigned long i, j, gpfn, mfn; + unsigned long i, j; + xen_pfn_t gpfn; + xen_pfn_t mfn; if ( !guest_handle_okay(extent_list, nr_extents) ) return 0; @@ -177,13 +180,14 @@ guest_remove_page( static long decrease_reservation( struct domain *d, - XEN_GUEST_HANDLE(ulong) extent_list, + XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, int *preempted) { - unsigned long i, j, gmfn; + unsigned long i, j; + xen_pfn_t gmfn; if ( !guest_handle_okay(extent_list, nr_extents) ) return 0; @@ -214,7 +218,9 @@ translate_gpfn_list( XEN_GUEST_HANDLE(xen_translate_gpfn_list_t) uop, unsigned long *progress) { struct xen_translate_gpfn_list op; - unsigned long i, gpfn, mfn; + unsigned long i; + xen_pfn_t gpfn; + xen_pfn_t mfn; struct domain *d; if ( copy_from_guest(&op, uop, 1) ) diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index b7e5d2b662..68ded37513 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -26,6 +26,9 @@ DEFINE_XEN_GUEST_HANDLE(char); DEFINE_XEN_GUEST_HANDLE(int); DEFINE_XEN_GUEST_HANDLE(long); DEFINE_XEN_GUEST_HANDLE(void); + +typedef unsigned long xen_pfn_t; +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #endif /* Arch specific VIRQs definition */ diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index c5237ca5c8..bbfccec68b 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -28,6 +28,9 @@ DEFINE_XEN_GUEST_HANDLE(char); DEFINE_XEN_GUEST_HANDLE(int); DEFINE_XEN_GUEST_HANDLE(long); DEFINE_XEN_GUEST_HANDLE(void); + +typedef unsigned long xen_pfn_t; +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #endif /* @@ -177,7 +180,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ - unsigned long pfn_to_mfn_frame_list_list; + xen_pfn_t pfn_to_mfn_frame_list_list; unsigned long nmi_reason; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index bea67d4b0c..b267cda83d 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -28,6 +28,9 @@ DEFINE_XEN_GUEST_HANDLE(char); DEFINE_XEN_GUEST_HANDLE(int); DEFINE_XEN_GUEST_HANDLE(long); DEFINE_XEN_GUEST_HANDLE(void); + +typedef unsigned long xen_pfn_t; +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #endif /* @@ -250,7 +253,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ - unsigned long pfn_to_mfn_frame_list_list; + xen_pfn_t pfn_to_mfn_frame_list_list; unsigned long nmi_reason; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 4b321baff4..f55f702355 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -28,7 +28,7 @@ struct dom0_getmemlist { /* IN variables. */ domid_t domain; unsigned long max_pfns; - XEN_GUEST_HANDLE(ulong) buffer; + XEN_GUEST_HANDLE(xen_pfn_t) buffer; /* OUT variables. */ unsigned long num_pfns; }; @@ -98,7 +98,7 @@ struct dom0_getdomaininfo { uint32_t flags; unsigned long tot_pages; unsigned long max_pages; - unsigned long shared_info_frame; /* MFN of shared_info struct */ + xen_pfn_t shared_info_frame; /* MFN of shared_info struct */ uint64_t cpu_time; uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ @@ -162,7 +162,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_settime_t); struct dom0_getpageframeinfo { /* IN variables. */ - unsigned long mfn; /* Machine page frame number to query. */ + xen_pfn_t mfn; /* Machine page frame number to query. */ domid_t domain; /* To which domain does the frame belong? */ /* OUT variables. */ /* Is the page PINNED to a type? */ @@ -213,7 +213,7 @@ struct dom0_tbufcontrol { cpumap_t cpu_mask; uint32_t evt_mask; /* OUT variables */ - unsigned long buffer_mfn; + xen_pfn_t buffer_mfn; uint32_t size; }; typedef struct dom0_tbufcontrol dom0_tbufcontrol_t; @@ -313,7 +313,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_getpageframeinfo2_t); #define DOM0_ADD_MEMTYPE 31 struct dom0_add_memtype { /* IN variables. */ - unsigned long mfn; + xen_pfn_t mfn; unsigned long nr_mfns; uint32_t type; /* OUT variables. */ @@ -345,7 +345,7 @@ struct dom0_read_memtype { /* IN variables. */ uint32_t reg; /* OUT variables. */ - unsigned long mfn; + xen_pfn_t mfn; unsigned long nr_mfns; uint32_t type; }; @@ -499,7 +499,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_irq_permission_t); #define DOM0_IOMEM_PERMISSION 47 struct dom0_iomem_permission { domid_t domain; /* domain to be affected */ - unsigned long first_mfn; /* first page (physical page number) in range */ + xen_pfn_t first_mfn; /* first page (physical page number) in range */ unsigned long nr_mfns; /* number of pages in range (>0) */ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ }; @@ -509,7 +509,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_iomem_permission_t); #define DOM0_HYPERCALL_INIT 48 struct dom0_hypercall_init { domid_t domain; /* domain to be affected */ - unsigned long mfn; /* machine frame to be initialised */ + xen_pfn_t mfn; /* machine frame to be initialised */ }; typedef struct dom0_hypercall_init dom0_hypercall_init_t; DEFINE_XEN_GUEST_HANDLE(dom0_hypercall_init_t); diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h index 332830c962..00adf1ab80 100644 --- a/xen/include/public/grant_table.h +++ b/xen/include/public/grant_table.h @@ -240,7 +240,7 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t); #define GNTTABOP_transfer 4 struct gnttab_transfer { /* IN parameters. */ - unsigned long mfn; + xen_pfn_t mfn; domid_t domid; grant_ref_t ref; /* OUT parameters. */ diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index bd2e265a5a..102a20341b 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -29,7 +29,7 @@ struct xen_memory_reservation { * OUT: GMFN bases of extents that were allocated * (NB. This command also updates the mach_to_phys translation table) */ - XEN_GUEST_HANDLE(ulong) extent_start; + XEN_GUEST_HANDLE(xen_pfn_t) extent_start; /* Number of extents, and size/alignment of each (2^extent_order pages). */ unsigned long nr_extents; @@ -87,7 +87,7 @@ struct xen_machphys_mfn_list { * any large discontiguities in the machine address space, 2MB gaps in * the machphys table will be represented by an MFN base of zero. */ - XEN_GUEST_HANDLE(ulong) extent_start; + XEN_GUEST_HANDLE(xen_pfn_t) extent_start; /* * Number of extents written to the above array. This will be smaller @@ -117,7 +117,7 @@ struct xen_add_to_physmap { unsigned long idx; /* GPFN where the source mapping page should appear. */ - unsigned long gpfn; + xen_pfn_t gpfn; }; typedef struct xen_add_to_physmap xen_add_to_physmap_t; DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t); @@ -135,13 +135,13 @@ struct xen_translate_gpfn_list { unsigned long nr_gpfns; /* List of GPFNs to translate. */ - XEN_GUEST_HANDLE(ulong) gpfn_list; + XEN_GUEST_HANDLE(xen_pfn_t) gpfn_list; /* * Output list to contain MFN translations. May be the same as the input * list (in which case each input GPFN is overwritten with the output MFN). */ - XEN_GUEST_HANDLE(ulong) mfn_list; + XEN_GUEST_HANDLE(xen_pfn_t) mfn_list; }; typedef struct xen_translate_gpfn_list xen_translate_gpfn_list_t; DEFINE_XEN_GUEST_HANDLE(xen_translate_gpfn_list_t); diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 9cf5bdd2a5..72df4644b2 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -197,7 +197,7 @@ struct mmuext_op { unsigned int cmd; union { /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */ - unsigned long mfn; + xen_pfn_t mfn; /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ unsigned long linear_addr; } arg1; @@ -457,9 +457,9 @@ struct start_info { unsigned long nr_pages; /* Total pages allocated to this domain. */ unsigned long shared_info; /* MACHINE address of shared info struct. */ uint32_t flags; /* SIF_xxx flags. */ - unsigned long store_mfn; /* MACHINE page number of shared page. */ + xen_pfn_t store_mfn; /* MACHINE page number of shared page. */ uint32_t store_evtchn; /* Event channel for store communication. */ - unsigned long console_mfn; /* MACHINE address of console page. */ + xen_pfn_t console_mfn; /* MACHINE page number of console page. */ uint32_t console_evtchn; /* Event channel for console messages. */ /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */ unsigned long pt_base; /* VIRTUAL address of page directory. */ From d404680bc387721a3e45032b624c177e2bbedcf7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 6 Jun 2006 10:25:59 +0100 Subject: [PATCH 37/38] Use explicitly-sized types in the dom0_ops and privcmd structures. As discussed previously, the these operations are not performance-sensitive, so the additional cache footprint shouldn't be an issue. Signed-off-by: Hollis Blanchard --- .../drivers/xen/privcmd/privcmd.c | 12 +++---- .../include/xen/public/privcmd.h | 14 ++++---- xen/include/public/dom0_ops.h | 36 +++++++++---------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index f41bb11b67..824ae648a5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -61,11 +61,11 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, __asm__ __volatile__ ( "pushl %%ebx; pushl %%ecx; pushl %%edx; " "pushl %%esi; pushl %%edi; " - "movl 4(%%eax),%%ebx ;" - "movl 8(%%eax),%%ecx ;" - "movl 12(%%eax),%%edx ;" - "movl 16(%%eax),%%esi ;" - "movl 20(%%eax),%%edi ;" + "movl 8(%%eax),%%ebx ;" + "movl 16(%%eax),%%ecx ;" + "movl 24(%%eax),%%edx ;" + "movl 32(%%eax),%%esi ;" + "movl 40(%%eax),%%edi ;" "movl (%%eax),%%eax ;" "shll $5,%%eax ;" "addl $hypercall_page,%%eax ;" @@ -210,7 +210,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, batch_err: printk("batch_err ret=%d vma=%p addr=%lx " "num=%d arr=%p %lx-%lx\n", - ret, vma, m.addr, m.num, m.arr, + ret, vma, (unsigned long)m.addr, m.num, m.arr, vma ? vma->vm_start : 0, vma ? vma->vm_end : 0); break; } diff --git a/linux-2.6-xen-sparse/include/xen/public/privcmd.h b/linux-2.6-xen-sparse/include/xen/public/privcmd.h index df9650ca41..d1162eebb0 100644 --- a/linux-2.6-xen-sparse/include/xen/public/privcmd.h +++ b/linux-2.6-xen-sparse/include/xen/public/privcmd.h @@ -33,20 +33,22 @@ #ifndef __LINUX_PUBLIC_PRIVCMD_H__ #define __LINUX_PUBLIC_PRIVCMD_H__ +#include + #ifndef __user #define __user #endif typedef struct privcmd_hypercall { - unsigned long op; - unsigned long arg[5]; + __u64 op; + __u64 arg[5]; } privcmd_hypercall_t; typedef struct privcmd_mmap_entry { - unsigned long va; - unsigned long mfn; - unsigned long npages; + __u64 va; + __u64 mfn; + __u64 npages; } privcmd_mmap_entry_t; typedef struct privcmd_mmap { @@ -58,7 +60,7 @@ typedef struct privcmd_mmap { typedef struct privcmd_mmapbatch { int num; /* number of pages to populate */ domid_t dom; /* target domain */ - unsigned long addr; /* virtual address */ + __u64 addr; /* virtual address */ xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */ } privcmd_mmapbatch_t; diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index f55f702355..bf941a4147 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0x03000000 +#define DOM0_INTERFACE_VERSION 0x03000001 /************************************************************************/ @@ -27,10 +27,10 @@ struct dom0_getmemlist { /* IN variables. */ domid_t domain; - unsigned long max_pfns; + uint64_t max_pfns; XEN_GUEST_HANDLE(xen_pfn_t) buffer; /* OUT variables. */ - unsigned long num_pfns; + uint64_t num_pfns; }; typedef struct dom0_getmemlist dom0_getmemlist_t; DEFINE_XEN_GUEST_HANDLE(dom0_getmemlist_t); @@ -96,8 +96,8 @@ struct dom0_getdomaininfo { #define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */ #define DOMFLAGS_SHUTDOWNSHIFT 16 uint32_t flags; - unsigned long tot_pages; - unsigned long max_pages; + uint64_t tot_pages; + uint64_t max_pages; xen_pfn_t shared_info_frame; /* MFN of shared_info struct */ uint64_t cpu_time; uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ @@ -229,8 +229,8 @@ struct dom0_physinfo { uint32_t sockets_per_node; uint32_t nr_nodes; uint32_t cpu_khz; - unsigned long total_pages; - unsigned long free_pages; + uint64_t total_pages; + uint64_t free_pages; uint32_t hw_cap[8]; }; typedef struct dom0_physinfo dom0_physinfo_t; @@ -276,7 +276,7 @@ struct dom0_shadow_control { uint32_t op; XEN_GUEST_HANDLE(ulong) dirty_bitmap; /* IN/OUT variables. */ - unsigned long pages; /* size of buffer, updated with actual size */ + uint64_t pages; /* size of buffer, updated with actual size */ /* OUT variables. */ struct dom0_shadow_control_stats stats; }; @@ -286,8 +286,8 @@ DEFINE_XEN_GUEST_HANDLE(dom0_shadow_control_t); #define DOM0_SETDOMAINMAXMEM 28 struct dom0_setdomainmaxmem { /* IN variables. */ - domid_t domain; - unsigned long max_memkb; + domid_t domain; + uint64_t max_memkb; }; typedef struct dom0_setdomainmaxmem dom0_setdomainmaxmem_t; DEFINE_XEN_GUEST_HANDLE(dom0_setdomainmaxmem_t); @@ -295,8 +295,8 @@ DEFINE_XEN_GUEST_HANDLE(dom0_setdomainmaxmem_t); #define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */ struct dom0_getpageframeinfo2 { /* IN variables. */ - domid_t domain; - unsigned long num; + domid_t domain; + uint64_t num; /* IN/OUT variables. */ XEN_GUEST_HANDLE(ulong) array; }; @@ -314,11 +314,11 @@ DEFINE_XEN_GUEST_HANDLE(dom0_getpageframeinfo2_t); struct dom0_add_memtype { /* IN variables. */ xen_pfn_t mfn; - unsigned long nr_mfns; - uint32_t type; + uint64_t nr_mfns; + uint32_t type; /* OUT variables. */ - uint32_t handle; - uint32_t reg; + uint32_t handle; + uint32_t reg; }; typedef struct dom0_add_memtype dom0_add_memtype_t; DEFINE_XEN_GUEST_HANDLE(dom0_add_memtype_t); @@ -346,7 +346,7 @@ struct dom0_read_memtype { uint32_t reg; /* OUT variables. */ xen_pfn_t mfn; - unsigned long nr_mfns; + uint64_t nr_mfns; uint32_t type; }; typedef struct dom0_read_memtype dom0_read_memtype_t; @@ -500,7 +500,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_irq_permission_t); struct dom0_iomem_permission { domid_t domain; /* domain to be affected */ xen_pfn_t first_mfn; /* first page (physical page number) in range */ - unsigned long nr_mfns; /* number of pages in range (>0) */ + uint64_t nr_mfns; /* number of pages in range (>0) */ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ }; typedef struct dom0_iomem_permission dom0_iomem_permission_t; From fa50dd1a8e15ca1e7d8455afe02830598edcde69 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 7 Jun 2006 09:59:56 +0100 Subject: [PATCH 38/38] [HVMLOADER] Revert to uniprocessor MPS table in rombios. Advertising more CPUs than the guest is allocated hangs boot of Windows XP (selects wrong HAL). The correct fix here is to dynamically generate the MPS table (at least the CPU entries) from hvmloader binary. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/Makefile | 4 ++-- tools/firmware/rombios/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile index 86b67035b8..a91391c2bd 100644 --- a/tools/firmware/hvmloader/Makefile +++ b/tools/firmware/hvmloader/Makefile @@ -51,8 +51,8 @@ hvmloader: roms.h hvmloader.c acpi_madt.c $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp -roms.h: ../rombios/BIOS-bochs-8-processors ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin - sh ./mkhex rombios ../rombios/BIOS-bochs-8-processors > roms.h +roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin + sh ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h sh ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h sh ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h diff --git a/tools/firmware/rombios/Makefile b/tools/firmware/rombios/Makefile index 080e3de5fd..3f4200df25 100644 --- a/tools/firmware/rombios/Makefile +++ b/tools/firmware/rombios/Makefile @@ -1,7 +1,7 @@ -#BIOS_BUILDS = BIOS-bochs-latest +BIOS_BUILDS = BIOS-bochs-latest #BIOS_BUILDS += BIOS-bochs-2-processors #BIOS_BUILDS += BIOS-bochs-4-processors -BIOS_BUILDS += BIOS-bochs-8-processors +#BIOS_BUILDS += BIOS-bochs-8-processors .PHONY: all all: bios