ia64/xen-unstable

changeset 15341:a371cfbd62e8

[IA64] Revive ACPI power management for IA64.

c/s 14552 took PM1a_EVT_BLK registers from Qemu into Xen.
Also support ACPI PM timer function.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Alex Williamson <alex.williamson@hp.com>
date Thu Jun 14 15:29:52 2007 -0600 (2007-06-14)
parents ed3bd3953287
children 1623f5f5094f
files xen/arch/ia64/vmx/Makefile xen/arch/ia64/vmx/mmio.c xen/arch/ia64/vmx/vacpi.c xen/arch/ia64/vmx/vmx_init.c xen/include/asm-ia64/hvm/vacpi.h xen/include/asm-ia64/vmx_platform.h
line diff
     1.1 --- a/xen/arch/ia64/vmx/Makefile	Thu Jun 14 15:13:59 2007 -0600
     1.2 +++ b/xen/arch/ia64/vmx/Makefile	Thu Jun 14 15:29:52 2007 -0600
     1.3 @@ -18,3 +18,4 @@ obj-y += vmx_virt.o
     1.4  obj-y += vmx_vsa.o
     1.5  obj-y += vtlb.o
     1.6  obj-y += optvfault.o
     1.7 +obj-y += vacpi.o
     2.1 --- a/xen/arch/ia64/vmx/mmio.c	Thu Jun 14 15:13:59 2007 -0600
     2.2 +++ b/xen/arch/ia64/vmx/mmio.c	Thu Jun 14 15:29:52 2007 -0600
     2.3 @@ -37,6 +37,7 @@
     2.4  #include <xen/domain.h>
     2.5  #include <asm/viosapic.h>
     2.6  #include <asm/vlsapic.h>
     2.7 +#include <asm/hvm/vacpi.h>
     2.8  
     2.9  #define HVM_BUFFERED_IO_RANGE_NR 1
    2.10  
    2.11 @@ -234,6 +235,9 @@ static void legacy_io_access(VCPU *vcpu,
    2.12      if (vmx_ide_pio_intercept(p, val))
    2.13          return;
    2.14  
    2.15 +    if (IS_ACPI_ADDR(p->addr) && vacpi_intercept(p, val))
    2.16 +	return;
    2.17 +
    2.18      vmx_send_assist_req(v);
    2.19      if(dir==IOREQ_READ){ //read
    2.20          *val=p->data;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/ia64/vmx/vacpi.c	Thu Jun 14 15:29:52 2007 -0600
     3.3 @@ -0,0 +1,179 @@
     3.4 +/*
     3.5 + * vacpi.c: emulation of the ACPI
     3.6 + * based on x86 hvm/pmtimer.c
     3.7 + *
     3.8 + * Copyright (c) 2007, FUJITSU LIMITED
     3.9 + *      Kouya Shimura <kouya at jp fujitsu com>
    3.10 + *
    3.11 + * Copyright (c) 2007, XenSource inc.
    3.12 + * Copyright (c) 2006, Intel Corporation.
    3.13 + *
    3.14 + * This program is free software; you can redistribute it and/or modify it
    3.15 + * under the terms and conditions of the GNU General Public License,
    3.16 + * version 2, as published by the Free Software Foundation.
    3.17 + *
    3.18 + * This program is distributed in the hope it will be useful, but WITHOUT
    3.19 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.20 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    3.21 + * more details.
    3.22 + *
    3.23 + * You should have received a copy of the GNU General Public License along with
    3.24 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    3.25 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    3.26 + */
    3.27 +
    3.28 +#include <asm/vmx_vcpu.h>
    3.29 +#include <asm/vmx.h>
    3.30 +#include <asm/hvm/vacpi.h>
    3.31 +
    3.32 +/* The interesting bits of the PM1a_STS register */
    3.33 +#define TMR_STS    (1 << 0)
    3.34 +#define PWRBTN_STS (1 << 5)
    3.35 +#define GBL_STS    (1 << 8)
    3.36 +
    3.37 +/* The same in PM1a_EN */
    3.38 +#define TMR_EN     (1 << 0)
    3.39 +#define PWRBTN_EN  (1 << 5)
    3.40 +#define GBL_EN     (1 << 8)
    3.41 +
    3.42 +/* Mask of bits in PM1a_STS that can generate an SCI.  Although the ACPI
    3.43 + * spec lists other bits, the PIIX4, which we are emulating, only
    3.44 + * supports these three.  For now, we only use TMR_STS; in future we
    3.45 + * will let qemu set the other bits */
    3.46 +#define SCI_MASK (TMR_STS|PWRBTN_STS|GBL_STS)
    3.47 +
    3.48 +/* SCI IRQ number (must match SCI_INT number in ACPI FADT in hvmloader) */
    3.49 +#define SCI_IRQ 9
    3.50 +
    3.51 +/* We provide a 32-bit counter (must match the TMR_VAL_EXT bit in the FADT) */
    3.52 +#define TMR_VAL_MASK  (0xffffffff)
    3.53 +#define TMR_VAL_MSB   (0x80000000)
    3.54 +
    3.55 +/* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */
    3.56 +static void pmt_update_sci(struct domain *d, struct vacpi *s)
    3.57 +{
    3.58 +	if (s->regs.pm1a_en & s->regs.pm1a_sts & SCI_MASK)
    3.59 +		viosapic_set_irq(d, SCI_IRQ, 1);  /* Assert */
    3.60 +	else
    3.61 +		viosapic_set_irq(d, SCI_IRQ, 0);
    3.62 +}
    3.63 +
    3.64 +/* Set the correct value in the timer, accounting for time elapsed
    3.65 + * since the last time we did that. */
    3.66 +static void pmt_update_time(struct domain *d)
    3.67 +{
    3.68 +	struct vacpi *s = &d->arch.hvm_domain.vacpi;
    3.69 +	s_time_t curr_gtime;
    3.70 +	unsigned long delta;
    3.71 +	uint32_t msb = s->regs.tmr_val & TMR_VAL_MSB;
    3.72 +
    3.73 +	/* Update the timer */
    3.74 +	curr_gtime = NOW();
    3.75 +	delta = curr_gtime - s->last_gtime;
    3.76 +	delta = ((delta >> 8) * ((FREQUENCE_PMTIMER << 32) / SECONDS(1))) >> 24;
    3.77 +	s->regs.tmr_val += delta;
    3.78 +	s->regs.tmr_val &= TMR_VAL_MASK;
    3.79 +	s->last_gtime = curr_gtime;
    3.80 +
    3.81 +	/* If the counter's MSB has changed, set the status bit */
    3.82 +	if ((s->regs.tmr_val & TMR_VAL_MSB) != msb) {
    3.83 +		s->regs.pm1a_sts |= TMR_STS;
    3.84 +		pmt_update_sci(d, s);
    3.85 +	}
    3.86 +}
    3.87 +
    3.88 +/* This function should be called soon after each time the MSB of the
    3.89 + * pmtimer register rolls over, to make sure we update the status
    3.90 + * registers and SCI at least once per rollover */
    3.91 +static void pmt_timer_callback(void *opaque)
    3.92 +{
    3.93 +	struct domain *d = opaque;
    3.94 +	struct vacpi *s = &d->arch.hvm_domain.vacpi;
    3.95 +	uint64_t cycles, time_flip;
    3.96 +
    3.97 +	/* Recalculate the timer and make sure we get an SCI if we need one */
    3.98 +	pmt_update_time(d);
    3.99 +
   3.100 +	/* How close are we to the next MSB flip? */
   3.101 +	cycles = TMR_VAL_MSB - (s->regs.tmr_val & (TMR_VAL_MSB - 1));
   3.102 +
   3.103 +	/* Overall time between MSB flips */
   3.104 +	time_flip = (((SECONDS(1) << 23) / FREQUENCE_PMTIMER) * cycles) >> 23;
   3.105 +
   3.106 +	/* Wake up again near the next bit-flip */
   3.107 +	set_timer(&s->timer, NOW() + time_flip + MILLISECS(1));
   3.108 +}
   3.109 +
   3.110 +int vacpi_intercept(ioreq_t * iop, u64 * val)
   3.111 +{
   3.112 +	struct domain *d = current->domain;
   3.113 +	struct vacpi *s = &d->arch.hvm_domain.vacpi;
   3.114 +	uint64_t addr_off = iop->addr - ACPI_PM1A_EVT_BLK_ADDRESS;
   3.115 +
   3.116 +	if (addr_off < 4) {	/* Access to PM1a_STS and PM1a_EN registers */
   3.117 +		void *p = (void *)&s->regs.evt_blk + addr_off;
   3.118 +
   3.119 +		if (iop->dir == 1) {	/* Read */
   3.120 +			if (iop->size == 1)
   3.121 +				*val = *(uint8_t *) p;
   3.122 +			else if (iop->size == 2)
   3.123 +				*val = *(uint16_t *) p;
   3.124 +			else if (iop->size == 4)
   3.125 +				*val = *(uint32_t *) p;
   3.126 +			else
   3.127 +				panic_domain(NULL, "wrong ACPI "
   3.128 +					     "PM1A_EVT_BLK access\n");
   3.129 +		} else {	/* Write */
   3.130 +			uint8_t *sp = (uint8_t *) & iop->data;
   3.131 +			int i;
   3.132 +
   3.133 +			for (i = 0; i < iop->size; i++, addr_off++, p++, sp++) {
   3.134 +				if (addr_off < 2) /* PM1a_STS */
   3.135 +					/* write-to-clear */
   3.136 +					*(uint8_t *) p &= ~*sp;
   3.137 +				else /* PM1a_EN */
   3.138 +					*(uint8_t *) p = *sp;
   3.139 +			}
   3.140 +			/* Fix the SCI state to match the new register state */
   3.141 +			pmt_update_sci(d, s);
   3.142 +		}
   3.143 +
   3.144 +		iop->state = STATE_IORESP_READY;
   3.145 +		vmx_io_assist(current);
   3.146 +		return 1;
   3.147 +	}
   3.148 +
   3.149 +	if (iop->addr == ACPI_PM_TMR_BLK_ADDRESS) {
   3.150 +		if (iop->size != 4)
   3.151 +			panic_domain(NULL, "wrong ACPI PM timer access\n");
   3.152 +		if (iop->dir == 1) {	/* Read */
   3.153 +			pmt_update_time(d);
   3.154 +			*val = s->regs.tmr_val;
   3.155 +		}
   3.156 +		/* PM_TMR_BLK is read-only */
   3.157 +		iop->state = STATE_IORESP_READY;
   3.158 +		vmx_io_assist(current);
   3.159 +		return 1;
   3.160 +	}
   3.161 +
   3.162 +	return 0;
   3.163 +}
   3.164 +
   3.165 +void vacpi_init(struct domain *d)
   3.166 +{
   3.167 +	struct vacpi *s = &d->arch.hvm_domain.vacpi;
   3.168 +
   3.169 +	s->regs.tmr_val = 0;
   3.170 +	s->regs.evt_blk = 0;
   3.171 +	s->last_gtime = NOW();
   3.172 +
   3.173 +	/* Set up callback to fire SCIs when the MSB of TMR_VAL changes */
   3.174 +	init_timer(&s->timer, pmt_timer_callback, d, first_cpu(cpu_online_map));
   3.175 +	pmt_timer_callback(d);
   3.176 +}
   3.177 +
   3.178 +void vacpi_relinquish_resources(struct domain *d)
   3.179 +{
   3.180 +	struct vacpi *s = &d->arch.hvm_domain.vacpi;
   3.181 +	kill_timer(&s->timer);
   3.182 +}
     4.1 --- a/xen/arch/ia64/vmx/vmx_init.c	Thu Jun 14 15:13:59 2007 -0600
     4.2 +++ b/xen/arch/ia64/vmx/vmx_init.c	Thu Jun 14 15:29:52 2007 -0600
     4.3 @@ -347,6 +347,8 @@ vmx_relinquish_guest_resources(struct do
     4.4  
     4.5  	for_each_vcpu(d, v)
     4.6  		vmx_release_assist_channel(v);
     4.7 +
     4.8 +	vacpi_relinquish_resources(d);
     4.9  }
    4.10  
    4.11  void
    4.12 @@ -415,6 +417,8 @@ void vmx_setup_platform(struct domain *d
    4.13  
    4.14  	/* Initialize iosapic model within hypervisor */
    4.15  	viosapic_init(d);
    4.16 +
    4.17 +	vacpi_init(d);
    4.18  }
    4.19  
    4.20  void vmx_do_launch(struct vcpu *v)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/include/asm-ia64/hvm/vacpi.h	Thu Jun 14 15:29:52 2007 -0600
     5.3 @@ -0,0 +1,55 @@
     5.4 +/*
     5.5 + * vacpi.h: Virtual ACPI definitions
     5.6 + *
     5.7 + * Copyright (c) 2007, FUJITSU LIMITED
     5.8 + *      Kouya Shimura <kouya at jp fujitsu com>
     5.9 + *
    5.10 + * This program is free software; you can redistribute it and/or modify it
    5.11 + * under the terms and conditions of the GNU General Public License,
    5.12 + * version 2, as published by the Free Software Foundation.
    5.13 + *
    5.14 + * This program is distributed in the hope it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    5.17 + * more details.
    5.18 + *
    5.19 + * You should have received a copy of the GNU General Public License along with
    5.20 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    5.21 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    5.22 + */
    5.23 +
    5.24 +#ifndef __ASM_IA64_HVM_VACPI_H__
    5.25 +#define __ASM_IA64_HVM_VACPI_H__
    5.26 +
    5.27 +#include <public/hvm/ioreq.h>
    5.28 +
    5.29 +#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40
    5.30 +#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
    5.31 +#define ACPI_PM_TMR_BLK_ADDRESS   (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
    5.32 +
    5.33 +#define IS_ACPI_ADDR(X)  ((unsigned long)((X)-ACPI_PM1A_EVT_BLK_ADDRESS)<12)
    5.34 +
    5.35 +#define FREQUENCE_PMTIMER  3579545UL	/* Timer should run at 3.579545 MHz */
    5.36 +
    5.37 +struct vacpi_regs {
    5.38 +	union {
    5.39 +		struct {
    5.40 +			uint32_t pm1a_sts:16;
    5.41 +			uint32_t pm1a_en:16;
    5.42 +		};
    5.43 +		uint32_t evt_blk;
    5.44 +	};
    5.45 +	uint32_t tmr_val;
    5.46 +};
    5.47 +
    5.48 +struct vacpi {
    5.49 +	struct vacpi_regs regs;
    5.50 +	s_time_t last_gtime;
    5.51 +	struct timer timer;
    5.52 +};
    5.53 +
    5.54 +int vacpi_intercept(ioreq_t * p, u64 * val);
    5.55 +void vacpi_init(struct domain *d);
    5.56 +void vacpi_relinquish_resources(struct domain *d);
    5.57 +
    5.58 +#endif	/* __ASM_IA64_HVM_VACPI_H__ */
     6.1 --- a/xen/include/asm-ia64/vmx_platform.h	Thu Jun 14 15:13:59 2007 -0600
     6.2 +++ b/xen/include/asm-ia64/vmx_platform.h	Thu Jun 14 15:29:52 2007 -0600
     6.3 @@ -22,6 +22,7 @@
     6.4  #include <public/xen.h>
     6.5  #include <public/hvm/params.h>
     6.6  #include <asm/viosapic.h>
     6.7 +#include <asm/hvm/vacpi.h>
     6.8  
     6.9  
    6.10  /* Value of guest os type */
    6.11 @@ -54,6 +55,7 @@ typedef struct virtual_platform_def {
    6.12      struct mmio_list    *mmio;
    6.13      /* One IOSAPIC now... */
    6.14      struct viosapic     viosapic;
    6.15 +    struct vacpi        vacpi;
    6.16  } vir_plat_t;
    6.17  
    6.18  static inline int __fls(uint32_t word)