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);
next prev parent 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).