qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Blue Swirl" <blauwirbel@gmail.com>
To: Paul Brook <paul@codesourcery.com>
Cc: "J. Mayer" <l_indien@magic.fr>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] qemu/hw pckbd.c
Date: Thu, 19 Apr 2007 21:15:30 +0300	[thread overview]
Message-ID: <f43fc5580704191115r3f770995x428da0857d534c37@mail.gmail.com> (raw)
In-Reply-To: <200704191544.45984.paul@codesourcery.com>

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

Ok, try this patch. It doesn't handle cases where the sub-page areas
are something else than IO. Though I don't know if it handles any
other cases for that matter, but at least Sparc32 may work. :-)

[-- Attachment #2: subpage_io.diff --]
[-- Type: text/x-patch, Size: 7594 bytes --]

Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c	2007-04-19 18:07:26.000000000 +0000
+++ qemu/exec.c	2007-04-19 18:07:28.000000000 +0000
@@ -155,6 +155,14 @@
 static int tb_flush_count;
 static int tb_phys_invalidate_count;
 
+#define SUBPAGE_IDX(addr) ((addr) & (TARGET_PAGE_BITS - 1))
+typedef struct subpage_t {
+    target_phys_addr_t base;
+    CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE];
+    CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE];
+    void *opaque[TARGET_PAGE_SIZE];
+} subpage_t;
+
 static void page_init(void)
 {
     /* NOTE: we can always suppose that qemu_host_page_size >=
@@ -1896,6 +1904,10 @@
 }
 #endif /* defined(CONFIG_USER_ONLY) */
 
+static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
+                             int memory);
+static void *subpage_init (target_phys_addr_t base, uint32_t *phys);
+
 /* register physical memory. 'size' must be a multiple of the target
    page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
    io memory page */
@@ -1906,15 +1918,39 @@
     target_phys_addr_t addr, end_addr;
     PhysPageDesc *p;
     CPUState *env;
+    unsigned long orig_size = size;
+    void *subpage;
 
     size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + size;
     for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
-        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
-        p->phys_offset = phys_offset;
-        if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
-            (phys_offset & IO_MEM_ROMD))
-            phys_offset += TARGET_PAGE_SIZE;
+        p = phys_page_find(addr >> TARGET_PAGE_BITS);
+        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
+            unsigned long orig_memory = p->phys_offset;
+            target_phys_addr_t start_addr2, end_addr2;
+
+            if (addr > start_addr)
+                start_addr2 = 0;
+            else
+                start_addr2 = start_addr & ~TARGET_PAGE_MASK;
+
+            if (end_addr - addr > TARGET_PAGE_SIZE)
+                end_addr2 = TARGET_PAGE_SIZE - 1;
+            else
+                end_addr2 = start_addr + orig_size - addr;
+
+            if (!(orig_memory & IO_MEM_SUBPAGE)) {
+                subpage = subpage_init(addr, &p->phys_offset);
+                subpage_register(subpage, 0, TARGET_PAGE_SIZE, orig_memory);
+            }
+            subpage_register(io_mem_opaque[orig_memory], start_addr2, end_addr2, phys_offset);
+        } else {
+            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
+            p->phys_offset = phys_offset;
+            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
+                (phys_offset & IO_MEM_ROMD))
+                phys_offset += TARGET_PAGE_SIZE;
+        }
     }
     
     /* since each CPU stores ram addresses in its TLB cache, we must
@@ -2150,6 +2186,146 @@
 };
 #endif
 
+static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
+                                 unsigned int len)
+{
+    CPUReadMemoryFunc **mem_read;
+    uint32_t ret;
+    unsigned int idx;
+
+    idx = SUBPAGE_IDX(addr - mmio->base);
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: subpage %p len %d addr " PADDRX " idx %d\n", __func__,
+           mmio, len, addr, idx);
+#endif
+    mem_read = mmio->mem_read[idx];
+    ret = (*mem_read[len])(mmio->opaque[idx], addr);
+
+    return ret;
+}
+
+static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
+                              uint32_t value, unsigned int len)
+{
+    CPUWriteMemoryFunc **mem_write;
+    unsigned int idx;
+
+    idx = SUBPAGE_IDX(addr - mmio->base);
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: subpage %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
+           mmio, len, addr, idx, value);
+#endif
+    mem_write = mmio->mem_write[idx];
+    (*mem_write[len])(mmio->opaque[idx], addr, value);
+}
+
+static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return subpage_readlen(opaque, addr, 0);
+}
+
+static void subpage_writeb (void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    subpage_writelen(opaque, addr, value, 0);
+}
+
+static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return subpage_readlen(opaque, addr, 1);
+}
+
+static void subpage_writew (void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    subpage_writelen(opaque, addr, value, 1);
+}
+
+static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return subpage_readlen(opaque, addr, 2);
+}
+
+static void subpage_writel (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    subpage_writelen(opaque, addr, value, 2);
+}
+
+static CPUReadMemoryFunc *subpage_read[] = {
+    &subpage_readb,
+    &subpage_readw,
+    &subpage_readl,
+};
+
+static CPUWriteMemoryFunc *subpage_write[] = {
+    &subpage_writeb,
+    &subpage_writew,
+    &subpage_writel,
+};
+
+static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
+                             int memory)
+{
+    int idx, eidx;
+
+    if (start > TARGET_PAGE_SIZE || end > TARGET_PAGE_SIZE)
+        return -1;
+    idx = SUBPAGE_IDX(start);
+    eidx = SUBPAGE_IDX(end);
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
+           end, idx, eidx);
+#endif
+    for (; idx <= eidx; idx++) {
+        mmio->mem_read[idx] = io_mem_read[memory];
+        mmio->mem_write[idx] = io_mem_write[memory];
+        mmio->opaque[idx] = io_mem_opaque[memory];
+    }
+
+    return 0;
+}
+
+static void *subpage_init (target_phys_addr_t base, uint32_t *phys)
+{
+    subpage_t *mmio;
+    int subpage_memory;
+
+    mmio = qemu_mallocz(sizeof(subpage_t));
+    if (mmio != NULL) {
+        mmio->base = base;
+        subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
+#if defined(DEBUG_SUBPAGE)
+        printf("%s: %p base %08x len %08x %d\n", __func__,
+               mmio, base, TARGET_PAGE_SIZE, subpage_memory);
+#endif
+        *phys = subpage_memory | IO_MEM_SUBPAGE;
+    }
+
+    return mmio;
+}
+
 static void io_mem_init(void)
 {
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
Index: qemu/cpu-all.h
===================================================================
--- qemu.orig/cpu-all.h	2007-04-19 18:07:26.000000000 +0000
+++ qemu/cpu-all.h	2007-04-19 18:07:28.000000000 +0000
@@ -857,6 +857,7 @@
    exception, the write memory callback gets the ram offset instead of
    the physical address */
 #define IO_MEM_ROMD        (1)
+#define IO_MEM_SUBPAGE     (2)
 
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);

  reply	other threads:[~2007-04-19 18:20 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-16 22:47 [Qemu-devel] qemu/hw pckbd.c Thiemo Seufer
2007-04-18  9:29 ` J. Mayer
2007-04-18 13:06   ` Thiemo Seufer
2007-04-18 14:20     ` Jocelyn Mayer
2007-04-18 15:37       ` Blue Swirl
2007-04-18 16:08         ` Paul Brook
2007-04-19  8:43           ` J. Mayer
2007-04-19 14:44             ` Paul Brook
2007-04-19 18:15               ` Blue Swirl [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-02-10 13:39 Andrzej Zaborowski
2007-10-20 20:48 Thiemo Seufer
2007-02-18  0:08 Thiemo Seufer
2005-01-27 22:32 Fabrice Bellard
2005-01-17 22:31 Fabrice Bellard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f43fc5580704191115r3f770995x428da0857d534c37@mail.gmail.com \
    --to=blauwirbel@gmail.com \
    --cc=l_indien@magic.fr \
    --cc=paul@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).