qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 RESEND 1/5] apic: Implement LAPIC low priorit


From: Radim Krčmář
Subject: Re: [Qemu-devel] [PATCH v2 RESEND 1/5] apic: Implement LAPIC low priority arbitration functions
Date: Thu, 23 Apr 2015 15:49:39 +0200

2015-04-06 17:45-0600, James Sullivan:
> Currently, apic_get_arb_pri() is unimplemented and returns 0.
> 
> Implemented apic_get_arb_pri() and added two helper functions
> apic_compare_prio() and apic_lowest_prio() to be used for LAPIC
> arbitration.
> 
> Signed-off-by: James Sullivan <address@hidden>
> ---
> +static int apic_compare_prio(struct APICCommonState *cpu1,
> +                             struct APICCommonState *cpu2)
> +{
> +    return apic_get_arb_pri(cpu1) - apic_get_arb_pri(cpu2);
> +}
> +
> +static struct APICCommonState *apic_lowest_prio(const uint32_t
> +                                                *deliver_bitmask)
> +{
> +    APICCommonState *lowest = NULL;
> +    int i, d;
> +
> +    for (i = 0; i < MAX_APIC_WORDS; i++) {
> +        if (deliver_bitmask[i]) {
> +            d = i * 32 + apic_ffs_bit(deliver_bitmask[i]);
> +            if (!lowest || apic_compare_prio(local_apics[d], lowest) < 0) {
> +                lowest = local_apics[d];

deliver_bitmask is 8 times u32 to express all 255 possible APICs.
apic_ffs_bit() takes the last set bit, so this loop incorrectly
considers only up to 8 candidates for lowest priority delivery.
foreach_apic() could be used when fixing it, which would also avoid a
'local_apic[d] == NULL' crash.

> +            }
> +        }
> +    }
> +    return lowest;

(For consideration:
 APM 2-16.2.2 Lowest Priority Messages and Arbitration
   If there is a tie for lowest priority, the local APIC with the highest
   APIC ID is selected.

 Intel is undefined in spec and picks the lowest APIC ID in practice.)

> @@ -336,8 +360,27 @@ static int apic_get_ppr(APICCommonState *s)
>  
>  static int apic_get_arb_pri(APICCommonState *s)

(I'd call it apic_get_apr() -- we return the state of that register.)

>  {
> -    /* XXX: arbitration */
> -    return 0;
> +    int tpr, isrv, irrv, apr;
> +
> +    tpr = apic_get_tpr(s);
> +    isrv = get_highest_priority_int(s->isr);
> +    if (isrv < 0) {
> +        isrv = 0;
> +    }
> +    isrv >>= 4;
> +    irrv = get_highest_priority_int(s->irr);
> +    if (irrv < 0) {
> +        irrv = 0;
> +    }
> +    irrv >>= 4;
> +
> +    if ((tpr >= irrv) && (tpr > isrv)) {
> +        apr = s->tpr & 0xff;
> +    } else {
> +        apr = ((tpr & isrv) > irrv) ? (tpr & isrv) : irrv;
> +        apr <<= 4;
> +    }
> +    return apr;
>  }

(This function is called too much IMO.
 The trivial optimization is to memorize apic_get_arb_pri() of lowest
 priority LAPIC.  And you can instantly return if it is 0.
 The more complicated one is to use ARB as a real LAPIC register and
 update it on TPR/ISR/IRR change, so apic_get_arb_pri() would be just
 'return s->apr;'.)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]