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>
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)