WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] hvm bios: add PMM (a memory manager during POST)

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] hvm bios: add PMM (a memory manager during POST)
From: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
Date: Thu, 22 Jan 2009 20:12:22 +0900
Delivery-date: Thu, 22 Jan 2009 03:12:58 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
The PMM (POST Memory Manager) offers malloc/free functionality
for PCI option ROMs during POST (Power On Self Test).

This patch adds a PMM functionality to the guest BIOS.

For example, the option ROM on LSI Logic SAS card uses PMM and
failed to initialize the device without PMM.  Thus, the HVM can't
boot up directly from the passthroughed SCSI disk.
gPXE also uses PMM (I don't know what happens without PMM).

With this patch, we succeeded in SAS boot of HVM.

For further information about PMM:
http://www.phoenix.com/en/OEM-ODM/Customer+Services/White+Papers-Specs/PC+Industry+Specifications.htm
http://www.phoenix.com/NR/rdonlyres/873A00CF-33AC-4775-B77E-08E7B9754993/0/specspmm101.pdf

Thanks,
Kouya

Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
Signed-off-by: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>

diff -r af1d9af1a993 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/hvmloader/config.h Thu Jan 22 19:51:24 2009 +0900
@@ -45,6 +45,8 @@
 #define E820_NR_OFFSET                0x0
 #define E820_OFFSET                   0x8
 
+#define PMM_ENTRY_POINT               0xFFC0
+
 /* Xen Platform Device */
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
 
diff -r af1d9af1a993 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Thu Jan 22 19:51:24 2009 +0900
@@ -442,6 +442,35 @@
     return round_option_rom(rom->rom_size * 512 + 1);
 }
 
+typedef struct {
+    uint8_t signature[4]; /* "$PMM" */
+    uint8_t revision;     /* 01h */
+    uint8_t length;
+    uint8_t checksum;
+    uint16_t entrypoint[2];
+    uint8_t reserved[5];  /* All 0 */
+} __attribute__ ((packed)) pmm_struct_t;
+
+/*
+ * Set up POST Memory Manager.
+ */
+static void setup_pmm(uint32_t addr)
+{
+    pmm_struct_t *pmms = (pmm_struct_t *)addr;
+    uint8_t *p, csum;
+
+    memset(pmms, 0, sizeof(*pmms));
+    memcpy(pmms->signature, "$PMM", 4);
+    pmms->revision = 0x01;
+    pmms->length = sizeof(pmm_struct_t);
+    pmms->entrypoint[0] = PMM_ENTRY_POINT;
+    pmms->entrypoint[1] = ROMBIOS_SEG;
+
+    for (csum = 0, p = (uint8_t *)pmms; p < (uint8_t *)(pmms + 1); p++)
+        csum += *p;
+    pmms->checksum = -csum;
+}
+
 /*
  * Scan the PCI bus for the first NIC supported by etherboot, and copy
  * the corresponding rom data to *copy_rom_dest. Returns the length of the
@@ -648,7 +677,7 @@
 {
     int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0;
     int rombios_sz, smbios_sz;
-    uint32_t etherboot_phys_addr, option_rom_phys_addr;
+    uint32_t etherboot_phys_addr, option_rom_phys_addr, pmm_phys_addr;
     uint16_t xen_pfiob;
 
     printf("HVM Loader\n");
@@ -666,6 +695,13 @@
 
     printf("Writing SMBIOS tables ...\n");
     smbios_sz = hvm_write_smbios_tables();
+
+    pmm_phys_addr = SMBIOS_PHYSICAL_ADDRESS + round_option_rom(smbios_sz);
+    if ( pmm_phys_addr + sizeof(pmm_struct_t) < ROMBIOS_PHYSICAL_ADDRESS )
+    {
+        setup_pmm(pmm_phys_addr);
+        printf("Setup PMM at %x\n", pmm_phys_addr);
+    }
 
     printf("Loading ROMBIOS ...\n");
     rombios_sz = sizeof(rombios);
diff -r af1d9af1a993 tools/firmware/rombios/32bit/32bitbios.c
--- a/tools/firmware/rombios/32bit/32bitbios.c  Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/rombios/32bit/32bitbios.c  Thu Jan 22 19:51:24 2009 +0900
@@ -49,5 +49,7 @@
 
        TABLE_ENTRY(IDX_GET_S3_WAKING_VECTOR, get_s3_waking_vector),
 
+       TABLE_ENTRY(IDX_PMM, pmm),
+
        TABLE_ENTRY(IDX_LAST       , 0)     /* keep last */
 };
diff -r af1d9af1a993 tools/firmware/rombios/32bit/Makefile
--- a/tools/firmware/rombios/32bit/Makefile     Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/rombios/32bit/Makefile     Thu Jan 22 19:51:24 2009 +0900
@@ -18,7 +18,7 @@
 clean: subdirs-clean
        rm -rf *.o $(TARGET) $(DEPS)
 
-$(TARGET): 32bitbios.o $(MODULES) util.o
+$(TARGET): 32bitbios.o $(MODULES) util.o pmm.o
        $(LD) $(LDFLAGS_DIRECT) -s -r $^ -o 32bitbios_all.o
        @nm 32bitbios_all.o |                                \
          egrep '^ +U ' >/dev/null && {                      \
diff -r af1d9af1a993 tools/firmware/rombios/32bit/pmm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/pmm.c        Thu Jan 22 19:51:24 2009 +0900
@@ -0,0 +1,532 @@
+/*
+ *  pmm.c - POST(Power On Self Test) Memory Manager
+ *  according to the specification described in
+ *  
http://www.phoenix.com/NR/rdonlyres/873A00CF-33AC-4775-B77E-08E7B9754993/0/specspmm101.pdf
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *  Copyright (C) 2009 FUJITSU LIMITED
+ *
+ *  Author: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <../hvmloader/config.h>
+#include <../hvmloader/e820.h>
+
+#ifdef TEST_STANDALONE
+#include <stdio.h>
+#else
+#include "util.h"
+#endif
+
+//#define DEBUG_PMM
+
+#define ASSERT(_expr, _action)                                  \
+    if (!(_expr)) {                                             \
+        printf("ASSERTION FAIL: %s %s:%d %s()\n",               \
+               __STRING(_expr), __FILE__, __LINE__, __func__);  \
+        _action;                                                \
+    } else
+
+#ifdef DEBUG_PMM
+# define PMM_DEBUG(format, p...) printf("PMM " format, ##p)
+#else
+# define PMM_DEBUG(format, p...)
+#endif
+
+struct pmmAllocArgs {
+    uint16_t function;
+    uint32_t length;
+    uint32_t handle;
+    uint16_t flags;
+} __attribute__ ((packed));
+
+struct pmmFindArgs {
+    uint16_t function;
+    uint32_t handle;
+} __attribute__ ((packed));
+
+struct pmmDeallocArgs {
+    uint16_t function;
+    uint32_t buffer;
+} __attribute__ ((packed));
+
+#define PMM_FUNCTION_ALLOCATE   0
+#define PMM_FUNCTION_FIND       1         
+#define PMM_FUNCTION_DEALLOC    2
+
+#define PARAGRAPH_LENGTH        16  // unit of length
+
+#define PMM_HANDLE_ANONYMOUS    0xffffffff
+
+#define PMM_FLAGS_MEMORY_TYPE_MASK      0x0003
+#define PMM_FLAGS_MEMORY_INVALID        0
+#define PMM_FLAGS_MEMORY_CONVENTIONAL   1  // 0 to 1MB
+#define PMM_FLAGS_MEMORY_EXTENDED       2  // 1MB to 4GB
+#define PMM_FLAGS_MEMORY_ANY            3  // whichever is available
+#define PMM_FLAGS_ALIGINMENT            0x0004
+
+/* Error code */
+#define PMM_ENOMEM      (0)     // Out of memory, duplicate handle
+#define PMM_EINVAL      (-1)    // Invalid argument
+
+#define ALIGN_UP(addr, size)    (((addr)+((size)-1))&(~((size)-1)))
+#define ALIGN_DOWN(addr, size)  ((addr)&(~((size)-1)))
+
+typedef struct chunk {
+    uint32_t magic;
+    struct chunk *next;
+    uint32_t handle;
+    uint32_t __fill; // for 16byte alignment, not used
+    uint8_t buffer[PARAGRAPH_LENGTH]; // minimum length
+} chunk_t;
+
+typedef struct heap {
+    chunk_t *head, *end;
+} heap_t;
+
+#define HEAP_NOT_INITIALIZED    (chunk_t *)-1
+#define HEAP_ALIGNMENT          16
+
+/* 
+ * This must be located in the data segment since bss in 32bitbios
+ * doesn't be relocated.
+ */
+static struct {
+    heap_t heap;     // conventional memory (below 1MB, 0x10000-0x7FFFF)
+    heap_t ext_heap; // extended memory (above 1MB, 0x100000-)
+} pmm_data = { {HEAP_NOT_INITIALIZED, NULL}, {NULL, NULL} };
+
+#define CHUNK_MAGIC_INUSE   0x2A4D4D50  // 'PMM*'
+#define CHUNK_MAGIC_AVAIL   0x5F4D4D50  // 'PMM_'
+
+#define chunk_is_inuse(_c)  ((_c)->magic == CHUNK_MAGIC_INUSE)
+#define chunk_is_avail(_c)  ((_c)->magic == CHUNK_MAGIC_AVAIL)
+#define set_inuse(_c)       (_c)->magic = CHUNK_MAGIC_INUSE
+#define set_avail(_c)       (_c)->magic = CHUNK_MAGIC_AVAIL
+
+#define CHUNK_HEADER_SIZE   ((int)(&((chunk_t *)0)->buffer))
+#define MIN_CHUNK_SIZE      (sizeof(chunk_t))
+
+#define chunk_size(_c)      ((void *)((_c)->next) - (void *)(_c))
+#define chunk_buffer(_c)    ((uint32_t)(&(_c)->buffer))
+#define chunk_bufsize(_c)   (chunk_size(_c) - CHUNK_HEADER_SIZE)
+
+#define buffer_chunk(_buf)  (chunk_t *)((_buf) - CHUNK_HEADER_SIZE)
+
+#define chunk_loop_condition(_h, _c) \
+    (((_c) < (_h)->end) && (/* avoid infinite loop */ (_c) < (_c)->next))
+
+#define for_each_chunk(_h, _c)                  \
+    for ((_c) = (_h)->head;                     \
+         chunk_loop_condition(_h, _c);          \
+         (_c) = (_c)->next)
+
+#define for_remain_chunk(_h, _c)                \
+    for (;                                      \
+         chunk_loop_condition(_h, _c);          \
+         (_c) = (_c)->next)
+
+static chunk_t *
+split_chunk(chunk_t *cp, uint32_t length)
+{
+    chunk_t *sp = (void *)chunk_buffer(cp) + length;
+
+    if (chunk_bufsize(cp) - length < MIN_CHUNK_SIZE)
+        return cp;
+
+    sp->magic = CHUNK_MAGIC_AVAIL;
+    sp->next = cp->next;
+    sp->handle = PMM_HANDLE_ANONYMOUS;
+
+    cp->next = sp;
+    return sp;
+}
+
+static void
+join_available_chunks(heap_t *heap, chunk_t *cp)
+{
+    chunk_t *np = cp->next;
+
+    for_remain_chunk(heap, np)
+        if (chunk_is_inuse(np))
+            break;
+    cp->next = np;
+}
+
+static void
+pmm_init_heap(heap_t *heap, uint32_t from_addr, uint32_t to_addr)
+{
+    chunk_t *cp = (chunk_t *)ALIGN_UP(from_addr, HEAP_ALIGNMENT);
+
+    cp->magic = CHUNK_MAGIC_AVAIL;
+    cp->next = (chunk_t *)ALIGN_DOWN(to_addr, HEAP_ALIGNMENT);
+    cp->handle = PMM_HANDLE_ANONYMOUS;
+
+    heap->head = cp;
+    heap->end = cp->next;
+}
+
+static void
+pmm_initalize(void)
+{
+    int i, e820_nr = *E820_NR;
+    struct e820entry *e820 = E820;
+
+    /* extended memory: RAM below 4GB, 0x100000-0xXXXXXXXX */
+    for (i = 0; i < e820_nr; i++)
+    {
+        if (e820[i].type == E820_RAM && e820[i].addr == 0x00100000)
+        {
+            pmm_init_heap(&pmm_data.ext_heap, e820[i].addr, 
+                          e820[i].addr + e820[i].size);
+            break;
+        }
+    }
+
+    /* convectional memory: RAM below 1MB, 0x10000-0x7FFFF */
+    pmm_init_heap(&pmm_data.heap, SCRATCH_PHYSICAL_ADDRESS,
+                  HYPERCALL_PHYSICAL_ADDRESS);
+}
+
+static uint32_t
+pmm_max_avail_length(heap_t *heap)
+{
+    chunk_t *cp;
+    uint32_t size, max = 0;
+
+    for_each_chunk(heap, cp)
+    {
+        if (chunk_is_avail(cp))
+        {
+            join_available_chunks(heap, cp);
+            size = chunk_bufsize(cp);
+            if (size > max)
+                max = size;
+        }
+    }
+    return (max / PARAGRAPH_LENGTH);
+}
+
+static chunk_t *
+first_fit(heap_t *heap, uint32_t size, uint32_t handle, uint32_t flags)
+{
+    chunk_t *cp;
+    int32_t align = 0;
+
+    if (flags & PMM_FLAGS_ALIGINMENT)
+        align = ((size ^ (size - 1)) >> 1) + 1;
+
+    for_each_chunk(heap, cp)
+    {
+        if (chunk_is_avail(cp))
+        {
+            join_available_chunks(heap, cp);
+
+            if (align)
+            {
+                uint32_t addr = chunk_buffer(cp);
+                uint32_t offset = ALIGN_UP(addr, align) - addr;
+
+                if (offset > 0)
+                {
+                    ASSERT(offset >= CHUNK_HEADER_SIZE, continue);
+
+                    if (offset + size > chunk_bufsize(cp))
+                        continue;
+
+                    cp = split_chunk(cp, offset - CHUNK_HEADER_SIZE);
+                    return cp;
+                }
+            }
+
+            if (size <= chunk_bufsize(cp))
+                return cp;
+        }
+        else
+        {
+            ASSERT(chunk_is_inuse(cp), return NULL);
+
+            /* duplication check for handle */
+            if (handle != PMM_HANDLE_ANONYMOUS && cp->handle == handle)
+                return NULL;
+        }
+    }
+
+    return NULL;
+}
+
+static chunk_t *
+pmm_find_handle(heap_t *heap, uint32_t handle)
+{
+    chunk_t *cp;
+
+    if (handle == PMM_HANDLE_ANONYMOUS)
+        return NULL;
+
+    for_each_chunk(heap, cp)
+        if (cp->handle == handle)
+            return cp;
+    return NULL;
+}
+
+static uint32_t
+pmm_alloc_heap(heap_t *heap, uint32_t length, uint32_t handle, uint32_t flags)
+{
+    chunk_t *cp;
+    uint32_t size;
+
+    /* return the largest memory block available */
+    if (length == 0)
+        return pmm_max_avail_length(heap);
+
+    size = length * PARAGRAPH_LENGTH;
+    cp = first_fit(heap, size, handle, flags);
+
+    if (cp == NULL)
+        return PMM_ENOMEM;
+
+    /* duplication check for handle */
+    if (handle != PMM_HANDLE_ANONYMOUS)
+    {
+        chunk_t *np = cp->next;
+
+        for_remain_chunk(heap, np)
+            if (np->handle == handle)
+                return PMM_ENOMEM;
+    }
+
+    split_chunk(cp, size);
+
+    cp->handle = handle;
+    set_inuse(cp);
+
+    return chunk_buffer(cp);
+}
+
+static uint32_t
+pmm_allocate(uint32_t length, uint32_t handle, uint16_t flags)
+{
+    switch(flags & PMM_FLAGS_MEMORY_TYPE_MASK)
+    {
+    case PMM_FLAGS_MEMORY_CONVENTIONAL:
+        /* duplication check for handle */
+        if (pmm_find_handle(&pmm_data.ext_heap, handle))
+            return PMM_ENOMEM;
+        return pmm_alloc_heap(&pmm_data.heap, length, handle, flags);
+
+    case PMM_FLAGS_MEMORY_EXTENDED:
+    case PMM_FLAGS_MEMORY_ANY: // XXX: ignore conventional memory for now
+        /* duplication check for handle */
+        if (pmm_find_handle(&pmm_data.heap, handle))
+            return PMM_ENOMEM;
+        return pmm_alloc_heap(&pmm_data.ext_heap, length, handle, flags);
+    }
+    return PMM_EINVAL;
+}
+
+static uint32_t
+pmm_find(uint32_t handle)
+{
+    chunk_t *cp;
+
+    if (handle == PMM_HANDLE_ANONYMOUS)
+        return 0;
+
+    cp = pmm_find_handle(&pmm_data.heap, handle);
+    if (cp != NULL)
+        return chunk_buffer(cp);
+    cp = pmm_find_handle(&pmm_data.ext_heap, handle);
+    if (cp != NULL)
+        return chunk_buffer(cp);
+    return 0;
+}
+
+static uint32_t
+pmm_dealloc(uint32_t buffer)
+{
+    chunk_t *cp = buffer_chunk(buffer);
+
+    if (!chunk_is_inuse(cp))
+        return PMM_EINVAL;
+
+    set_avail(cp);
+    cp->handle = PMM_HANDLE_ANONYMOUS;
+    return 0;
+}
+
+
+struct pmm_args {
+    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;  // saved registers
+    uint16_t flags; // saved flags
+    uint16_t ip, cs; // return address
+
+    union {
+        uint16_t function;
+        struct pmmAllocArgs alloc;
+        struct pmmFindArgs find;
+        struct pmmDeallocArgs dealloc;
+    };
+} __attribute__ ((packed));
+
+void
+pmm(struct pmm_args a)
+{
+    uint32_t ret = PMM_EINVAL;
+
+    if (pmm_data.heap.head == HEAP_NOT_INITIALIZED)
+        pmm_initalize();
+
+    switch(a.function) {
+    case PMM_FUNCTION_ALLOCATE:
+        ret = pmm_allocate(a.alloc.length, a.alloc.handle, a.alloc.flags);
+        PMM_DEBUG("Alloc length=%x handle=%x flags=%x ret=%x\n", 
+               a.alloc.length, a.alloc.handle, a.alloc.flags, ret);
+        break;
+
+    case PMM_FUNCTION_FIND:
+        ret = pmm_find(a.find.handle);
+        PMM_DEBUG("Find handle=%x ret=%x\n", a.find.handle, ret);
+        break;
+
+    case PMM_FUNCTION_DEALLOC:
+        ret = pmm_dealloc(a.dealloc.buffer);
+        PMM_DEBUG("Dealloc buffer=%x ret=%x\n", a.dealloc.buffer, ret);
+        break;
+
+    default:
+        PMM_DEBUG("Invalid function:%d\n", a.function);
+    }
+
+    *(uint16_t *)&a.edx = ret >> 16;
+    *(uint16_t *)&a.eax = ret;
+}
+
+#ifdef TEST_STANDALONE
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+static void
+dump_chunk(heap_t *heap)
+{
+    chunk_t *cp;
+
+    printf("chunk");
+    for_each_chunk(heap, cp)
+    {
+        if (chunk_is_inuse(cp))
+            printf(" *%x", (uint32_t)cp);
+        else
+            printf(" %x", (uint32_t)cp);
+    }
+    printf(" <%x\n", (uint32_t)cp);
+}
+
+#define TEST_HEAP_SIZE  0x10000
+#define MAX_ALLOC_NR    1000
+
+static void
+pmm_test_initialize(void)
+{
+    int fd;
+
+    fd = open("/dev/zero", O_RDWR);
+
+    mmap((void *)0x20000000, TEST_HEAP_SIZE,
+         PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+    pmm_init_heap(&pmm_data.heap, 0x20000000, 0x20000000 + TEST_HEAP_SIZE);
+    close(fd);
+}
+
+static uint32_t
+random_alloc(void)
+{
+    int size, flags;
+    uint32_t ret;
+
+    size = 1 << (rand() % 6);
+    flags = PMM_FLAGS_MEMORY_CONVENTIONAL|(rand() & PMM_FLAGS_ALIGINMENT);
+    ret = pmm_allocate(size, PMM_HANDLE_ANONYMOUS, flags);
+    if (ret)
+    {
+        if (chunk_bufsize(buffer_chunk(ret)) < size)
+            printf("size small!\n");
+        if ((flags & PMM_FLAGS_ALIGINMENT) && (ret & (size - 1)))
+            printf("NOT aligned!\n");
+        memset((void *)ret, rand(), size);
+    }
+    return ret;
+}
+
+static void
+test(void)
+{
+    uint32_t a[MAX_ALLOC_NR], tmp;
+    int i, j, k;
+    uint32_t first_len = pmm_allocate(0, 0, PMM_FLAGS_MEMORY_CONVENTIONAL);
+    static uint32_t count;
+
+    memset(a, 0, sizeof(a));
+
+    for (k = 0; k < 1000; k++)
+    {
+        j = rand() % MAX_ALLOC_NR;
+        for (i = 0; i < j; i++)
+            if (a[i] == 0)
+                a[i] = random_alloc();
+        for (i = 0; i < MAX_ALLOC_NR; i++)
+        {
+            j = rand() % MAX_ALLOC_NR;
+            tmp = a[i]; a[i] = a[j]; a[j] = tmp;
+        }
+        j = rand() % MAX_ALLOC_NR;
+        for (i = 0; i < j; i++)
+            if (a[i])
+            {
+                pmm_dealloc(a[i]);
+                a[i] = 0;
+            }
+    }
+
+    for (i = 0; i < MAX_ALLOC_NR; i++)
+        if (a[i])
+        {
+            pmm_dealloc(a[i]);
+            a[i] = 0;
+        }
+
+    if (first_len != pmm_allocate(0, 0, PMM_FLAGS_MEMORY_CONVENTIONAL))
+        printf("TEST fail!!!\n");
+    else
+        printf("ok %d\n", ++count);
+    dump_chunk(&pmm_data.heap);
+}
+
+int
+main(int argc, char **argv)
+{
+    pmm_test_initialize();
+
+    while(1)
+        test();
+}
+
+#endif
diff -r af1d9af1a993 tools/firmware/rombios/32bitprotos.h
--- a/tools/firmware/rombios/32bitprotos.h      Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/rombios/32bitprotos.h      Thu Jan 22 19:51:24 2009 +0900
@@ -18,7 +18,8 @@
 #define IDX_TCPA_INITIALIZE_TPM            11
 #define IDX_TCPA_MEASURE_POST              12
 #define IDX_GET_S3_WAKING_VECTOR           13
-#define IDX_LAST                           14 /* keep last! */
+#define IDX_PMM                            14
+#define IDX_LAST                           15 /* keep last! */
 
 #ifdef GCC_PROTOS
   #define PARMS(x...) x
@@ -44,4 +45,6 @@
 
 Bit32u get_s3_waking_vector( PARMS(void) );
 
+void pmm( PARMS(pushad_regs_t *regs, ...) );
+
 #endif
diff -r af1d9af1a993 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Wed Jan 21 14:44:43 2009 +0000
+++ b/tools/firmware/rombios/rombios.c  Thu Jan 22 19:51:24 2009 +0900
@@ -11631,6 +11631,17 @@
   HALT(__LINE__)
   iret
 
+.org PMM_ENTRY_POINT
+pmm_entry_point:
+  pushf
+  pushad
+  call pmm_upcall
+  popad
+  popf
+  db 0xcb ;; lret
+pmm_upcall:
+  DoUpcall(IDX_PMM)
+
 #ifdef HVMTEST
 .org 0xffe0
   jmp 0xf000:post;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>