From d2ea4546c30b7cb7d24cf0a0a7104552574e2d70 Mon Sep 17 00:00:00 2001 From: Yin Fengwei Date: Mon, 4 Jun 2018 14:45:33 +0800 Subject: [PATCH] hv: Add suspend/resume callback for ioapic These two functions will be called when ACRN enter/exit S3. Signed-off-by: Zheng Gen Signed-off-by: Yan Like Acked-by: Eddie Dong --- hypervisor/arch/x86/ioapic.c | 42 ++++++++++++++++++++++++++++ hypervisor/include/arch/x86/ioapic.h | 4 +++ 2 files changed, 46 insertions(+) diff --git a/hypervisor/arch/x86/ioapic.c b/hypervisor/arch/x86/ioapic.c index 764189f1d..96dca55a7 100644 --- a/hypervisor/arch/x86/ioapic.c +++ b/hypervisor/arch/x86/ioapic.c @@ -10,6 +10,8 @@ #define IOAPIC_REGSEL_OFFSET 0 #define IOAPIC_WINSWL_OFFSET 0x10 +#define IOAPIC_MAX_PIN 256 + /* IOAPIC Redirection Table (RTE) Entry structure */ struct ioapic_rte { uint32_t lo_32; @@ -25,6 +27,8 @@ static struct gsi_table gsi_table[NR_MAX_GSI]; static uint32_t nr_gsi; static spinlock_t ioapic_lock; +static struct ioapic_rte saved_rte[CONFIG_NR_IOAPICS][IOAPIC_MAX_PIN]; + /* * the irq to ioapic pin mapping should extract from ACPI MADT table * hardcoded here @@ -372,6 +376,44 @@ void dump_ioapic(void) } } +void suspend_ioapic(void) +{ + int ioapic_id, ioapic_pin; + + for (ioapic_id = 0; ioapic_id < CONFIG_NR_IOAPICS; ioapic_id++) { + int max_pins; + int version; + void *addr; + + addr = map_ioapic(get_ioapic_base(ioapic_id)); + version = ioapic_read_reg32(addr, IOAPIC_VER); + max_pins = (version & IOAPIC_MAX_RTE_MASK) >> MAX_RTE_SHIFT; + + for (ioapic_pin = 0; ioapic_pin < max_pins; ioapic_pin++) + ioapic_get_rte_entry(addr, ioapic_pin, + &saved_rte[ioapic_id][ioapic_pin]); + } +} + +void resume_ioapic(void) +{ + int ioapic_id, ioapic_pin; + + for (ioapic_id = 0; ioapic_id < CONFIG_NR_IOAPICS; ioapic_id++) { + int max_pins; + int version; + void *addr; + + addr = map_ioapic(get_ioapic_base(ioapic_id)); + version = ioapic_read_reg32(addr, IOAPIC_VER); + max_pins = (version & IOAPIC_MAX_RTE_MASK) >> MAX_RTE_SHIFT; + + for (ioapic_pin = 0; ioapic_pin < max_pins; ioapic_pin++) + ioapic_set_rte_entry(addr, ioapic_pin, + &saved_rte[ioapic_id][ioapic_pin]); + } +} + void get_rte_info(struct ioapic_rte *rte, bool *mask, bool *irr, bool *phys, int *delmode, bool *level, int *vector, uint32_t *dest) { diff --git a/hypervisor/include/arch/x86/ioapic.h b/hypervisor/include/arch/x86/ioapic.h index de49b8899..8084b31a1 100644 --- a/hypervisor/include/arch/x86/ioapic.h +++ b/hypervisor/include/arch/x86/ioapic.h @@ -30,6 +30,10 @@ void irq_gsi_mask_unmask(uint32_t irq, bool mask); void ioapic_set_rte(uint32_t irq, uint64_t rte); void ioapic_get_rte(uint32_t irq, uint64_t *rte); + +void suspend_ioapic(void); +void resume_ioapic(void); + extern uint16_t legacy_irq_to_pin[]; extern uint16_t pic_ioapic_pin_map[]; #endif /* IOAPIC_H */