Exemple #1
0
/* Set the correct value in the timer, accounting for time elapsed
 * since the last time we did that. */
static void pmt_update_time(PMTState *s)
{
    uint64_t curr_gtime, tmp;
    uint32_t tmr_val = s->pm.tmr_val, msb = tmr_val & TMR_VAL_MSB;
    
    ASSERT(spin_is_locked(&s->lock));

    /* Update the timer */
    curr_gtime = hvm_get_guest_time(s->vcpu);
    tmp = ((curr_gtime - s->last_gtime) * s->scale) + s->not_accounted;
    s->not_accounted = (uint32_t)tmp;
    tmr_val += tmp >> 32;
    tmr_val &= TMR_VAL_MASK;
    s->last_gtime = curr_gtime;

    /* Update timer value atomically wrt lock-free reads in handle_pmt_io(). */
    *(volatile uint32_t *)&s->pm.tmr_val = tmr_val;

    /* If the counter's MSB has changed, set the status bit */
    if ( (tmr_val & TMR_VAL_MSB) != msb )
    {
        s->pm.pm1a_sts |= TMR_STS;
        pmt_update_sci(s);
    }
}
Exemple #2
0
void hvm_acpi_sleep_button(struct domain *d)
{
    PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
    spin_lock(&s->lock);
    s->pm.pm1a_sts |= SLPBTN_STS;
    pmt_update_sci(s);
    spin_unlock(&s->lock);
}
Exemple #3
0
/* Handle port I/O to the PM1a_STS and PM1a_EN registers */
static int handle_evt_io(
    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
{
    struct vcpu *v = current;
    PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
    uint32_t addr, data, byte;
    int i;

    addr = port -
        ((v->domain->arch.hvm_domain.params[
            HVM_PARAM_ACPI_IOPORTS_LOCATION] == 0) ?
         PM1a_STS_ADDR_V0 : PM1a_STS_ADDR_V1);

    spin_lock(&s->lock);

    if ( dir == IOREQ_WRITE )
    {
        /* Handle this I/O one byte at a time */
        for ( i = bytes, data = *val;
              i > 0;
              i--, addr++, data >>= 8 )
        {
            byte = data & 0xff;
            switch ( addr )
            {
                /* PM1a_STS register bits are write-to-clear */
            case 0 /* PM1a_STS_ADDR */:
                s->pm.pm1a_sts &= ~byte;
                break;
            case 1 /* PM1a_STS_ADDR + 1 */:
                s->pm.pm1a_sts &= ~(byte << 8);
                break;
            case 2 /* PM1a_EN_ADDR */:
                s->pm.pm1a_en = (s->pm.pm1a_en & 0xff00) | byte;
                break;
            case 3 /* PM1a_EN_ADDR + 1 */:
                s->pm.pm1a_en = (s->pm.pm1a_en & 0xff) | (byte << 8);
                break;
            default:
                gdprintk(XENLOG_WARNING, 
                         "Bad ACPI PM register write: %x bytes (%x) at %x\n", 
                         bytes, *val, port);
            }
        }
        /* Fix up the SCI state to match the new register state */
        pmt_update_sci(s);
    }
    else /* p->dir == IOREQ_READ */
    {
/* Set the correct value in the timer, accounting for time elapsed
 * since the last time we did that. */
static void pmt_update_time(PMTState *s)
{
    uint64_t curr_gtime;
    uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB;

    ASSERT(spin_is_locked(&s->lock));

    /* Update the timer */
    curr_gtime = hvm_get_guest_time(s->vcpu);
    s->pm.tmr_val += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
    s->pm.tmr_val &= TMR_VAL_MASK;
    s->last_gtime = curr_gtime;

    /* If the counter's MSB has changed, set the status bit */
    if ( (s->pm.tmr_val & TMR_VAL_MSB) != msb )
    {
        s->pm.pm1a_sts |= TMR_STS;
        pmt_update_sci(s);
    }
}