From patchwork Thu Jun 20 10:15:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hu Tao X-Patchwork-Id: 252852 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 40A8A2C029B for ; Thu, 20 Jun 2013 20:22:34 +1000 (EST) Received: from localhost ([::1]:43099 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Upc0c-00077V-6A for incoming@patchwork.ozlabs.org; Thu, 20 Jun 2013 06:22:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48641) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Upbvd-0007Mv-EZ for qemu-devel@nongnu.org; Thu, 20 Jun 2013 06:17:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Upbvb-0000j8-7M for qemu-devel@nongnu.org; Thu, 20 Jun 2013 06:17:21 -0400 Received: from [222.73.24.84] (port=19949 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UpbvZ-0000fd-JX for qemu-devel@nongnu.org; Thu, 20 Jun 2013 06:17:19 -0400 X-IronPort-AV: E=Sophos;i="4.87,903,1363104000"; d="scan'208";a="7614706" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 20 Jun 2013 18:13:11 +0800 Received: from fnstmail02.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id r5KAG4O1006751 for ; Thu, 20 Jun 2013 18:16:05 +0800 Received: from G08FNSTD100614.fnst.cn.fujitsu.com ([10.167.233.156]) by fnstmail02.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2013062018145891-2329256 ; Thu, 20 Jun 2013 18:14:58 +0800 From: Hu Tao To: qemu-devel@nongnu.org Date: Thu, 20 Jun 2013 18:15:11 +0800 Message-Id: X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/06/20 18:14:58, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/06/20 18:14:59, Serialize complete at 2013/06/20 18:14:59 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 222.73.24.84 Subject: [Qemu-devel] [PATCH RFC 12/15] introduce memory controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Hu Tao --- hw/i386/pc.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci-host/piix.c | 1 - include/hw/i386/pc.h | 43 ++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 398b201..c28baa2 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1256,3 +1256,159 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i); } } + +void mc_update_pam(MemoryController *d) +{ + PCIDevice *pd = PCI_DEVICE(d); + MemoryControllerClass *c = MEMORY_CONTROLLER_GET_CLASS(d); + int i; + + memory_region_transaction_begin(); + for (i = 0; i < 13; i++) { + pam_update(&d->pam_regions[i], i, + pd->config[c->pam0 + ((i + 1) / 2)]); + } + memory_region_transaction_commit(); +} + +void mc_update_smram(MemoryController *d) +{ + PCIDevice *pd = PCI_DEVICE(d); + MemoryControllerClass *c = MEMORY_CONTROLLER_GET_CLASS(d); + + memory_region_transaction_begin(); + smram_update(&d->smram_region, pd->config[c->smram], + d->smm_enabled); + memory_region_transaction_commit(); +} + +void mc_update(MemoryController *d) +{ + mc_update_pam(d); + mc_update_smram(d); +} + +void mc_set_smm(int val, void *arg) +{ + MemoryController *d = arg; + PCIDevice *pd = PCI_DEVICE(d); + MemoryControllerClass *c = MEMORY_CONTROLLER_GET_CLASS(d); + + memory_region_transaction_begin(); + smram_set_smm(&d->smm_enabled, val, pd->config[c->smram], + &d->smram_region); + memory_region_transaction_commit(); +} + +static int memory_controller_init(PCIDevice *dev) +{ + MemoryController *m = MEMORY_CONTROLLER(dev); + MemoryControllerClass *c = MEMORY_CONTROLLER_GET_CLASS(dev); + ram_addr_t ram_size; + hwaddr below_4g_mem_size, above_4g_mem_size; + hwaddr pci_hole_start, pci_hole_size; + hwaddr pci_hole64_start, pci_hole64_size; + int i; + + g_assert(m->system_memory != NULL); + + if(m->ram_size > c->pci_hole_start) { + below_4g_mem_size = c->pci_hole_start; + above_4g_mem_size = m->ram_size - c->pci_hole_start; + } else { + below_4g_mem_size = m->ram_size; + above_4g_mem_size = 0; + } + + /* Allocate RAM. We allocate it as a single memory region and use + * aliases to address portions of it, mostly for backwards compatibility + * with older qemus that used qemu_ram_alloc(). + */ + memory_region_init_ram(&m->ram, "pc.ram", m->ram_size); + vmstate_register_ram_global(&m->ram); + memory_region_init_alias(&m->ram_below_4g, "ram-below-4g", &m->ram, + 0, below_4g_mem_size); + memory_region_add_subregion(m->system_memory, 0, &m->ram_below_4g); + if (above_4g_mem_size > 0) { + memory_region_init_alias(&m->ram_above_4g, "ram-above-4g", &m->ram, + below_4g_mem_size, above_4g_mem_size); + memory_region_add_subregion(m->system_memory, c->pci_hole_end, + &m->ram_above_4g); + } + + pci_hole_start = below_4g_mem_size; + pci_hole_size = c->pci_hole_end - pci_hole_start; + + pci_hole64_start = c->pci_hole_end + m->ram_size - pci_hole_start; + if (sizeof(hwaddr) == 4) { + pci_hole64_size = 0; + } else { + pci_hole64_size = (1ULL << 62); + } + + memory_region_init_alias(&m->pci_hole, "pci-hole", m->pci_address_space, + pci_hole_start, pci_hole_size); + memory_region_add_subregion(m->system_memory, pci_hole_start, + &m->pci_hole); + memory_region_init_alias(&m->pci_hole_64bit, "pci-hole64", + m->pci_address_space, + pci_hole64_start, pci_hole64_size); + if (pci_hole64_size) { + memory_region_add_subregion(m->system_memory, pci_hole64_start, + &m->pci_hole_64bit); + } + memory_region_init_alias(&m->smram_region, "smram-region", + m->pci_address_space, 0xa0000, 0x20000); + memory_region_add_subregion_overlap(m->system_memory, 0xa0000, + &m->smram_region, 1); + memory_region_set_enabled(&m->smram_region, false); + + init_pam(m->ram_memory, m->system_memory, m->pci_address_space, + &m->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); + for (i = 0; i < 12; ++i) { + init_pam(m->ram_memory, m->system_memory, m->pci_address_space, + &m->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, + PAM_EXPAN_SIZE); + } + + ram_size = m->ram_size / 8 / 1024 / 1024; + if (ram_size > 255) { + ram_size = 255; + } + dev->config[0x57] = ram_size; + + dev->config[0x72] = 0x02; + + cpu_smm_register(c->set_smm, m); + return 0; +} + +static void memory_controller_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + MemoryControllerClass *mc = MEMORY_CONTROLLER_CLASS(klass); + + k->no_hotplug = 1; + k->init = memory_controller_init; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "Host bridge"; + dc->no_user = 1; + mc->set_smm = mc_set_smm; + mc->update = mc_update; +} + +static const TypeInfo memory_controller_type_info = { + .name = TYPE_MEMORY_CONTROLLER, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(MemoryController), + .class_init = memory_controller_class_init, + .class_size = sizeof(MemoryControllerClass), +}; + +static void memory_controller_register_types(void) +{ + type_register_static(&memory_controller_type_info); +} + +type_init(memory_controller_register_types) diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 5318ddc..44ebe0f 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -99,7 +99,6 @@ struct I440FXPMCState { MemoryRegion ram; MemoryRegion ram_below_4g; MemoryRegion ram_above_4g; - }; #define TYPE_I440FX_DEVICE "i440FX" diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 5f60365..f06008b 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -8,6 +8,49 @@ #include "hw/block/fdc.h" #include "net/net.h" #include "hw/i386/ioapic.h" +#include "hw/pci/pci.h" +#include "hw/pci-host/pam.h" + +#define TYPE_MEMORY_CONTROLLER "memory controller" +#define MEMORY_CONTROLLER(obj) OBJECT_CHECK(MemoryController, (obj), TYPE_DEVICE) +#define MEMORY_CONTROLLER_CLASS(klass) OBJECT_CLASS_CHECK(MemoryControllerClass, (klass), TYPE_MEMORY_CONTROLLER) +#define MEMORY_CONTROLLER_GET_CLASS(obj) OBJECT_GET_CLASS(MemoryControllerClass, (obj), TYPE_MEMORY_CONTROLLER) + +typedef struct MemoryController MemoryController; +typedef struct MemoryControllerClass MemoryControllerClass; + +typedef struct MemoryControllerClass { + PCIDeviceClass parent_class; + + hwaddr pci_hole_start; + hwaddr pci_hole_end; + uint16_t pam0; + uint16_t smram; + + void (*set_smm)(int val, void *arg); + void (*update)(MemoryController *m); +} MemoryControllerClass; + +typedef struct MemoryController { + PCIDevice dev; + MemoryRegion *system_memory; + MemoryRegion *pci_address_space; + MemoryRegion *ram_memory; + MemoryRegion pci_hole; + MemoryRegion pci_hole_64bit; + PAMMemoryRegion pam_regions[13]; + MemoryRegion smram_region; + uint8_t smm_enabled; + ram_addr_t ram_size; + MemoryRegion ram; + MemoryRegion ram_below_4g; + MemoryRegion ram_above_4g; +} MemoryController; + +void mc_update_pam(MemoryController *d); +void mc_update_smram(MemoryController *d); +void mc_update(MemoryController *d); +void mc_set_smm(int val, void *arg); /* PC-style peripherals (also used by other machines). */