[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Intercept ACPI pm-timer registers
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1174900383 0 # Node ID 3afefd64e39271dbd0d9ea26f79f41a05b89fdd8 # Parent dccb274295ae4df8812a645ea4809e82ae54b2e0 [HVM] Intercept ACPI pm-timer registers Bring the PM1a_STS and PM1a_EN registers into Xen and use them to deliver SCI to the guest before it sees the MSB of the pm-timer change. Also correct some of the semantics of the registers. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- tools/ioemu/hw/piix4acpi.c | 243 ++---------------------------------------- xen/arch/x86/hvm/hvm.c | 3 xen/arch/x86/hvm/pmtimer.c | 220 ++++++++++++++++++++++++++++++++++---- xen/include/asm-x86/hvm/io.h | 2 xen/include/asm-x86/hvm/vpt.h | 4 xen/include/public/hvm/save.h | 4 6 files changed, 220 insertions(+), 256 deletions(-) diff -r dccb274295ae -r 3afefd64e392 tools/ioemu/hw/piix4acpi.c --- a/tools/ioemu/hw/piix4acpi.c Mon Mar 26 01:13:16 2007 +0100 +++ b/tools/ioemu/hw/piix4acpi.c Mon Mar 26 09:13:03 2007 +0000 @@ -52,126 +52,16 @@ typedef struct AcpiDeviceState AcpiDevic typedef struct AcpiDeviceState AcpiDeviceState; AcpiDeviceState *acpi_device_table; -typedef struct PM1Event_BLK { - uint16_t pm1_status; /* pm1a_EVT_BLK */ - uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */ -}PM1Event_BLK; - typedef struct PCIAcpiState { PCIDevice dev; - uint16_t irq; - uint16_t pm1_status; /* pm1a_EVT_BLK */ - uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */ uint16_t pm1_control; /* pm1a_ECNT_BLK */ - uint32_t pm1_timer; /* pmtmr_BLK */ - uint64_t old_vmck_ticks; /* using vm_clock counter */ } PCIAcpiState; - -static PCIAcpiState *acpi_state; - -static void acpi_reset(PCIAcpiState *s) -{ - uint8_t *pci_conf; - pci_conf = s->dev.config; - - pci_conf[0x42] = 0x00; - pci_conf[0x43] = 0x00; - s->irq = 9; - s->pm1_status = 0; - s->pm1_enable = 0x00; /* TMROF_EN should cleared */ - s->pm1_control = SCI_EN; /* SCI_EN */ - s->pm1_timer = 0; - s->old_vmck_ticks = qemu_get_clock(vm_clock); -} - -/*byte access */ -static void acpiPm1Status_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - if ((val&TMROF_STS)==TMROF_STS) - s->pm1_status = s->pm1_status&!TMROF_STS; - - if ((val&GBL_STS)==GBL_STS) - s->pm1_status = s->pm1_status&!GBL_STS; - -/* printf("acpiPm1Status_writeb \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */ -} - -static uint32_t acpiPm1Status_readb(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = s->pm1_status; -/* printf("acpiPm1Status_readb \n addr %x val:%x\n", addr, val); */ - - return val; -} - -static void acpiPm1StatusP1_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_status = (val<<8)||(s->pm1_status); -/* printf("acpiPm1StatusP1_writeb \n addr %x val:%x\n", addr, val); */ -} - -static uint32_t acpiPm1StatusP1_readb(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = (s->pm1_status)>>8; - printf("acpiPm1StatusP1_readb \n addr %x val:%x\n", addr, val); - - return val; -} - -static void acpiPm1Enable_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_enable = val; -/* printf("acpiPm1Enable_writeb \n addr %x val:%x\n", addr, val); */ -} - -static uint32_t acpiPm1Enable_readb(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = (s->pm1_enable)||0x1; -/* printf("acpiPm1Enable_readb \n addr %x val:%x\n", addr, val); */ - - return val; -} - -static void acpiPm1EnableP1_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_enable = (val<<8)||(s->pm1_enable); -/* printf("acpiPm1EnableP1_writeb \n addr %x val:%x\n", addr, val); */ - -} - -static uint32_t acpiPm1EnableP1_readb(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = (s->pm1_enable)>>8; -/* printf("acpiPm1EnableP1_readb \n addr %x val:%x\n", addr, val); */ - - return val; -} static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val) { PCIAcpiState *s = opaque; - s->pm1_control = val; + s->pm1_control = (s->pm1_control & 0xff00) | (val & 0xff); /* printf("acpiPm1Control_writeb \n addr %x val:%x\n", addr, val); */ } @@ -181,7 +71,8 @@ static uint32_t acpiPm1Control_readb(voi PCIAcpiState *s = opaque; uint32_t val; - val = s->pm1_control; + /* Mask out the write-only bits */ + val = s->pm1_control & ~(GBL_RLS|SLP_EN) & 0xff; /* printf("acpiPm1Control_readb \n addr %x val:%x\n", addr, val); */ return val; @@ -191,14 +82,13 @@ static void acpiPm1ControlP1_writeb(void { PCIAcpiState *s = opaque; - s->pm1_control = (val<<8)||(s->pm1_control); + s->pm1_control = (s->pm1_control & 0xff) | (val << 8); /* printf("acpiPm1ControlP1_writeb \n addr %x val:%x\n", addr, val); */ // Check for power off request - + val <<= 8; if (((val & SLP_EN) != 0) && ((val & SLP_TYP_MASK) == SLP_VAL)) { - s->pm1_timer=0x0; //clear ACPI timer qemu_system_shutdown_request(); } } @@ -208,7 +98,8 @@ static uint32_t acpiPm1ControlP1_readb(v PCIAcpiState *s = opaque; uint32_t val; - val = (s->pm1_control)>>8; + /* Mask out the write-only bits */ + val = (s->pm1_control & ~(GBL_RLS|SLP_EN)) >> 8; /* printf("acpiPm1ControlP1_readb \n addr %x val:%x\n", addr, val); */ return val; @@ -216,50 +107,6 @@ static uint32_t acpiPm1ControlP1_readb(v /* word access */ - -static void acpiPm1Status_writew(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - if ((val&TMROF_STS)==TMROF_STS) - s->pm1_status = s->pm1_status&!TMROF_STS; - - if ((val&GBL_STS)==GBL_STS) - s->pm1_status = s->pm1_status&!GBL_STS; - -/* printf("acpiPm1Status_writew \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */ -} - -static uint32_t acpiPm1Status_readw(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = s->pm1_status; -/* printf("acpiPm1Status_readw \n addr %x val:%x\n", addr, val); */ - - return val; -} - -static void acpiPm1Enable_writew(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_enable = val; -/* printf("acpiPm1Enable_writew \n addr %x val:%x\n", addr, val); */ - -} - -static uint32_t acpiPm1Enable_readw(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = s->pm1_enable; -/* printf("acpiPm1Enable_readw \n addr %x val:%x\n", addr, val); */ - - return val; -} static void acpiPm1Control_writew(void *opaque, uint32_t addr, uint32_t val) { @@ -282,56 +129,13 @@ static uint32_t acpiPm1Control_readw(voi PCIAcpiState *s = opaque; uint32_t val; - val = s->pm1_control; + /* Mask out the write-only bits */ + val = s->pm1_control & ~(GBL_RLS|SLP_EN); /* printf("acpiPm1Control_readw \n addr %x val:%x\n", addr, val); */ return val; } -/* dword access */ - -static void acpiPm1Event_writel(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_status = val; - s->pm1_enable = val>>16; -/* printf("acpiPm1Event_writel \n addr %x val:%x \n", addr, val); */ - -} - -static uint32_t acpiPm1Event_readl(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - uint32_t val; - - val = s->pm1_status|(s->pm1_enable<<16); -/* printf("acpiPm1Event_readl \n addr %x val:%x\n", addr, val); */ - - return val; -} - -static void acpiPm1Timer_writel(void *opaque, uint32_t addr, uint32_t val) -{ - PCIAcpiState *s = opaque; - - s->pm1_timer = val; - s->old_vmck_ticks = qemu_get_clock(vm_clock) + - muldiv64(val, FREQUENCE_PMTIMER, ticks_per_sec); -} - -static uint32_t acpiPm1Timer_readl(void *opaque, uint32_t addr) -{ - PCIAcpiState *s = opaque; - int64_t current_vmck_ticks = qemu_get_clock(vm_clock); - int64_t vmck_ticks_delta = current_vmck_ticks - s->old_vmck_ticks; - - if (s->old_vmck_ticks) - s->pm1_timer += muldiv64(vmck_ticks_delta, FREQUENCE_PMTIMER, - ticks_per_sec); - s->old_vmck_ticks = current_vmck_ticks; - return s->pm1_timer; -} static void acpi_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) @@ -341,37 +145,14 @@ static void acpi_map(PCIDevice *pci_dev, printf("register acpi io\n"); /* Byte access */ - register_ioport_write(addr, 1, 1, acpiPm1Status_writeb, d); - register_ioport_read(addr, 1, 1, acpiPm1Status_readb, d); - register_ioport_write(addr+1, 1, 1, acpiPm1StatusP1_writeb, d); - register_ioport_read(addr+1, 1, 1, acpiPm1StatusP1_readb, d); - - register_ioport_write(addr + 2, 1, 1, acpiPm1Enable_writeb, d); - register_ioport_read(addr + 2, 1, 1, acpiPm1Enable_readb, d); - register_ioport_write(addr + 2 +1, 1, 1, acpiPm1EnableP1_writeb, d); - register_ioport_read(addr + 2 +1, 1, 1, acpiPm1EnableP1_readb, d); - register_ioport_write(addr + 4, 1, 1, acpiPm1Control_writeb, d); register_ioport_read(addr + 4, 1, 1, acpiPm1Control_readb, d); register_ioport_write(addr + 4 + 1, 1, 1, acpiPm1ControlP1_writeb, d); register_ioport_read(addr + 4 +1, 1, 1, acpiPm1ControlP1_readb, d); /* Word access */ - register_ioport_write(addr, 2, 2, acpiPm1Status_writew, d); - register_ioport_read(addr, 2, 2, acpiPm1Status_readw, d); - - register_ioport_write(addr + 2, 2, 2, acpiPm1Enable_writew, d); - register_ioport_read(addr + 2, 2, 2, acpiPm1Enable_readw, d); - register_ioport_write(addr + 4, 2, 2, acpiPm1Control_writew, d); register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d); - - /* DWord access */ - register_ioport_write(addr, 4, 4, acpiPm1Event_writel, d); - register_ioport_read(addr, 4, 4, acpiPm1Event_readl, d); - - register_ioport_write(addr + 8, 4, 4, acpiPm1Timer_writel, d); - register_ioport_read(addr + 8, 4, 4, acpiPm1Timer_readl, d); } /* PIIX4 acpi pci configuration space, func 2 */ @@ -385,7 +166,6 @@ void pci_piix4_acpi_init(PCIBus *bus, in bus, "PIIX4 ACPI", sizeof(PCIAcpiState), devfn, NULL, NULL); - acpi_state = d; pci_conf = d->dev.config; pci_conf[0x00] = 0x86; /* Intel */ pci_conf[0x01] = 0x80; @@ -408,6 +188,9 @@ void pci_piix4_acpi_init(PCIBus *bus, in */ pci_conf[0x40] = 0x41; /* Special device-specific BAR at 0x40 */ pci_conf[0x41] = 0x1f; + pci_conf[0x42] = 0x00; + pci_conf[0x43] = 0x00; + d->pm1_control = SCI_EN; + acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO); - acpi_reset(d); } diff -r dccb274295ae -r 3afefd64e392 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Mon Mar 26 01:13:16 2007 +0100 +++ b/xen/arch/x86/hvm/hvm.c Mon Mar 26 09:13:03 2007 +0000 @@ -218,6 +218,7 @@ void hvm_domain_destroy(struct domain *d { pit_deinit(d); rtc_deinit(d); + pmtimer_deinit(d); hpet_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) @@ -303,7 +304,7 @@ int hvm_vcpu_initialise(struct vcpu *v) pit_init(v, cpu_khz); rtc_init(v, RTC_PORT(0)); - pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); + pmtimer_init(v); hpet_init(v); /* Init guest TSC to start from zero. */ diff -r dccb274295ae -r 3afefd64e392 xen/arch/x86/hvm/pmtimer.c --- a/xen/arch/x86/hvm/pmtimer.c Mon Mar 26 01:13:16 2007 +0100 +++ b/xen/arch/x86/hvm/pmtimer.c Mon Mar 26 09:13:03 2007 +0000 @@ -1,12 +1,172 @@ +/* + * hvm/pmtimer.c: emulation of the ACPI PM timer + * + * Copyright (c) 2007, XenSource inc. + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + #include <asm/hvm/vpt.h> #include <asm/hvm/io.h> #include <asm/hvm/support.h> +/* Slightly more readable port I/O addresses for the registers we intercept */ +#define PM1a_STS_ADDR (ACPI_PM1A_EVT_BLK_ADDRESS) +#define PM1a_EN_ADDR (ACPI_PM1A_EVT_BLK_ADDRESS + 2) +#define TMR_VAL_ADDR (ACPI_PM_TMR_BLK_ADDRESS) + +/* The interesting bit of the PM1a_STS register */ +#define TMR_STS (1 << 0) +#define PWRBTN_STS (1 << 5) +#define GBL_STS (1 << 8) + +/* The same in PM1a_EN */ +#define TMR_EN (1 << 0) +#define PWRBTN_EN (1 << 5) +#define GBL_EN (1 << 8) + +/* Mask of bits in PM1a_STS that can generate an SCI. Although the ACPI + * spec lists other bits, the PIIX4, which we are emulating, only + * supports these three. For now, we only use TMR_STS; in future we + * will let qemu set the other bits */ +#define SCI_MASK (TMR_STS|PWRBTN_STS|GBL_STS) + +/* SCI IRQ number (must match SCI_INT number in ACPI FADT in hvmloader) */ +#define SCI_IRQ 9 + +/* We provide a 32-bit counter (must match the TMR_VAL_EXT bit in the FADT) */ +#define TMR_VAL_MASK (0xffffffff) +#define TMR_VAL_MSB (0x80000000) + + +/* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */ +static void pmt_update_sci(PMTState *s) +{ + if ( s->pm.pm1a_en & s->pm.pm1a_sts & SCI_MASK ) + hvm_isa_irq_assert(s->vcpu->domain, SCI_IRQ); + else + hvm_isa_irq_deassert(s->vcpu->domain, SCI_IRQ); +} + +/* 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; + + /* 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); + } +} + +/* This function should be called soon after each time the MSB of the + * pmtimer register rolls over, to make sure we update the status + * registers and SCI at least once per rollover */ +static void pmt_timer_callback(void *opaque) +{ + PMTState *s = opaque; + uint32_t pmt_cycles_until_flip; + uint64_t time_until_flip; + + /* Recalculate the timer and make sure we get an SCI if we need one */ + pmt_update_time(s); + + /* How close are we to the next MSB flip? */ + pmt_cycles_until_flip = TMR_VAL_MSB - (s->pm.tmr_val & (TMR_VAL_MSB - 1)); + + /* Overall time between MSB flips */ + time_until_flip = (1000000000ULL << 31) / FREQUENCE_PMTIMER; + + /* Reduced appropriately */ + time_until_flip = (time_until_flip * pmt_cycles_until_flip) / (1ULL<<31); + + /* Wake up again near the next bit-flip */ + set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1)); +} + + +/* Handle port I/O to the PM1a_STS and PM1a_EN registers */ +static int handle_evt_io(ioreq_t *p) +{ + struct vcpu *v = current; + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + uint32_t addr, data, byte; + int i; + + if ( p->dir == 0 ) /* Write */ + { + /* Handle this I/O one byte at a time */ + for ( i = p->size, addr = p->addr, data = p->data; + i > 0; + i--, addr++, data >>= 8 ) + { + byte = data & 0xff; + switch(addr) + { + /* PM1a_STS register bits are write-to-clear */ + case PM1a_STS_ADDR: + s->pm.pm1a_sts &= ~byte; + break; + case PM1a_STS_ADDR + 1: + s->pm.pm1a_sts &= ~(byte << 8); + break; + + case PM1a_EN_ADDR: + s->pm.pm1a_en = (s->pm.pm1a_en & 0xff00) | byte; + break; + case 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: %"PRIu64 + " bytes (%#"PRIx64") at %"PRIx64"\n", + p->size, p->data, p->addr); + } + } + /* Fix up the SCI state to match the new register state */ + pmt_update_sci(s); + } + else /* Read */ + { + data = s->pm.pm1a_sts | (((uint32_t) s->pm.pm1a_en) << 16); + data >>= 8 * (p->addr - PM1a_STS_ADDR); + if ( p->size == 1 ) data &= 0xff; + else if ( p->size == 2 ) data &= 0xffff; + p->data = data; + } + return 1; +} + + +/* Handle port I/O to the TMR_VAL register */ static int handle_pmt_io(ioreq_t *p) { struct vcpu *v = current; PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - uint64_t curr_gtime; if (p->size != 4 || p->data_is_ptr || @@ -19,12 +179,8 @@ static int handle_pmt_io(ioreq_t *p) /* PM_TMR_BLK is read-only */ return 1; } else if (p->dir == 1) { /* read */ - /* Set the correct value in the timer, accounting for time - * elapsed since the last time we did that. */ - curr_gtime = hvm_get_guest_time(s->vcpu); - s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; - p->data = s->pm.timer; - s->last_gtime = curr_gtime; + pmt_update_time(s); + p->data = s->pm.tmr_val; return 1; } return 0; @@ -33,6 +189,7 @@ static int pmtimer_save(struct domain *d static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB; uint32_t x; /* Update the counter to the guest's current time. We always save @@ -40,7 +197,12 @@ static int pmtimer_save(struct domain *d * last_gtime, but just in case, make sure we only go forwards */ x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32; if ( x < 1UL<<31 ) - s->pm.timer += x; + s->pm.tmr_val += x; + if ( (s->pm.tmr_val & TMR_VAL_MSB) != msb ) + s->pm.pm1a_sts |= TMR_STS; + /* No point in setting the SCI here because we'll already have saved the + * IRQ and *PIC state; we'll fix it up when we restore the domain */ + return hvm_save_entry(PMTIMER, 0, h, &s->pm); } @@ -48,12 +210,15 @@ static int pmtimer_load(struct domain *d { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - /* Reload the counter */ + /* Reload the registers */ if ( hvm_load_entry(PMTIMER, h, &s->pm) ) return -EINVAL; /* Calculate future counter values from now. */ s->last_gtime = hvm_get_guest_time(s->vcpu); + + /* Set the SCI state from the registers */ + pmt_update_sci(s); return 0; } @@ -62,19 +227,30 @@ HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtim 1, HVMSR_PER_DOM); -void pmtimer_init(struct vcpu *v, int base) -{ - PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - - s->pm.timer = 0; +void pmtimer_init(struct vcpu *v) +{ + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + + s->pm.tmr_val = 0; + s->pm.pm1a_sts = 0; + s->pm.pm1a_en = 0; + s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); s->vcpu = v; - /* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every - * time the timer's top bit flips, and generate an SCI if TMR_EN - * (bit 0 of PM1a_EN) is set. For now, those registers are in - * qemu-dm, and we just calculate the timer's value on demand. */ - - register_portio_handler(v->domain, base, 4, handle_pmt_io); -} - + /* Intercept port I/O (need two handlers because PM1a_CNT is between + * PM1a_EN and TMR_VAL and is handled by qemu) */ + register_portio_handler(v->domain, TMR_VAL_ADDR, 4, handle_pmt_io); + register_portio_handler(v->domain, PM1a_STS_ADDR, 4, handle_evt_io); + + /* Set up callback to fire SCIs when the MSB of TMR_VAL changes */ + init_timer(&s->timer, pmt_timer_callback, s, v->processor); + pmt_timer_callback(s); +} + + +void pmtimer_deinit(struct domain *d) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + kill_timer(&s->timer); +} diff -r dccb274295ae -r 3afefd64e392 xen/include/asm-x86/hvm/io.h --- a/xen/include/asm-x86/hvm/io.h Mon Mar 26 01:13:16 2007 +0100 +++ b/xen/include/asm-x86/hvm/io.h Mon Mar 26 09:13:03 2007 +0000 @@ -80,7 +80,7 @@ struct hvm_io_op { struct cpu_user_regs io_context; /* current context */ }; -#define MAX_IO_HANDLER 8 +#define MAX_IO_HANDLER 9 #define HVM_PORTIO 0 #define HVM_MMIO 1 diff -r dccb274295ae -r 3afefd64e392 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Mon Mar 26 01:13:16 2007 +0100 +++ b/xen/include/asm-x86/hvm/vpt.h Mon Mar 26 09:13:03 2007 +0000 @@ -101,6 +101,7 @@ typedef struct PMTState { struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ uint64_t last_gtime; /* Last (guest) time we updated the timer */ uint64_t scale; /* Multiplier to get from tsc to timer ticks */ + struct timer timer; /* To make sure we send SCIs */ } PMTState; struct pl_time { /* platform time */ @@ -132,7 +133,8 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); -void pmtimer_init(struct vcpu *v, int base); +void pmtimer_init(struct vcpu *v); +void pmtimer_deinit(struct domain *d); void hpet_migrate_timers(struct vcpu *v); void hpet_init(struct vcpu *v); diff -r dccb274295ae -r 3afefd64e392 xen/include/public/hvm/save.h --- a/xen/include/public/hvm/save.h Mon Mar 26 01:13:16 2007 +0100 +++ b/xen/include/public/hvm/save.h Mon Mar 26 09:13:03 2007 +0000 @@ -392,7 +392,9 @@ DECLARE_HVM_SAVE_TYPE(HPET, 12, struct h */ struct hvm_hw_pmtimer { - uint32_t timer; + uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 24bit free-running counter */ + uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */ + uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */ }; DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |