mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.636 (3fc376f1OnDIvL1xiIhqzjKDbchujQ)
desc.h, traps.c, sched.h, event.h, schedule.c, memory.c: Fixes and cleanups.
This commit is contained in:
1 parent
12e76caadf
commit
ad5d9c688d
6 files changed
+154
-153
No files matched your search
+1
-2
@@ -821,8 +821,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
|
||||
else if ( (current->mm.ldt_ents != ents) ||
|
||||
(current->mm.ldt_base != ptr) )
|
||||
{
|
||||
if ( current->mm.ldt_ents != 0 )
|
||||
invalidate_shadow_ldt();
|
||||
invalidate_shadow_ldt();
|
||||
current->mm.ldt_base = ptr;
|
||||
current->mm.ldt_ents = ents;
|
||||
load_LDT(current);
|
||||
|
||||
+100
-128
@@ -43,7 +43,6 @@ static s32 ctx_allow = (s32)MILLISECS(5); /* context switch allowance */
|
||||
|
||||
typedef struct schedule_data_st
|
||||
{
|
||||
spinlock_t lock; /* lock for protecting this */
|
||||
struct list_head runqueue; /* runqueue */
|
||||
struct task_struct *curr; /* current task */
|
||||
struct task_struct *idle; /* idle task for this cpu */
|
||||
@@ -55,6 +54,8 @@ typedef struct schedule_data_st
|
||||
} __cacheline_aligned schedule_data_t;
|
||||
static schedule_data_t schedule_data[NR_CPUS];
|
||||
|
||||
spinlock_t schedule_lock[NR_CPUS] __cacheline_aligned;
|
||||
|
||||
/* Skanky periodic event to all guests. This must die in the next release! */
|
||||
static struct ac_timer v_timer;
|
||||
|
||||
@@ -128,8 +129,7 @@ void sched_add_domain(struct task_struct *p)
|
||||
|
||||
if ( p->domain == IDLE_DOMAIN_ID )
|
||||
{
|
||||
p->avt = 0xffffffff;
|
||||
p->evt = 0xffffffff;
|
||||
p->avt = p->evt = ~0U;
|
||||
schedule_data[p->processor].idle = p;
|
||||
}
|
||||
else
|
||||
@@ -159,29 +159,21 @@ void init_idle_task(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task_struct *p = current;
|
||||
spin_lock_irqsave(&schedule_data[p->processor].lock, flags);
|
||||
spin_lock_irqsave(&schedule_lock[p->processor], flags);
|
||||
p->has_cpu = 1;
|
||||
p->state = TASK_RUNNING;
|
||||
if ( !__task_on_runqueue(p) )
|
||||
__add_to_runqueue_head(p);
|
||||
spin_unlock_irqrestore(&schedule_data[p->processor].lock, flags);
|
||||
spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* wake up a domain which had been sleeping
|
||||
*/
|
||||
int wake_up(struct task_struct *p)
|
||||
void __wake_up(struct task_struct *p)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
ASSERT(p->state != TASK_DYING);
|
||||
|
||||
spin_lock_irqsave(&schedule_data[p->processor].lock, flags);
|
||||
|
||||
/* XXX RN: should we warp here? Might be a good idea to also boost a
|
||||
* domain which currently is unwarped and on run queue and
|
||||
* the receives an event. */
|
||||
if ( __task_on_runqueue(p) ) goto out;
|
||||
if ( unlikely(__task_on_runqueue(p)) )
|
||||
return;
|
||||
|
||||
p->state = TASK_RUNNING;
|
||||
__add_to_runqueue_head(p);
|
||||
@@ -198,16 +190,17 @@ int wake_up(struct task_struct *p)
|
||||
#ifdef SCHED_HISTO
|
||||
p->wokenup = NOW();
|
||||
#endif
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
spin_unlock_irqrestore(&schedule_data[p->processor].lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Voluntarily yield the processor to another domain, until an event occurs.
|
||||
*/
|
||||
void wake_up(struct task_struct *p)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&schedule_lock[p->processor], flags);
|
||||
__wake_up(p);
|
||||
spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
|
||||
}
|
||||
|
||||
/* Voluntarily yield the processor to another domain, until an event occurs. */
|
||||
long do_yield(void)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
@@ -216,9 +209,7 @@ long do_yield(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Demultiplex scheduler-related hypercalls.
|
||||
*/
|
||||
/* Demultiplex scheduler-related hypercalls. */
|
||||
long do_sched_op(unsigned long op)
|
||||
{
|
||||
long ret = 0;
|
||||
@@ -251,18 +242,14 @@ long do_sched_op(unsigned long op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Control the scheduler
|
||||
*/
|
||||
/* Control the scheduler. */
|
||||
long sched_bvtctl(unsigned long c_allow)
|
||||
{
|
||||
ctx_allow = c_allow;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust scheduling parameter for a given domain
|
||||
*/
|
||||
/* Adjust scheduling parameter for a given domain. */
|
||||
long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp,
|
||||
unsigned long warpl, unsigned long warpu)
|
||||
{
|
||||
@@ -276,9 +263,9 @@ long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp,
|
||||
if ( p == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
spin_lock_irq(&schedule_data[p->processor].lock);
|
||||
spin_lock_irq(&schedule_lock[p->processor]);
|
||||
p->mcu_advance = mcu_adv;
|
||||
spin_unlock_irq(&schedule_data[p->processor].lock);
|
||||
spin_unlock_irq(&schedule_lock[p->processor]);
|
||||
|
||||
put_task_struct(p);
|
||||
|
||||
@@ -293,18 +280,15 @@ long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp,
|
||||
* Otherwise we do a run through the scheduler after the current tasks
|
||||
* context switch allowance is over.
|
||||
*/
|
||||
void reschedule(struct task_struct *p)
|
||||
unsigned long __reschedule(struct task_struct *p)
|
||||
{
|
||||
int cpu = p->processor;
|
||||
struct task_struct *curr;
|
||||
unsigned long flags;
|
||||
s_time_t now, min_time;
|
||||
|
||||
if ( p->has_cpu )
|
||||
return;
|
||||
if ( unlikely(p->has_cpu || !__task_on_runqueue(p)) )
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&schedule_data[cpu].lock, flags);
|
||||
|
||||
now = NOW();
|
||||
curr = schedule_data[cpu].curr;
|
||||
/* domain should run at least for ctx_allow */
|
||||
@@ -312,23 +296,26 @@ void reschedule(struct task_struct *p)
|
||||
|
||||
if ( is_idle_task(curr) || (min_time <= now) )
|
||||
{
|
||||
/* reschedule */
|
||||
set_bit(_HYP_EVENT_NEED_RESCHED, &curr->hyp_events);
|
||||
|
||||
spin_unlock_irqrestore(&schedule_data[cpu].lock, flags);
|
||||
|
||||
if ( cpu != smp_processor_id() )
|
||||
smp_send_event_check_cpu(cpu);
|
||||
|
||||
return;
|
||||
return (1 << p->processor);
|
||||
}
|
||||
|
||||
/* current hasn't been running for long enough -> reprogram timer.
|
||||
* but don't bother if timer would go off soon anyway */
|
||||
if ( schedule_data[cpu].s_timer.expires > min_time + TIME_SLOP )
|
||||
mod_ac_timer(&schedule_data[cpu].s_timer, min_time);
|
||||
|
||||
spin_unlock_irqrestore(&schedule_data[cpu].lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void reschedule(struct task_struct *p)
|
||||
{
|
||||
unsigned long flags, cpu_mask;
|
||||
spin_lock_irqsave(&schedule_lock[p->processor], flags);
|
||||
cpu_mask = __reschedule(p);
|
||||
spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
|
||||
hyp_event_notify(cpu_mask);
|
||||
}
|
||||
|
||||
|
||||
@@ -341,9 +328,9 @@ void reschedule(struct task_struct *p)
|
||||
*/
|
||||
asmlinkage void __enter_scheduler(void)
|
||||
{
|
||||
struct task_struct *prev, *next, *next_prime, *p;
|
||||
struct task_struct *prev = current, *next = NULL, *next_prime, *p;
|
||||
struct list_head *tmp;
|
||||
int this_cpu;
|
||||
int this_cpu = prev->processor;
|
||||
s_time_t now;
|
||||
s32 r_time; /* time for new dom to run */
|
||||
s32 ranfor; /* assume we never run longer than 2.1s! */
|
||||
@@ -352,69 +339,41 @@ asmlinkage void __enter_scheduler(void)
|
||||
|
||||
perfc_incrc(sched_run);
|
||||
|
||||
prev = current;
|
||||
next = NULL;
|
||||
|
||||
this_cpu = prev->processor;
|
||||
|
||||
spin_lock_irq(&schedule_data[this_cpu].lock);
|
||||
spin_lock_irq(&schedule_lock[this_cpu]);
|
||||
|
||||
now = NOW();
|
||||
|
||||
/* remove timer, if still on list */
|
||||
rem_ac_timer(&schedule_data[this_cpu].s_timer);
|
||||
|
||||
/* deschedule the current domain */
|
||||
|
||||
ASSERT(!in_interrupt());
|
||||
ASSERT(__task_on_runqueue(prev));
|
||||
ASSERT(prev->state != TASK_UNINTERRUPTIBLE);
|
||||
|
||||
if ( is_idle_task(prev) )
|
||||
goto deschedule_done;
|
||||
|
||||
/* do some accounting */
|
||||
ranfor = (s32)(now - prev->lastschd);
|
||||
prev->cpu_time += ranfor;
|
||||
|
||||
/* calculate mcu and update avt */
|
||||
mcus = ranfor/MCU;
|
||||
if (ranfor % MCU) mcus ++; /* always round up */
|
||||
prev->avt += mcus * prev->mcu_advance;
|
||||
|
||||
/* recalculate evt */
|
||||
__calc_evt(prev);
|
||||
|
||||
/* dequeue */
|
||||
__del_from_runqueue(prev);
|
||||
|
||||
switch ( prev->state )
|
||||
if ( likely(!is_idle_task(prev)) )
|
||||
{
|
||||
case TASK_INTERRUPTIBLE:
|
||||
if ( signal_pending(prev) )
|
||||
ranfor = (s32)(now - prev->lastschd);
|
||||
prev->cpu_time += ranfor;
|
||||
|
||||
/* Calculate mcu and update avt. */
|
||||
mcus = (ranfor + MCU - 1) / MCU;
|
||||
prev->avt += mcus * prev->mcu_advance;
|
||||
|
||||
__calc_evt(prev);
|
||||
|
||||
__del_from_runqueue(prev);
|
||||
|
||||
if ( likely(prev->state == TASK_RUNNING) ||
|
||||
unlikely((prev->state == TASK_INTERRUPTIBLE) &&
|
||||
signal_pending(prev)) )
|
||||
{
|
||||
prev->state = TASK_RUNNING; /* but has events pending */
|
||||
break;
|
||||
prev->state = TASK_RUNNING;
|
||||
__add_to_runqueue_tail(prev);
|
||||
}
|
||||
case TASK_UNINTERRUPTIBLE:
|
||||
case TASK_DYING:
|
||||
case TASK_STOPPED:
|
||||
default:
|
||||
/* Done if not running. Else continue. */
|
||||
goto deschedule_done;
|
||||
case TASK_RUNNING:;
|
||||
}
|
||||
|
||||
/* requeue */
|
||||
__add_to_runqueue_tail(prev);
|
||||
|
||||
deschedule_done:
|
||||
clear_bit(_HYP_EVENT_NEED_RESCHED, &prev->hyp_events);
|
||||
|
||||
/*
|
||||
* Pick a new domain
|
||||
*/
|
||||
|
||||
/* we should at least have the idle task */
|
||||
/* We should at least have the idle task */
|
||||
ASSERT(!list_empty(&schedule_data[this_cpu].runqueue));
|
||||
|
||||
/*
|
||||
@@ -425,64 +384,76 @@ asmlinkage void __enter_scheduler(void)
|
||||
next = schedule_data[this_cpu].idle;
|
||||
next_prime = NULL;
|
||||
|
||||
next_evt = 0xffffffff;
|
||||
next_prime_evt = 0xffffffff;
|
||||
min_avt = 0xffffffff; /* to calculate svt */
|
||||
next_evt = ~0U;
|
||||
next_prime_evt = ~0U;
|
||||
min_avt = ~0U;
|
||||
|
||||
list_for_each(tmp, &schedule_data[this_cpu].runqueue) {
|
||||
list_for_each ( tmp, &schedule_data[this_cpu].runqueue )
|
||||
{
|
||||
p = list_entry(tmp, struct task_struct, run_list);
|
||||
if (p->evt < next_evt) {
|
||||
if ( p->evt < next_evt )
|
||||
{
|
||||
next_prime = next;
|
||||
next_prime_evt = next_evt;
|
||||
next = p;
|
||||
next_evt = p->evt;
|
||||
} else if (next_prime_evt == 0xffffffff) {
|
||||
}
|
||||
else if ( next_prime_evt == ~0U )
|
||||
{
|
||||
next_prime_evt = p->evt;
|
||||
next_prime = p;
|
||||
} else if (p->evt < next_prime_evt) {
|
||||
}
|
||||
else if ( p->evt < next_prime_evt )
|
||||
{
|
||||
next_prime_evt = p->evt;
|
||||
next_prime = p;
|
||||
}
|
||||
/* determine system virtual time */
|
||||
if (p->avt < min_avt)
|
||||
|
||||
/* Determine system virtual time. */
|
||||
if ( p->avt < min_avt )
|
||||
min_avt = p->avt;
|
||||
}
|
||||
ASSERT(next != NULL); /* we should have at least the idle task */
|
||||
|
||||
/* update system virtual time */
|
||||
if (min_avt != 0xffffffff) schedule_data[this_cpu].svt = min_avt;
|
||||
/* Update system virtual time. */
|
||||
if ( min_avt != ~0U )
|
||||
schedule_data[this_cpu].svt = min_avt;
|
||||
|
||||
/* check for virtual time overrun on this cpu */
|
||||
if (schedule_data[this_cpu].svt >= 0xf0000000) {
|
||||
if ( schedule_data[this_cpu].svt >= 0xf0000000 )
|
||||
{
|
||||
u_long t_flags;
|
||||
write_lock_irqsave(&tasklist_lock, t_flags);
|
||||
p = &idle0_task;
|
||||
do {
|
||||
if (p->processor == this_cpu && !is_idle_task(p)) {
|
||||
if ( (p->processor == this_cpu) && !is_idle_task(p) )
|
||||
{
|
||||
p->evt -= 0xe0000000;
|
||||
p->avt -= 0xe0000000;
|
||||
}
|
||||
} while ( (p = p->next_task) != &idle0_task );
|
||||
}
|
||||
while ( (p = p->next_task) != &idle0_task );
|
||||
write_unlock_irqrestore(&tasklist_lock, t_flags);
|
||||
schedule_data[this_cpu].svt -= 0xe0000000;
|
||||
}
|
||||
|
||||
/* work out time for next run through scheduler */
|
||||
if (is_idle_task(next)) {
|
||||
if ( is_idle_task(next) )
|
||||
{
|
||||
r_time = ctx_allow;
|
||||
goto sched_done;
|
||||
}
|
||||
|
||||
if (next_prime == NULL || is_idle_task(next_prime)) {
|
||||
/* we have only one runable task besides the idle task */
|
||||
if ( (next_prime == NULL) || is_idle_task(next_prime) )
|
||||
{
|
||||
/* We have only one runnable task besides the idle task. */
|
||||
r_time = 10 * ctx_allow; /* RN: random constant */
|
||||
goto sched_done;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we are here we have two runable tasks.
|
||||
* work out how long 'next' can run till its evt is greater than
|
||||
* 'next_prime's evt. Taking context switch allowance into account.
|
||||
* If we are here then we have two runnable tasks.
|
||||
* Work out how long 'next' can run till its evt is greater than
|
||||
* 'next_prime's evt. Take context switch allowance into account.
|
||||
*/
|
||||
ASSERT(next_prime->evt >= next->evt);
|
||||
r_time = ((next_prime->evt - next->evt)/next->mcu_advance) + ctx_allow;
|
||||
@@ -491,7 +462,8 @@ asmlinkage void __enter_scheduler(void)
|
||||
ASSERT(r_time >= ctx_allow);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (r_time < ctx_allow) {
|
||||
if ( r_time < ctx_allow )
|
||||
{
|
||||
printk("[%02d]: %lx\n", this_cpu, (unsigned long)r_time);
|
||||
dump_rqueue(&schedule_data[this_cpu].runqueue, "foo");
|
||||
}
|
||||
@@ -508,7 +480,7 @@ asmlinkage void __enter_scheduler(void)
|
||||
schedule_data[this_cpu].s_timer.expires = now + r_time;
|
||||
add_ac_timer(&schedule_data[this_cpu].s_timer);
|
||||
|
||||
spin_unlock_irq(&schedule_data[this_cpu].lock);
|
||||
spin_unlock_irq(&schedule_lock[this_cpu]);
|
||||
|
||||
/* done, switch tasks */
|
||||
if ( unlikely(prev == next) )
|
||||
@@ -610,7 +582,7 @@ void __init scheduler_init(void)
|
||||
for ( i = 0; i < NR_CPUS; i++ )
|
||||
{
|
||||
INIT_LIST_HEAD(&schedule_data[i].runqueue);
|
||||
spin_lock_init(&schedule_data[i].lock);
|
||||
spin_lock_init(&schedule_lock[i]);
|
||||
schedule_data[i].curr = &idle0_task;
|
||||
|
||||
init_ac_timer(&schedule_data[i].s_timer);
|
||||
@@ -688,10 +660,10 @@ void dump_runq(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
printk("BVT: mcu=0x%08Xns ctx_allow=0x%08Xns NOW=0x%08X%08X\n",
|
||||
(u32)MCU, (u32)ctx_allow, (u32)(now>>32), (u32)now);
|
||||
for (i = 0; i < smp_num_cpus; i++) {
|
||||
spin_lock_irqsave(&schedule_data[i].lock, flags);
|
||||
spin_lock_irqsave(&schedule_lock[i], flags);
|
||||
printk("CPU[%02d] svt=0x%08X ", i, (s32)schedule_data[i].svt);
|
||||
dump_rqueue(&schedule_data[i].runqueue, "rq");
|
||||
spin_unlock_irqrestore(&schedule_data[i].lock, flags);
|
||||
spin_unlock_irqrestore(&schedule_lock[i], flags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
+23
-15
@@ -28,31 +28,39 @@
|
||||
*/
|
||||
static inline unsigned long mark_guest_event(struct task_struct *p, int event)
|
||||
{
|
||||
unsigned long flags, cpu_mask;
|
||||
|
||||
if ( test_and_set_bit(event, &p->shared_info->events) )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* No need for the runqueue_lock! The check below does not race
|
||||
* with the setting of has_cpu, because that is set with runqueue_lock
|
||||
* held. The lock must be released before hypervisor exit (and so
|
||||
* a write barrier executed). And, just before hypervisor exit,
|
||||
* outstanding events are checked. So bit is certainly set early enough.
|
||||
*/
|
||||
smp_mb();
|
||||
if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
|
||||
reschedule(p);
|
||||
return p->has_cpu ? (1 << p->processor) : 0;
|
||||
spin_lock_irqsave(&schedule_lock[p->processor], flags);
|
||||
if ( p->state == TASK_INTERRUPTIBLE )
|
||||
__wake_up(p);
|
||||
cpu_mask = __reschedule(p);
|
||||
if ( p->has_cpu )
|
||||
cpu_mask |= 1 << p->processor;
|
||||
spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
|
||||
|
||||
return cpu_mask;
|
||||
}
|
||||
|
||||
/* As above, but hyp_events are handled within the hypervisor. */
|
||||
static inline unsigned long mark_hyp_event(struct task_struct *p, int event)
|
||||
{
|
||||
unsigned long flags, cpu_mask;
|
||||
|
||||
if ( test_and_set_bit(event, &p->hyp_events) )
|
||||
return 0;
|
||||
smp_mb();
|
||||
if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
|
||||
reschedule(p);
|
||||
return p->has_cpu ? (1 << p->processor) : 0;
|
||||
|
||||
spin_lock_irqsave(&schedule_lock[p->processor], flags);
|
||||
if ( p->state == TASK_INTERRUPTIBLE )
|
||||
__wake_up(p);
|
||||
cpu_mask = __reschedule(p);
|
||||
if ( p->has_cpu )
|
||||
cpu_mask |= 1 << p->processor;
|
||||
spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
|
||||
|
||||
return cpu_mask;
|
||||
}
|
||||
|
||||
/* Notify the given set of CPUs that guest events may be outstanding. */
|
||||
|
||||
@@ -233,7 +233,7 @@ extern void free_irq(unsigned int, void *);
|
||||
extern unsigned long wait_init_idle;
|
||||
#define init_idle() clear_bit(smp_processor_id(), &wait_init_idle);
|
||||
|
||||
|
||||
extern spinlock_t schedule_lock[NR_CPUS] __cacheline_aligned;
|
||||
|
||||
/*
|
||||
* Scheduler functions (in schedule.c)
|
||||
@@ -247,8 +247,10 @@ long sched_bvtctl(unsigned long ctx_allow);
|
||||
long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp,
|
||||
unsigned long warpl, unsigned long warpu);
|
||||
void init_idle_task(void);
|
||||
int wake_up(struct task_struct *p);
|
||||
void __wake_up(struct task_struct *p);
|
||||
void wake_up(struct task_struct *p);
|
||||
long do_yield(void);
|
||||
unsigned long __reschedule(struct task_struct *p);
|
||||
void reschedule(struct task_struct *p);
|
||||
|
||||
/* NB. Limited entry in Xen. Not for arbitrary use! */
|
||||
|
||||
@@ -305,6 +305,24 @@ DO_ERROR(18, SIGBUS, "machine check", machine_check)
|
||||
|
||||
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
|
||||
{
|
||||
/*
|
||||
* If we trapped on an LDT access then ensure that the default_ldt is
|
||||
* loaded, if nothing else. We load default_ldt lazily because LDT
|
||||
* switching costs time and many applications don't need it.
|
||||
*/
|
||||
if ( unlikely((error_code & 6) == 4) )
|
||||
{
|
||||
unsigned long ldt;
|
||||
flush_page_update_queue(); /* ensure LDTR is up to date */
|
||||
__asm__ __volatile__ ( "sldt %0" : "=r" (ldt) );
|
||||
if ( likely(ldt == 0) )
|
||||
{
|
||||
queue_set_ldt((unsigned long)&default_ldt[0], 5);
|
||||
flush_page_update_queue();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(regs->xcs & 2))
|
||||
goto gp_in_kernel;
|
||||
|
||||
|
||||
@@ -18,18 +18,20 @@ extern struct desc_struct default_ldt[];
|
||||
|
||||
static inline void clear_LDT(void)
|
||||
{
|
||||
queue_set_ldt((unsigned long)&default_ldt[0], 5);
|
||||
/*
|
||||
* NB. We load the default_ldt for lcall7/27 handling on demand, as
|
||||
* it slows down context switching. Noone uses it anyway.
|
||||
*/
|
||||
queue_set_ldt(0, 0);
|
||||
}
|
||||
|
||||
static inline void load_LDT(struct mm_struct *mm)
|
||||
{
|
||||
void *segments = mm->context.segments;
|
||||
int count = LDT_ENTRIES;
|
||||
int count = 0;
|
||||
|
||||
if (!segments) {
|
||||
segments = &default_ldt[0];
|
||||
count = 5;
|
||||
}
|
||||
if ( unlikely(segments != NULL) )
|
||||
count = LDT_ENTRIES;
|
||||
|
||||
queue_set_ldt((unsigned long)segments, count);
|
||||
}
|
||||
|
||||