* [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 @ 2011-07-23 19:17 Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions Richard Henderson ` (6 more replies) 0 siblings, 7 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel Changes v6->v7 * Rebase against master, which now includes 2 patches from v6. The tree is available at git://repo.or.cz/qemu/rth.git axp-system-5 Please pull, review, or something. r~ Richard Henderson (7): Export the unassigned_mem read/write functions. pci: Export pci_to_cpu_addr. target-alpha: Add custom PALcode image for CLIPPER emulation. target-alpha: Add CLIPPER emulation. target-alpha: Implement WAIT IPR. target-alpha: Implement HALT IPR. target-alpha: Add high-resolution access to wall clock and an alarm. .gitmodules | 3 + Makefile | 3 +- Makefile.target | 1 + configure | 8 +- cpu-common.h | 7 + default-configs/alpha-softmmu.mak | 2 + exec.c | 12 +- hw/alpha_dp264.c | 188 +++++++++ hw/alpha_pci.c | 358 +++++++++++++++++ hw/alpha_sys.h | 44 ++ hw/alpha_typhoon.c | 799 +++++++++++++++++++++++++++++++++++++ hw/pci.c | 3 +- hw/pci.h | 1 + pc-bios/README | 3 + pc-bios/palcode-clipper | Bin 0 -> 185703 bytes roms/qemu-palcode | 1 + target-alpha/cpu.h | 4 + target-alpha/helper.h | 5 + target-alpha/op_helper.c | 25 ++ target-alpha/translate.c | 50 ++- 20 files changed, 1497 insertions(+), 20 deletions(-) create mode 100644 hw/alpha_dp264.c create mode 100644 hw/alpha_pci.c create mode 100644 hw/alpha_sys.h create mode 100644 hw/alpha_typhoon.c create mode 100755 pc-bios/palcode-clipper create mode 160000 roms/qemu-palcode -- 1.7.4.4 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-24 13:28 ` Anthony Liguori 2011-07-23 19:17 ` [Qemu-devel] [PATCH 2/7] pci: Export pci_to_cpu_addr Richard Henderson ` (5 subsequent siblings) 6 siblings, 1 reply; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel Signed-off-by: Richard Henderson <rth@twiddle.net> --- cpu-common.h | 7 +++++++ exec.c | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 44b04b3..78e1bad 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -56,6 +56,13 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0); } +extern CPUReadMemoryFunc unassigned_mem_readb; +extern CPUReadMemoryFunc unassigned_mem_readw; +extern CPUReadMemoryFunc unassigned_mem_readl; +extern CPUWriteMemoryFunc unassigned_mem_writeb; +extern CPUWriteMemoryFunc unassigned_mem_writew; +extern CPUWriteMemoryFunc unassigned_mem_writel; + ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr); ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, ram_addr_t size, void *host); diff --git a/exec.c b/exec.c index 2160ded..c00badd 100644 --- a/exec.c +++ b/exec.c @@ -3232,7 +3232,7 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) return ram_addr; } -static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) +uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); @@ -3243,7 +3243,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) +uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); @@ -3254,7 +3254,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) return 0; } -static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) +uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); @@ -3265,7 +3265,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) return 0; } -static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); @@ -3275,7 +3275,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_ #endif } -static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); @@ -3285,7 +3285,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_ #endif } -static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-23 19:17 ` [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions Richard Henderson @ 2011-07-24 13:28 ` Anthony Liguori 2011-07-24 16:42 ` Richard Henderson 0 siblings, 1 reply; 17+ messages in thread From: Anthony Liguori @ 2011-07-24 13:28 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel On 07/23/2011 02:17 PM, Richard Henderson wrote: > Signed-off-by: Richard Henderson<rth@twiddle.net> Why? Regards, Anthony Liguori > --- > cpu-common.h | 7 +++++++ > exec.c | 12 ++++++------ > 2 files changed, 13 insertions(+), 6 deletions(-) > > diff --git a/cpu-common.h b/cpu-common.h > index 44b04b3..78e1bad 100644 > --- a/cpu-common.h > +++ b/cpu-common.h > @@ -56,6 +56,13 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, > cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0); > } > > +extern CPUReadMemoryFunc unassigned_mem_readb; > +extern CPUReadMemoryFunc unassigned_mem_readw; > +extern CPUReadMemoryFunc unassigned_mem_readl; > +extern CPUWriteMemoryFunc unassigned_mem_writeb; > +extern CPUWriteMemoryFunc unassigned_mem_writew; > +extern CPUWriteMemoryFunc unassigned_mem_writel; > + > ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr); > ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, > ram_addr_t size, void *host); > diff --git a/exec.c b/exec.c > index 2160ded..c00badd 100644 > --- a/exec.c > +++ b/exec.c > @@ -3232,7 +3232,7 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) > return ram_addr; > } > > -static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) > +uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); > @@ -3243,7 +3243,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) > return 0; > } > > -static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) > +uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); > @@ -3254,7 +3254,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) > return 0; > } > > -static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) > +uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); > @@ -3265,7 +3265,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) > return 0; > } > > -static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) > +void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); > @@ -3275,7 +3275,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_ > #endif > } > > -static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) > +void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); > @@ -3285,7 +3285,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_ > #endif > } > > -static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) > +void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) > { > #ifdef DEBUG_UNASSIGNED > printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-24 13:28 ` Anthony Liguori @ 2011-07-24 16:42 ` Richard Henderson 2011-07-24 18:56 ` Anthony Liguori 0 siblings, 1 reply; 17+ messages in thread From: Richard Henderson @ 2011-07-24 16:42 UTC (permalink / raw) To: Anthony Liguori; +Cc: qemu-devel On 07/24/2011 06:28 AM, Anthony Liguori wrote: > On 07/23/2011 02:17 PM, Richard Henderson wrote: >> Signed-off-by: Richard Henderson<rth@twiddle.net> > > Why? So that I can write i/o functions like this: switch (addr) { case 0: ... case 64: ... case 128: ... ... default: unassigned_mem_readl(...) } Perhaps Avi's rewrite makes this unnecessary; I browsed through his patch set but didn't immediately see if there's a way for the i/o function to return "failure". What I certainly don't want to do is write this with 100 tiny functions registering 8 bytes each, registered some tiny distance away from each other. r~ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-24 16:42 ` Richard Henderson @ 2011-07-24 18:56 ` Anthony Liguori 2011-07-24 19:00 ` Richard Henderson 2011-08-04 23:58 ` Edgar E. Iglesias 0 siblings, 2 replies; 17+ messages in thread From: Anthony Liguori @ 2011-07-24 18:56 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel On 07/24/2011 11:42 AM, Richard Henderson wrote: > On 07/24/2011 06:28 AM, Anthony Liguori wrote: >> On 07/23/2011 02:17 PM, Richard Henderson wrote: >>> Signed-off-by: Richard Henderson<rth@twiddle.net> >> >> Why? > > So that I can write i/o functions like this: > > switch (addr) { > case 0: ... > case 64: ... > case 128: ... > ... > default: > unassigned_mem_readl(...) > } > > Perhaps Avi's rewrite makes this unnecessary; I browsed through > his patch set but didn't immediately see if there's a way for > the i/o function to return "failure". What is returned by totally unregistered MMIO is defined by the chipset. What's returned by an empty space in the MMIO space of a device is device specific. What does your device return if there's an access at 32? Regards, Anthony Liguori > > What I certainly don't want to do is write this with 100 tiny > functions registering 8 bytes each, registered some tiny > distance away from each other. > > > r~ > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-24 18:56 ` Anthony Liguori @ 2011-07-24 19:00 ` Richard Henderson 2011-07-25 1:47 ` Anthony Liguori 2011-08-04 23:58 ` Edgar E. Iglesias 1 sibling, 1 reply; 17+ messages in thread From: Richard Henderson @ 2011-07-24 19:00 UTC (permalink / raw) To: Anthony Liguori; +Cc: qemu-devel On 07/24/2011 11:56 AM, Anthony Liguori wrote: > What is returned by totally unregistered MMIO is defined by the > chipset. What's returned by an empty space in the MMIO space of a > device is device specific. It's one and the same here, it's the chipset I'm implementing. > What does your device return if there's an access at 32? A machine check. r~ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-24 19:00 ` Richard Henderson @ 2011-07-25 1:47 ` Anthony Liguori 2011-07-25 2:14 ` Richard Henderson 0 siblings, 1 reply; 17+ messages in thread From: Anthony Liguori @ 2011-07-25 1:47 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel On 07/24/2011 02:00 PM, Richard Henderson wrote: > On 07/24/2011 11:56 AM, Anthony Liguori wrote: >> What is returned by totally unregistered MMIO is defined by the >> chipset. What's returned by an empty space in the MMIO space of a >> device is device specific. > > It's one and the same here, it's the chipset I'm implementing. Sorry if its obvious, which patch in the series actually uses this? Regards, Anthony Liguori >> What does your device return if there's an access at 32? > > A machine check. > > > r~ > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-25 1:47 ` Anthony Liguori @ 2011-07-25 2:14 ` Richard Henderson 0 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-25 2:14 UTC (permalink / raw) To: Anthony Liguori; +Cc: qemu-devel On 07/24/2011 06:47 PM, Anthony Liguori wrote: > On 07/24/2011 02:00 PM, Richard Henderson wrote: >> On 07/24/2011 11:56 AM, Anthony Liguori wrote: >>> What is returned by totally unregistered MMIO is defined by the >>> chipset. What's returned by an empty space in the MMIO space of a >>> device is device specific. >> >> It's one and the same here, it's the chipset I'm implementing. > > Sorry if its obvious, which patch in the series actually uses this? 4/7, see hw/alpha_typhoon.c. r~ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-07-24 18:56 ` Anthony Liguori 2011-07-24 19:00 ` Richard Henderson @ 2011-08-04 23:58 ` Edgar E. Iglesias 2011-08-05 15:39 ` Richard Henderson 1 sibling, 1 reply; 17+ messages in thread From: Edgar E. Iglesias @ 2011-08-04 23:58 UTC (permalink / raw) To: Anthony Liguori; +Cc: Avi Kivity, qemu-devel, Richard Henderson On Sun, Jul 24, 2011 at 01:56:00PM -0500, Anthony Liguori wrote: > On 07/24/2011 11:42 AM, Richard Henderson wrote: > >On 07/24/2011 06:28 AM, Anthony Liguori wrote: > >>On 07/23/2011 02:17 PM, Richard Henderson wrote: > >>>Signed-off-by: Richard Henderson<rth@twiddle.net> > >> > >>Why? > > > >So that I can write i/o functions like this: > > > > switch (addr) { > > case 0: ... > > case 64: ... > > case 128: ... > > ... > > default: > > unassigned_mem_readl(...) > > } > > > >Perhaps Avi's rewrite makes this unnecessary; I browsed through > >his patch set but didn't immediately see if there's a way for > >the i/o function to return "failure". > > What is returned by totally unregistered MMIO is defined by the > chipset. What's returned by an empty space in the MMIO space of a > device is device specific. Not really, IMO. Im not going to say that HW does it this way or another because different HW may do it different ways, but from my experience this how most HW generally works: Accesses to unmapped addresses are decoded, routed and finally handled by the first node that realizes that the addr is unmapped. The action might be to ignore or to signal some kind of error. AFAIK, most systems will signal the error by sending an error back to the CPU via dedicated control signals or by raising interrupts (the latter is very uncommon). The common case is to signal an error via ctrl signals on the bus that go back to the CPU and the final decision on what to do is made by the CPU. QEMU currently doesnt model ctrl lines for bus accesses so entering a per CPU xxx_unassigned_acceess function is pretty much in line with most HW. QEMU only models the data lanes so I think Richards patch is quite OK because it brings the decission back to the CPU model. I would prefer though, if the new Memory API would let devices pass ctrl data back to the CPU in addition to the data lanes. That would probably involve quite a bit of work though. CC:ing Avi, you might have more input on this. Cheers ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions. 2011-08-04 23:58 ` Edgar E. Iglesias @ 2011-08-05 15:39 ` Richard Henderson 0 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-08-05 15:39 UTC (permalink / raw) To: Edgar E. Iglesias; +Cc: Avi Kivity, qemu-devel On 08/04/2011 04:58 PM, Edgar E. Iglesias wrote: > QEMU only models the data lanes so I think Richards patch is quite OK > because it brings the decission back to the CPU model. > > I would prefer though, if the new Memory API would let devices pass > ctrl data back to the CPU in addition to the data lanes. That would > probably involve quite a bit of work though. CC:ing Avi, you might > have more input on this. Amusingly, after having updated my system to Avi's tree, I find I don't need the unassigned_mem_read[bwl] helpers anymore, but only the cpu_unassigned_access function, which is already exported. It would be nice if the new api allowed signaling of errors, but I can't think of a really nice way of doing that. r~ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 2/7] pci: Export pci_to_cpu_addr. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 3/7] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson ` (4 subsequent siblings) 6 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel This is, more or less, the read accessor to pci_bus_set_mem_base as a write accessor. It will be needed for implementing sparse memory spaces for Alpha. Signed-off-by: Richard Henderson <rth@twiddle.net> --- hw/pci.c | 3 +-- hw/pci.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index b904a4e..68e18d3 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -820,8 +820,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, return pci_dev; } -static target_phys_addr_t pci_to_cpu_addr(PCIBus *bus, - target_phys_addr_t addr) +target_phys_addr_t pci_to_cpu_addr(PCIBus *bus, target_phys_addr_t addr) { return addr + bus->mem_base; } diff --git a/hw/pci.h b/hw/pci.h index c220745..458be00 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -246,6 +246,7 @@ void pci_device_reset(PCIDevice *dev); void pci_bus_reset(PCIBus *bus); void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base); +target_phys_addr_t pci_to_cpu_addr(PCIBus *bus, target_phys_addr_t addr); PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, const char *default_devaddr); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 3/7] target-alpha: Add custom PALcode image for CLIPPER emulation. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 2/7] pci: Export pci_to_cpu_addr Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 4/7] target-alpha: Add " Richard Henderson ` (3 subsequent siblings) 6 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel Signed-off-by: Richard Henderson <rth@twiddle.net> --- .gitmodules | 3 +++ Makefile | 3 ++- configure | 8 +++++++- pc-bios/README | 3 +++ pc-bios/palcode-clipper | Bin 0 -> 185703 bytes roms/qemu-palcode | 1 + 6 files changed, 16 insertions(+), 2 deletions(-) create mode 100755 pc-bios/palcode-clipper create mode 160000 roms/qemu-palcode diff --git a/.gitmodules b/.gitmodules index 7884471..528743d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "roms/ipxe"] path = roms/ipxe url = git://git.qemu.org/ipxe.git +[submodule "roms/qemu-palcode"] + path = roms/qemu-palcode + url = git://repo.or.cz/qemu-palcode.git diff --git a/Makefile b/Makefile index f3a03ad..310608b 100644 --- a/Makefile +++ b/Makefile @@ -243,7 +243,8 @@ bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ mpc8544ds.dtb \ multiboot.bin linuxboot.bin \ s390-zipl.rom \ -spapr-rtas.bin slof.bin +spapr-rtas.bin slof.bin \ +palcode-sx164 else BLOBS= endif diff --git a/configure b/configure index 6911c3b..6a8a4c8 100755 --- a/configure +++ b/configure @@ -3522,7 +3522,13 @@ FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit" FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" FILES="$FILES pc-bios/spapr-rtas/Makefile" FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile" -for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do +for bios_file in \ + $source_path/pc-bios/*.bin \ + $source_path/pc-bios/*.rom \ + $source_path/pc-bios/*.dtb \ + $source_path/pc-bios/openbios-* \ + $source_path/pc-bios/palcode-* +do FILES="$FILES pc-bios/`basename $bios_file`" done mkdir -p $DIRS diff --git a/pc-bios/README b/pc-bios/README index f74b246..861227a 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -32,3 +32,6 @@ - The S390 zipl loader is an addition to the official IBM s390-tools package. That fork is maintained in its own git repository at: git://repo.or.cz/s390-tools.git + +- The Alpha palcode image is available from: + git://repo.or.cz/qemu-palcode.git diff --git a/pc-bios/palcode-clipper b/pc-bios/palcode-clipper new file mode 100755 index 0000000000000000000000000000000000000000..a92372c107af72071e265e1ca94b9ae5573bd317 GIT binary patch literal 185703 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 literal 0 HcmV?d00001 diff --git a/roms/qemu-palcode b/roms/qemu-palcode new file mode 160000 index 0000000..7abb12f --- /dev/null +++ b/roms/qemu-palcode @@ -0,0 +1 @@ +Subproject commit 7abb12f60eb3069019e9497e193733d77d8f0722 -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 4/7] target-alpha: Add CLIPPER emulation. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson ` (2 preceding siblings ...) 2011-07-23 19:17 ` [Qemu-devel] [PATCH 3/7] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR Richard Henderson ` (2 subsequent siblings) 6 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel This is a DP264 variant, SMP capable, no unusual hardware present. The emulation does not currently include any PCI IOMMU code. Hopefully the generic support for that can be merged to HEAD soon. Signed-off-by: Richard Henderson <rth@twiddle.net> --- Makefile.target | 1 + default-configs/alpha-softmmu.mak | 2 + hw/alpha_dp264.c | 188 +++++++++ hw/alpha_pci.c | 358 +++++++++++++++++ hw/alpha_sys.h | 44 ++ hw/alpha_typhoon.c | 781 +++++++++++++++++++++++++++++++++++++ 6 files changed, 1374 insertions(+), 0 deletions(-) create mode 100644 hw/alpha_dp264.c create mode 100644 hw/alpha_pci.c create mode 100644 hw/alpha_sys.h create mode 100644 hw/alpha_typhoon.c diff --git a/Makefile.target b/Makefile.target index cde509b..08fb2ec 100644 --- a/Makefile.target +++ b/Makefile.target @@ -371,6 +371,7 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o obj-alpha-y = i8259.o mc146818rtc.o obj-alpha-y += vga.o cirrus_vga.o +obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak index abadcff..be86d0c 100644 --- a/default-configs/alpha-softmmu.mak +++ b/default-configs/alpha-softmmu.mak @@ -3,7 +3,9 @@ include pci.mak CONFIG_SERIAL=y CONFIG_I8254=y +CONFIG_PCKBD=y CONFIG_VGA_PCI=y CONFIG_IDE_CORE=y CONFIG_IDE_QDEV=y CONFIG_VMWARE_VGA=y +CONFIG_IDE_CMD646=y diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c new file mode 100644 index 0000000..6fdfabe --- /dev/null +++ b/hw/alpha_dp264.c @@ -0,0 +1,188 @@ +/* + * QEMU Alpha DP264/CLIPPER hardware system emulator. + * + * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK + * variants because CLIPPER doesn't have an SMC669 SuperIO controler + * that we need to emulate as well. + */ + +#include "hw.h" +#include "elf.h" +#include "loader.h" +#include "boards.h" +#include "alpha_sys.h" +#include "sysemu.h" +#include "mc146818rtc.h" +#include "ide.h" + +#define MAX_IDE_BUS 2 + +static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) +{ + if (((addr >> 41) & 3) == 2) { + addr &= 0xffffffffffull; + } + return addr; +} + +/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. + (0) The dev_irq_n lines into the cpu, which we totally ignore, + (1) The DRIR lines in the typhoon chipset, + (2) The "vector" aka mangled interrupt number reported by SRM PALcode, + (3) The interrupt number assigned by the kernel. + The following function is concerned with (1) only. */ + +static int clipper_pci_map_irq(PCIDevice *d, int irq_num) +{ + int slot = d->devfn >> 3; + + assert(irq_num >= 0 && irq_num <= 3); + + return (slot + 1) * 4 + irq_num; +} + +static void clipper_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + CPUState *cpus[4]; + ram_addr_t ram_offset; + PCIBus *pci_bus; + qemu_irq isa_pci_irq, rtc_irq, *isa_irqs; + long size, i; + const char *palcode_filename; + uint64_t palcode_entry, palcode_low, palcode_high; + uint64_t kernel_entry, kernel_low, kernel_high; + + /* Create up to 4 cpus. */ + memset(cpus, 0, sizeof(cpus)); + for (i = 0; i < smp_cpus; ++i) { + cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67"); + } + + cpus[0]->trap_arg0 = ram_size; + cpus[0]->trap_arg1 = 0; + cpus[0]->trap_arg2 = smp_cpus; + + ram_offset = qemu_ram_alloc(NULL, "ram", ram_size); + cpu_register_physical_memory(0, ram_size, ram_offset); + + /* Init the chipset. */ + pci_bus = typhoon_init(&isa_pci_irq, &rtc_irq, cpus, clipper_pci_map_irq); + + /* Init the ISA bus. */ + isa_bus_new(NULL); + isa_mem_base = pci_to_cpu_addr(pci_bus, 0); + + isa_irqs = i8259_init(isa_pci_irq); + isa_bus_irqs(isa_irqs); + + rtc_init(1980, rtc_irq); + pit_init(0x40, 0); + isa_create_simple("i8042"); + + /* VGA setup. Don't bother loading the bios. */ + alpha_pci_vga_setup(pci_bus); + + /* Serial code setup. */ + for (i = 0; i < MAX_SERIAL_PORTS; ++i) { + if (serial_hds[i]) { + serial_isa_init(i, serial_hds[i]); + } + } + + /* Network setup. e1000 is good enough, failing Tulip support. */ + for (i = 0; i < nb_nics; i++) { + pci_nic_init_nofail(&nd_table[i], "e1000", NULL); + } + + /* IDE disk setup. */ + { + DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; + ide_drive_get(hd, MAX_IDE_BUS); + + pci_cmd646_ide_init(pci_bus, hd, 0); + } + + /* Load PALcode. Given that this is not "real" cpu palcode, + but one explicitly written for the emulation, we might as + well load it directly from and ELF image. */ + palcode_filename = (bios_name ? bios_name : "palcode-clipper"); + palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); + if (palcode_filename == NULL) { + hw_error("no palcode provided\n"); + exit(1); + } + size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, + NULL, &palcode_entry, &palcode_low, &palcode_high, + 0, EM_ALPHA, 0); + if (size < 0) { + hw_error("could not load palcode '%s'\n", palcode_filename); + exit(1); + } + + /* Start all cpus at the PALcode RESET entry point. */ + for (i = 0; i < smp_cpus; ++i) { + cpus[i]->pal_mode = 1; + cpus[i]->pc = palcode_entry; + cpus[i]->palbr = palcode_entry; + } + + /* Load a kernel. */ + if (kernel_filename) { + uint64_t param_offset; + + size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, + NULL, &kernel_entry, &kernel_low, &kernel_high, + 0, EM_ALPHA, 0); + if (size < 0) { + hw_error("could not load kernel '%s'\n", kernel_filename); + exit(1); + } + + cpus[0]->trap_arg1 = kernel_entry; + + param_offset = kernel_low - 0x6000; + + if (kernel_cmdline) { + pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); + } + + if (initrd_filename) { + long initrd_base, initrd_size; + + initrd_size = get_image_size(initrd_filename); + if (initrd_size < 0) { + hw_error("could not load initial ram disk '%s'\n", + initrd_filename); + exit(1); + } + + /* Put the initrd image as high in memory as possible. */ + initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; + load_image_targphys(initrd_filename, initrd_base, + ram_size - initrd_base); + + stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000UL); + stq_phys(param_offset + 0x108, initrd_size); + } + } +} + +static QEMUMachine clipper_machine = { + .name = "clipper", + .desc = "Alpha DP264/CLIPPER", + .init = clipper_init, + .max_cpus = 4, + .is_default = 1, +}; + +static void clipper_machine_init(void) +{ + qemu_register_machine(&clipper_machine); +} + +machine_init(clipper_machine_init); diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c new file mode 100644 index 0000000..b321772 --- /dev/null +++ b/hw/alpha_pci.c @@ -0,0 +1,358 @@ +/* + * QEMU Alpha PCI support functions. + * + * Some of this isn't very Alpha specific at all. Some of this is specific + * to sparse PCI access support for older Alpha systems. + */ + +#include "config.h" +#include "alpha_sys.h" +#include "qemu-log.h" +#include "sysemu.h" +#include "vmware_vga.h" + + +/* PCI IO reads, to byte-word addressable memory. */ +/* ??? Doesn't handle multiple PCI busses. */ + +static uint32_t bw_io_readb(void *opaque, target_phys_addr_t addr) +{ + return cpu_inb(addr); +} + +static uint32_t bw_io_readw(void *opaque, target_phys_addr_t addr) +{ + return cpu_inw(addr); +} + +static uint32_t bw_io_readl(void *opaque, target_phys_addr_t addr) +{ + return cpu_inl(addr); +} + +/* PCI IO writes, to byte-word addressable memory. */ +/* ??? Doesn't handle multiple PCI busses. */ + +static void bw_io_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + cpu_outb(addr, val); +} + +static void bw_io_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + cpu_outw(addr, val); +} + +static void bw_io_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + cpu_outl(addr, val); +} + +CPUReadMemoryFunc * const alpha_pci_bw_io_reads[] = { + bw_io_readb, + bw_io_readw, + bw_io_readl, +}; + +CPUWriteMemoryFunc * const alpha_pci_bw_io_writes[] = { + bw_io_writeb, + bw_io_writew, + bw_io_writel, +}; + +/* PCI config space reads, to byte-word addressable memory. */ +static uint32_t bw_conf1_readb(void *opaque, target_phys_addr_t addr) +{ + PCIBus *b = opaque; + return pci_data_read(b, addr, 1); +} + +static uint32_t bw_conf1_readw(void *opaque, target_phys_addr_t addr) +{ + PCIBus *b = opaque; + return pci_data_read(b, addr, 2); +} + +static uint32_t bw_conf1_readl(void *opaque, target_phys_addr_t addr) +{ + PCIBus *b = opaque; + return pci_data_read(b, addr, 4); +} + +/* PCI config space writes, to byte-word addressable memory. */ +static void bw_conf1_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *b = opaque; + pci_data_write(b, addr, val, 1); +} + +static void bw_conf1_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *b = opaque; + pci_data_write(b, addr, val, 2); +} + +static void bw_conf1_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *b = opaque; + pci_data_write(b, addr, val, 4); +} + +CPUReadMemoryFunc * const alpha_pci_bw_conf1_reads[] = { + bw_conf1_readb, + bw_conf1_readw, + bw_conf1_readl, +}; + +CPUWriteMemoryFunc * const alpha_pci_bw_conf1_writes[] = { + bw_conf1_writeb, + bw_conf1_writew, + bw_conf1_writel, +}; + +/* PCI MEM access to dense (but not byte-word addressable) memory. */ +static uint32_t dense_mem_readl(void *opaque, target_phys_addr_t addr) +{ + PCIBus *b = opaque; + return ldl_phys(pci_to_cpu_addr(b, addr)); +} + +static void dense_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t v) +{ + PCIBus *b = opaque; + stl_phys(pci_to_cpu_addr(b, addr), v); +} + +CPUReadMemoryFunc * const alpha_pci_dense_mem_reads[] = { + unassigned_mem_readb, + unassigned_mem_readw, + dense_mem_readl, +}; + +CPUWriteMemoryFunc * const alpha_pci_dense_mem_writes[] = { + unassigned_mem_writeb, + unassigned_mem_writew, + dense_mem_writel, +}; + +/* PCI IO to sparse memory. These are helper routines, which expect that the + relevant HAE has already been prepended to ADDR by the core-specific + routine that is actually registered with the memory region. */ + +uint32_t alpha_sparse_io_read(target_phys_addr_t addr) +{ + int size = (addr >> 3) & 3; + uint32_t val; + + addr >>= 5; + switch (size) { + case 0: + /* byte access */ + val = cpu_inb(addr); + break; + case 1: + /* word access */ + val = cpu_inw(addr); + break; + case 2: + /* tri-byte access; apparently possible with real pci lines. */ + qemu_log("pci: tri-byte io read"); + return ~0u; + default: + /* long access */ + return cpu_inl(addr); + } + + val <<= (addr & 3) * 8; + return val; +} + +void alpha_sparse_io_write(target_phys_addr_t addr, uint32_t val) +{ + int size = (addr >> 3) & 3; + + addr >>= 5; + switch (size) { + case 0: + /* byte access */ + val >>= (addr & 3) * 8; + cpu_outb(addr, val); + break; + case 1: + /* word access */ + val >>= (addr & 3) * 8; + cpu_outw(addr, val); + break; + case 2: + /* tri-byte access; apparently possible with real pci lines. */ + qemu_log("pci: tri-byte io write"); + break; + default: + /* long access */ + cpu_outl(addr, val); + break; + } +} + +uint32_t alpha_sparse_mem_read(PCIBus *b, target_phys_addr_t addr) +{ + int size = (addr >> 3) & 3; + uint32_t val; + + addr = pci_to_cpu_addr(b, addr >> 5); + switch (size) { + case 0: + /* byte access */ + val = ldub_phys(addr); + break; + case 1: + /* word access */ + val = lduw_phys(addr); + break; + case 2: + /* tri-byte access; apparently possible with real pci lines. */ + qemu_log("pci: tri-byte mem read"); + return ~0u; + default: + /* long access */ + return ldl_phys(addr); + } + + val <<= (addr & 3) * 8; + return val; +} + +void alpha_sparse_mem_write(PCIBus *b, target_phys_addr_t addr, uint32_t val) +{ + int size = (addr >> 3) & 3; + + addr = pci_to_cpu_addr(b, addr >> 5); + switch (size) { + case 0: + /* byte access */ + val >>= (addr & 3) * 8; + stb_phys(addr, val); + break; + case 1: + /* word access */ + val >>= (addr & 3) * 8; + stw_phys(addr, val); + break; + case 2: + /* tri-byte access; apparently possible with real pci lines. */ + qemu_log("pci: tri-byte mem write"); + break; + default: + /* long access */ + stl_phys(addr, val); + break; + } +} + +uint32_t alpha_sparse_conf1_read(PCIBus *b, target_phys_addr_t addr) +{ + int size = ((addr >> 3) & 3) + 1; + uint32_t val; + + if (size == 3) { + qemu_log("pci: tri-byte configuration read"); + return ~0u; + } + + addr >>= 5; + val = pci_data_read(b, addr, size); + val <<= (addr & 3) * 8; + + return val; +} + +void alpha_sparse_conf1_write(PCIBus *b, target_phys_addr_t addr, uint32_t val) +{ + int size = ((addr >> 3) & 3) + 1; + + if (size == 3) { + qemu_log("pci: tri-byte configuration write"); + return; + } + + addr >>= 5; + val >>= (addr & 3) * 8; + pci_data_write(b, addr, val, size); +} + +/* Configuration space accesses do not normall use an HAE. */ +static uint32_t sparse_conf1_readl(void *opaque, target_phys_addr_t addr) +{ + PCIBus *b = opaque; + return alpha_sparse_conf1_read(b, addr); +} + +static void sparse_conf1_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *b = opaque; + alpha_sparse_conf1_write(b, addr, val); +} + +CPUReadMemoryFunc * const alpha_pci_sparse_conf1_reads[] = { + unassigned_mem_readb, + unassigned_mem_readw, + sparse_conf1_readl, +}; + +CPUWriteMemoryFunc * const alpha_pci_sparse_conf1_writes[] = { + unassigned_mem_writeb, + unassigned_mem_writew, + sparse_conf1_writel, +}; + +/* PCI/EISA Interrupt Acknowledge Cycle. */ + +static uint32_t iack_readl(void *opaque, target_phys_addr_t addr) +{ + if (addr & 15) { + return unassigned_mem_readl(opaque, addr); + } + return pic_read_irq(isa_pic); +} + +static void special_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + qemu_log("pci: special write cycle %08x", val); +} + +CPUReadMemoryFunc * const alpha_pci_iack_reads[] = { + unassigned_mem_readb, + unassigned_mem_readw, + iack_readl, +}; + +CPUWriteMemoryFunc * const alpha_pci_special_writes[] = { + unassigned_mem_writeb, + unassigned_mem_writew, + special_writel, +}; +\f +void alpha_pci_vga_setup(PCIBus *pci_bus) +{ + switch (vga_interface_type) { +#ifdef CONFIG_SPICE + case VGA_QXL: + pci_create_simple(pci_bus, -1, "qxl-vga"); + return; +#endif + case VGA_CIRRUS: + pci_cirrus_vga_init(pci_bus); + return; + case VGA_VMWARE: + if (pci_vmsvga_init(pci_bus)) { + return; + } + break; + } + /* If VGA is enabled at all, and one of the above didn't work, then + fallback to Standard VGA. */ + if (vga_interface_type != VGA_NONE) { + pci_vga_init(pci_bus); + } +} diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h new file mode 100644 index 0000000..98e5351 --- /dev/null +++ b/hw/alpha_sys.h @@ -0,0 +1,44 @@ +/* Alpha cores and system support chips. */ + +#ifndef HW_ALPHA_H +#define HW_ALPHA_H 1 + +#include "pci.h" +#include "pci_host.h" +#include "ide.h" +#include "net.h" +#include "pc.h" +#include "usb-ohci.h" +#include "irq.h" + + +extern PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq, + CPUState *cpus[3], pci_map_irq_fn sys_map_irq); + +/* alpha_pci.c. */ +extern CPUReadMemoryFunc * const alpha_pci_bw_io_reads[]; +extern CPUWriteMemoryFunc * const alpha_pci_bw_io_writes[]; +extern CPUReadMemoryFunc * const alpha_pci_bw_conf1_reads[]; +extern CPUWriteMemoryFunc * const alpha_pci_bw_conf1_writes[]; + +extern CPUReadMemoryFunc * const alpha_pci_dense_mem_reads[]; +extern CPUWriteMemoryFunc * const alpha_pci_dense_mem_writes[]; + +extern CPUReadMemoryFunc * const alpha_pci_sparse_conf1_reads[]; +extern CPUWriteMemoryFunc * const alpha_pci_sparse_conf1_writes[]; + +extern CPUReadMemoryFunc * const alpha_pci_iack_reads[]; +extern CPUWriteMemoryFunc * const alpha_pci_special_writes[]; + +extern uint32_t alpha_sparse_io_read(target_phys_addr_t); +extern void alpha_sparse_io_write(target_phys_addr_t, uint32_t); + +extern uint32_t alpha_sparse_mem_read(PCIBus *, target_phys_addr_t); +extern void alpha_sparse_mem_write(PCIBus *, target_phys_addr_t, uint32_t); + +extern uint32_t alpha_sparse_conf1_read(PCIBus *, target_phys_addr_t); +extern void alpha_sparse_conf1_write(PCIBus *, target_phys_addr_t, uint32_t); + +void alpha_pci_vga_setup(PCIBus *pci_bus); + +#endif diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c new file mode 100644 index 0000000..7cdf7d3 --- /dev/null +++ b/hw/alpha_typhoon.c @@ -0,0 +1,781 @@ +/* + * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation. + * + * Written by Richard Henderson. + * + * This work is licensed under the GNU GPL license version 2 or later. + */ + +#include "cpu.h" +#include "exec-all.h" +#include "hw.h" +#include "devices.h" +#include "sysemu.h" +#include "alpha_sys.h" + +typedef struct TyphoonCchip { + uint64_t misc; + uint64_t drir; + uint64_t dim[4]; + uint32_t iic[4]; + CPUState *cpu[4]; +} TyphoonCchip; + +typedef struct TyphoonWindow { + uint32_t base_addr; + uint32_t mask; + uint32_t translated_base_pfn; +} TyphoonWindow; + +typedef struct TyphoonPchip { + uint64_t ctl; + TyphoonWindow win[4]; +} TyphoonPchip; + +typedef struct TyphoonState { + PCIHostState host; + + TyphoonCchip cchip; + TyphoonPchip pchip; + + /* QEMU emulation state. */ + uint32_t latch_tmp; +} TyphoonState; + +/* Called when one of DRIR or DIM changes. */ +static void cpu_irq_change(CPUState *env, uint64_t req) +{ + /* If there are any non-masked interrupts, tell the cpu. */ + if (env) { + if (req) { + cpu_interrupt(env, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); + } + } +} + +static uint32_t cchip_readl(void *opaque, target_phys_addr_t addr) +{ + CPUState *env = cpu_single_env; + TyphoonState *s = opaque; + uint64_t ret = 0; + + if (addr & 4) { + return s->latch_tmp; + } + + switch (addr) { + case 0x0000: + /* CSC: Cchip System Configuration Register. */ + /* All sorts of data here; probably the only thing relevant is + PIP<14> Pchip 1 Present = 0. */ + break; + + case 0x0040: + /* MTR: Memory Timing Register. */ + /* All sorts of stuff related to real DRAM. */ + break; + + case 0x0080: + /* MISC: Miscellaneous Register. */ + ret = s->cchip.misc | (env->cpu_index & 3); + break; + + case 0x00c0: + /* MPD: Memory Presence Detect Register. */ + break; + + case 0x0100: /* AAR0 */ + case 0x0140: /* AAR1 */ + case 0x0180: /* AAR2 */ + case 0x01c0: /* AAR3 */ + /* AAR: Array Address Register. */ + /* All sorts of information about DRAM. */ + break; + + case 0x0200: + /* DIM0: Device Interrupt Mask Register, CPU0. */ + ret = s->cchip.dim[0]; + break; + case 0x0240: + /* DIM1: Device Interrupt Mask Register, CPU1. */ + ret = s->cchip.dim[1]; + break; + case 0x0280: + /* DIR0: Device Interrupt Request Register, CPU0. */ + ret = s->cchip.dim[0] & s->cchip.drir; + break; + case 0x02c0: + /* DIR1: Device Interrupt Request Register, CPU1. */ + ret = s->cchip.dim[1] & s->cchip.drir; + break; + case 0x0300: + /* DRIR: Device Raw Interrupt Request Register. */ + ret = s->cchip.drir; + break; + + case 0x0340: + /* PRBEN: Probe Enable Register. */ + break; + + case 0x0380: + /* IIC0: Interval Ignore Count Register, CPU0. */ + ret = s->cchip.iic[0]; + break; + case 0x03c0: + /* IIC1: Interval Ignore Count Register, CPU1. */ + ret = s->cchip.iic[1]; + break; + + case 0x0400: /* MPR0 */ + case 0x0440: /* MPR1 */ + case 0x0480: /* MPR2 */ + case 0x04c0: /* MPR3 */ + /* MPR: Memory Programming Register. */ + break; + + case 0x0580: + /* TTR: TIGbus Timing Register. */ + /* All sorts of stuff related to interrupt delivery timings. */ + break; + case 0x05c0: + /* TDR: TIGbug Device Timing Register. */ + break; + + case 0x0600: + /* DIM2: Device Interrupt Mask Register, CPU2. */ + ret = s->cchip.dim[2]; + break; + case 0x0640: + /* DIM3: Device Interrupt Mask Register, CPU3. */ + ret = s->cchip.dim[3]; + break; + case 0x0680: + /* DIR2: Device Interrupt Request Register, CPU2. */ + ret = s->cchip.dim[2] & s->cchip.drir; + break; + case 0x06c0: + /* DIR3: Device Interrupt Request Register, CPU3. */ + ret = s->cchip.dim[3] & s->cchip.drir; + break; + + case 0x0700: + /* IIC2: Interval Ignore Count Register, CPU2. */ + ret = s->cchip.iic[2]; + break; + case 0x0740: + /* IIC3: Interval Ignore Count Register, CPU3. */ + ret = s->cchip.iic[3]; + break; + + case 0x0780: + /* PWR: Power Management Control. */ + break; + + case 0x0c00: /* CMONCTLA */ + case 0x0c40: /* CMONCTLB */ + case 0x0c80: /* CMONCNT01 */ + case 0x0cc0: /* CMONCNT23 */ + break; + + default: + do_unassigned_access(addr, 0, 0, 0, 4); + return -1; + } + + s->latch_tmp = ret >> 32; + return ret; +} + +static uint32_t dchip_readl(void *opaque, target_phys_addr_t addr) +{ + /* Skip this. It's all related to DRAM timing and setup. */ + return 0; +} + +static uint32_t pchip_readl(void *opaque, target_phys_addr_t addr) +{ + TyphoonState *s = opaque; + uint64_t ret = 0; + + if (addr & 4) { + return s->latch_tmp; + } + + switch (addr) { + case 0x0000: + /* WSBA0: Window Space Base Address Register. */ + ret = s->pchip.win[0].base_addr; + break; + case 0x0040: + /* WSBA1 */ + ret = s->pchip.win[1].base_addr; + break; + case 0x0080: + /* WSBA2 */ + ret = s->pchip.win[2].base_addr; + break; + case 0x00c0: + /* WSBA3 */ + ret = s->pchip.win[3].base_addr; + break; + + case 0x0100: + /* WSM0: Window Space Mask Register. */ + ret = s->pchip.win[0].mask; + break; + case 0x0140: + /* WSM1 */ + ret = s->pchip.win[1].mask; + break; + case 0x0180: + /* WSM2 */ + ret = s->pchip.win[2].mask; + break; + case 0x01c0: + /* WSM3 */ + ret = s->pchip.win[3].mask; + break; + + case 0x0200: + /* TBA0: Translated Base Address Register. */ + ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10; + break; + case 0x0240: + /* TBA1 */ + ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10; + break; + case 0x0280: + /* TBA2 */ + ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10; + break; + case 0x02c0: + /* TBA3 */ + ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10; + break; + + case 0x0300: + /* PCTL: Pchip Control Register. */ + ret = s->pchip.ctl; + break; + case 0x0340: + /* PLAT: Pchip Master Latency Register. */ + break; + case 0x03c0: + /* PERROR: Pchip Error Register. */ + break; + case 0x0400: + /* PERRMASK: Pchip Error Mask Register. */ + break; + case 0x0440: + /* PERRSET: Pchip Error Set Register. */ + break; + case 0x0480: + /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */ + break; + case 0x04c0: + /* TLBIA: Translation Buffer Invalidate All Register (WO). */ + break; + case 0x0500: /* PMONCTL */ + case 0x0540: /* PMONCNT */ + case 0x0800: /* SPRST */ + break; + + default: + do_unassigned_access(addr, 0, 0, 0, 4); + return -1; + } + + s->latch_tmp = ret >> 32; + return ret; +} + +static void cchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32) +{ + TyphoonState *s = opaque; + uint64_t val, oldval, newval; + + if (addr & 4) { + val = (uint64_t)v32 << 32 | s->latch_tmp; + addr ^= 4; + } else { + s->latch_tmp = v32; + return; + } + + switch (addr) { + case 0x0000: + /* CSC: Cchip System Configuration Register. */ + /* All sorts of data here; nothing relevant RW. */ + break; + + case 0x0040: + /* MTR: Memory Timing Register. */ + /* All sorts of stuff related to real DRAM. */ + break; + + case 0x0080: + /* MISC: Miscellaneous Register. */ + newval = oldval = s->cchip.misc; + newval &= ~(val & 0x10000ff0); /* W1C fields */ + if (val & 0x100000) { + newval &= ~0xff0000ull; /* ACL clears ABT and ABW */ + } else { + newval |= val & 0x00f00000; /* ABT field is W1S */ + if ((newval & 0xf0000) == 0) { + newval |= val & 0xf0000; /* ABW field is W1S iff zero */ + } + } + newval |= (val & 0xf000) >> 4; /* IPREQ field sets IPINTR. */ + + newval &= ~0xf0000000000ull; /* WO and RW fields */ + newval |= val & 0xf0000000000ull; + s->cchip.misc = newval; + + /* Pass on changes to IPI and ITI state. */ + if ((newval ^ oldval) & 0xff0) { + int i; + for (i = 0; i < 4; ++i) { + CPUState *env = s->cchip.cpu[i]; + if (env) { + /* IPI can be either cleared or set by the write. */ + if (newval & (1 << (i + 8))) { + cpu_interrupt(env, CPU_INTERRUPT_SMP); + } else { + cpu_reset_interrupt(env, CPU_INTERRUPT_SMP); + } + + /* ITI can only be cleared by the write. */ + if ((newval & (1 << (i + 4))) == 0) { + cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER); + } + } + } + } + break; + + case 0x00c0: + /* MPD: Memory Presence Detect Register. */ + break; + + case 0x0100: /* AAR0 */ + case 0x0140: /* AAR1 */ + case 0x0180: /* AAR2 */ + case 0x01c0: /* AAR3 */ + /* AAR: Array Address Register. */ + /* All sorts of information about DRAM. */ + break; + + case 0x0200: /* DIM0 */ + /* DIM: Device Interrupt Mask Register, CPU0. */ + s->cchip.dim[0] = val; + cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir); + break; + case 0x0240: /* DIM1 */ + /* DIM: Device Interrupt Mask Register, CPU1. */ + s->cchip.dim[0] = val; + cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir); + break; + + case 0x0280: /* DIR0 (RO) */ + case 0x02c0: /* DIR1 (RO) */ + case 0x0300: /* DRIR (RO) */ + break; + + case 0x0340: + /* PRBEN: Probe Enable Register. */ + break; + + case 0x0380: /* IIC0 */ + s->cchip.iic[0] = val & 0xffffff; + break; + case 0x03c0: /* IIC1 */ + s->cchip.iic[1] = val & 0xffffff; + break; + + case 0x0400: /* MPR0 */ + case 0x0440: /* MPR1 */ + case 0x0480: /* MPR2 */ + case 0x04c0: /* MPR3 */ + /* MPR: Memory Programming Register. */ + break; + + case 0x0580: + /* TTR: TIGbus Timing Register. */ + /* All sorts of stuff related to interrupt delivery timings. */ + break; + case 0x05c0: + /* TDR: TIGbug Device Timing Register. */ + break; + + case 0x0600: + /* DIM2: Device Interrupt Mask Register, CPU2. */ + s->cchip.dim[2] = val; + cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir); + break; + case 0x0640: + /* DIM3: Device Interrupt Mask Register, CPU3. */ + s->cchip.dim[3] = val; + cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir); + break; + + case 0x0680: /* DIR2 (RO) */ + case 0x06c0: /* DIR3 (RO) */ + break; + + case 0x0700: /* IIC2 */ + s->cchip.iic[2] = val & 0xffffff; + break; + case 0x0740: /* IIC3 */ + s->cchip.iic[3] = val & 0xffffff; + break; + + case 0x0780: + /* PWR: Power Management Control. */ + break; + + case 0x0c00: /* CMONCTLA */ + case 0x0c40: /* CMONCTLB */ + case 0x0c80: /* CMONCNT01 */ + case 0x0cc0: /* CMONCNT23 */ + break; + + default: + do_unassigned_access(addr, 1, 0, 0, 4); + return; + } +} + +static void dchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32) +{ + /* Skip this. It's all related to DRAM timing and setup. */ +} + +static void pchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32) +{ + TyphoonState *s = opaque; + uint64_t val, oldval; + + switch (addr) { + case 0x0000: + /* WSBA0: Window Space Base Address Register. */ + s->pchip.win[0].base_addr = v32; + break; + case 0x0040: + /* WSBA1 */ + s->pchip.win[1].base_addr = v32; + break; + case 0x0080: + /* WSBA2 */ + s->pchip.win[2].base_addr = v32; + break; + case 0x00c0: + /* WSBA3 */ + s->pchip.win[3].base_addr = v32; + break; + + case 0x0100: + /* WSM0: Window Space Mask Register. */ + s->pchip.win[0].mask = v32; + break; + case 0x0140: + /* WSM1 */ + s->pchip.win[1].mask = v32; + break; + case 0x0180: + /* WSM2 */ + s->pchip.win[2].mask = v32; + break; + case 0x01c0: + /* WSM3 */ + s->pchip.win[3].mask = v32; + break; + + case 0x0200: + /* TBA0: Translated Base Address Register. */ + s->pchip.win[0].translated_base_pfn = v32 >> 10; + break; + case 0x0240: + /* TBA1 */ + s->pchip.win[1].translated_base_pfn = v32 >> 10; + break; + case 0x0280: + /* TBA2 */ + s->pchip.win[2].translated_base_pfn = v32 >> 10; + break; + case 0x02c0: + /* TBA3 */ + s->pchip.win[3].translated_base_pfn = v32 >> 10; + break; + + case 0x0004: + case 0x0044: + case 0x0084: + case 0x00c4: + case 0x0104: + case 0x0144: + case 0x0184: + case 0x01c4: + case 0x0204: + case 0x0244: + case 0x0284: + case 0x02c4: + /* MBZ high-part portions of the above registers. */ + break; + + case 0x0300: + /* PCTL: Pchip Control Register. */ + s->latch_tmp = v32; + break; + case 0x0304: + val = (uint64_t)v32 << 32 | s->latch_tmp; + + oldval = s->pchip.ctl; + oldval &= ~0x00001cff0fc7ffull; /* RW fields */ + oldval |= val & 0x00001cff0fc7ffull; + + s->pchip.ctl = oldval; + break; + + case 0x0340: case 0x0344: + /* PLAT: Pchip Master Latency Register. */ + break; + case 0x03c0: case 0x03c4: + /* PERROR: Pchip Error Register. */ + break; + case 0x0400: case 0x0404: + /* PERRMASK: Pchip Error Mask Register. */ + break; + case 0x0440: case 0x0444: + /* PERRSET: Pchip Error Set Register. */ + break; + + case 0x0480: + /* TLBIV: Translation Buffer Invalidate Virtual Register. */ + s->latch_tmp = v32; + break; + case 0x0484: + val = (uint64_t)v32 << 32 | s->latch_tmp; + break; + + case 0x04c0: + /* TLBIA: Translation Buffer Invalidate All Register (WO). */ + break; + case 0x04c4: + break; + + case 0x0500: case 0x0504: + /* PMONCTL */ + case 0x0540: case 0x0544: + /* PMONCNT */ + case 0x0800: case 0x0804: + /* SPRST */ + break; + + default: + do_unassigned_access(addr, 1, 0, 0, 4); + return; + } +} + +static CPUReadMemoryFunc * const cchip_reads[] = { + NULL, + NULL, + cchip_readl +}; + +static CPUWriteMemoryFunc * const cchip_writes[] = { + NULL, + NULL, + cchip_writel +}; + +static CPUReadMemoryFunc * const dchip_reads[] = { + NULL, + NULL, + dchip_readl +}; + +static CPUWriteMemoryFunc * const dchip_writes[] = { + NULL, + NULL, + dchip_writel +}; + +static CPUReadMemoryFunc * const pchip_reads[] = { + NULL, + NULL, + pchip_readl +}; + +static CPUWriteMemoryFunc * const pchip_writes[] = { + NULL, + NULL, + pchip_writel +}; + +static void typhoon_set_irq(void *opaque, int irq, int level) +{ + TyphoonState *s = opaque; + uint64_t drir; + int i; + + /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL. */ + drir = s->cchip.drir; + if (level) { + drir |= 1ull << irq; + } else { + drir &= ~(1ull << irq); + } + s->cchip.drir = drir; + + for (i = 0; i < 4; ++i) { + cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir); + } +} + +static void typhoon_set_isa_irq(void *opaque, int irq, int level) +{ + typhoon_set_irq(opaque, 55, level); +} + +static void typhoon_set_timer_irq(void *opaque, int irq, int level) +{ + TyphoonState *s = opaque; + int i; + + /* Thankfully, the mc146818rtc code doesn't track the IRQ state, + and so we don't have to worry about missing interrupts just + because we never actually ACK the interrupt. Just ignore any + case of the interrupt level going low. */ + if (level == 0) { + return; + } + + /* Deliver the interrupt to each CPU, considering each CPU's IIC. */ + for (i = 0; i < 4; ++i) { + CPUState *env = s->cchip.cpu[i]; + if (env) { + uint32_t iic = s->cchip.iic[i]; + + /* ??? The verbage in Section 10.2.2.10 isn't 100% clear. + Bit 24 is the OverFlow bit, RO, and set when the count + decrements past 0. When is OF cleared? My guess is that + OF is actually cleared when the IIC is written, and that + the ICNT field always decrements. At least, that's an + interpretation that makes sense, and "allows the CPU to + determine exactly how mant interval timer ticks were + skipped". At least within the next 4M ticks... */ + + iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000); + s->cchip.iic[i] = iic; + + if (iic & 0x1000000) { + /* Set the ITI bit for this cpu. */ + s->cchip.misc |= 1 << (i + 4); + /* And signal the interrupt. */ + cpu_interrupt(env, CPU_INTERRUPT_TIMER); + } + } + } +} + +PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq, + CPUState *cpus[3], pci_map_irq_fn sys_map_irq) +{ + const uint64_t MB = 1024 * 1024; + DeviceState *dev; + PCIHostState *p; + TyphoonState *s; + PCIBus *b; + int region; + + dev = qdev_create(NULL, "typhoon-pcihost"); + p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); + s = container_of(p, TyphoonState, host); + + /* Remember the CPUs so that we can deliver interrupts to them. */ + memcpy(s->cchip.cpu, cpus, 4 * sizeof(CPUState *)); + + *p_isa_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1); + *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1); + + b = pci_register_bus(&s->host.busdev.qdev, "pci", typhoon_set_irq, + sys_map_irq, s, 0, 64); + s->host.bus = b; + + qdev_init_nofail(dev); + + /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, + but the address space hole reserved at this point is 8TB. */ + + /* Pchip0 PCI memory, 0x800.0000.0000, 4GB. */ + pci_bus_set_mem_base(b, 0x80000000000ull); + + /* TIGbus, 0x801.0000.0000, 1GB. */ + /* ??? The TIGbus is used for delivering interrupts, and access to + the flash ROM. I'm not sure that we need to implement it at all. */ + + /* Pchip0 CSRs, 0x801.8000.0000, 256MB. */ + region = cpu_register_io_memory(pchip_reads, pchip_writes, s, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x80180000000, 256*MB, region); + + /* Cchip CSRs, 0x801.A000.0000, 256MB. */ + region = cpu_register_io_memory(cchip_reads, cchip_writes, s, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x801a0000000, 256*MB, region); + + /* Dchip CSRs, 0x801.B000.0000, 256MB. */ + region = cpu_register_io_memory(dchip_reads, dchip_writes, s, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x801b0000000, 256*MB, region); + + /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */ + region = cpu_register_io_memory(alpha_pci_iack_reads, + alpha_pci_special_writes, b, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x801f8000000, 64*MB, region); + + /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */ + region = cpu_register_io_memory(alpha_pci_bw_io_reads, + alpha_pci_bw_io_writes, b, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x801fc000000, 32*MB, region); + + /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */ + region = cpu_register_io_memory(alpha_pci_bw_conf1_reads, + alpha_pci_bw_conf1_writes, b, + DEVICE_LITTLE_ENDIAN); + cpu_register_physical_memory(0x801fe000000, 16*MB, region); + + /* For the record, these are the mappings for the second PCI bus. + We can get away with not implementing them because we indicate + via the Cchip.CSC<PIP> bit that Pchip1 is not present. */ + /* Pchip1 PCI memory, 0x802.0000.0000, 4GB. */ + /* Pchip1 CSRs, 0x802.8000.0000, 256MB. */ + /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB. */ + /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB. */ + /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */ + + return b; +} + +static int typhoon_pcihost_init(SysBusDevice *dev) +{ + return 0; +} + +static SysBusDeviceInfo typhoon_pcihost_info = { + .init = typhoon_pcihost_init, + .qdev.name = "typhoon-pcihost", + .qdev.size = sizeof(TyphoonState), + .qdev.no_user = 1 +}; + +static void typhoon_register(void) +{ + sysbus_register_withprop(&typhoon_pcihost_info); +} +device_init(typhoon_register); -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson ` (3 preceding siblings ...) 2011-07-23 19:17 ` [Qemu-devel] [PATCH 4/7] target-alpha: Add " Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-30 11:07 ` Blue Swirl 2011-07-23 19:17 ` [Qemu-devel] [PATCH 6/7] target-alpha: Implement HALT IPR Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 7/7] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson 6 siblings, 1 reply; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel --- target-alpha/translate.c | 31 +++++++++++++++++++++---------- 1 files changed, 21 insertions(+), 10 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index c61906a..fddaff8 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1617,9 +1617,10 @@ static void gen_mfpr(int ra, int regno) } } -static void gen_mtpr(int rb, int regno) +static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno) { TCGv tmp; + int data; if (rb == 31) { tmp = tcg_const_i64(0); @@ -1627,19 +1628,27 @@ static void gen_mtpr(int rb, int regno) tmp = cpu_ir[rb]; } - /* These two register numbers perform a TLB cache flush. Thankfully we - can only do this inside PALmode, which means that the current basic - block cannot be affected by the change in mappings. */ - if (regno == 255) { + switch (regno) { + case 255: /* TBIA */ gen_helper_tbia(); - } else if (regno == 254) { + break; + + case 254: /* TBIS */ gen_helper_tbis(tmp); - } else { + break; + + case 253: + /* WAIT */ + tmp = tcg_const_i64(1); + tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted)); + return gen_excp(ctx, EXCP_HLT, 0); + + default: /* The basic registers are data only, and unknown registers are read-zero, write-ignore. */ - int data = cpu_pr_data(regno); + data = cpu_pr_data(regno); if (data != 0) { if (data & PR_BYTE) { tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE); @@ -1649,11 +1658,14 @@ static void gen_mtpr(int rb, int regno) tcg_gen_st_i64(tmp, cpu_env, data); } } + break; } if (rb == 31) { tcg_temp_free(tmp); } + + return NO_EXIT; } #endif /* !USER_ONLY*/ @@ -3053,8 +3065,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) /* HW_MTPR (PALcode) */ #ifndef CONFIG_USER_ONLY if (ctx->tb->flags & TB_FLAGS_PAL_MODE) { - gen_mtpr(rb, insn & 0xffff); - break; + return gen_mtpr(ctx, rb, insn & 0xffff); } #endif goto invalid_opc; -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR. 2011-07-23 19:17 ` [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR Richard Henderson @ 2011-07-30 11:07 ` Blue Swirl 0 siblings, 0 replies; 17+ messages in thread From: Blue Swirl @ 2011-07-30 11:07 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel On Sat, Jul 23, 2011 at 10:17 PM, Richard Henderson <rth@twiddle.net> wrote: > --- Misses SoB and I don't know how to add it while pulling. Please fix or educate. > target-alpha/translate.c | 31 +++++++++++++++++++++---------- > 1 files changed, 21 insertions(+), 10 deletions(-) > > diff --git a/target-alpha/translate.c b/target-alpha/translate.c > index c61906a..fddaff8 100644 > --- a/target-alpha/translate.c > +++ b/target-alpha/translate.c > @@ -1617,9 +1617,10 @@ static void gen_mfpr(int ra, int regno) > } > } > > -static void gen_mtpr(int rb, int regno) > +static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno) > { > TCGv tmp; > + int data; > > if (rb == 31) { > tmp = tcg_const_i64(0); > @@ -1627,19 +1628,27 @@ static void gen_mtpr(int rb, int regno) > tmp = cpu_ir[rb]; > } > > - /* These two register numbers perform a TLB cache flush. Thankfully we > - can only do this inside PALmode, which means that the current basic > - block cannot be affected by the change in mappings. */ > - if (regno == 255) { > + switch (regno) { > + case 255: > /* TBIA */ > gen_helper_tbia(); > - } else if (regno == 254) { > + break; > + > + case 254: > /* TBIS */ > gen_helper_tbis(tmp); > - } else { > + break; > + > + case 253: > + /* WAIT */ > + tmp = tcg_const_i64(1); > + tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted)); > + return gen_excp(ctx, EXCP_HLT, 0); > + > + default: > /* The basic registers are data only, and unknown registers > are read-zero, write-ignore. */ > - int data = cpu_pr_data(regno); > + data = cpu_pr_data(regno); > if (data != 0) { > if (data & PR_BYTE) { > tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE); > @@ -1649,11 +1658,14 @@ static void gen_mtpr(int rb, int regno) > tcg_gen_st_i64(tmp, cpu_env, data); > } > } > + break; > } > > if (rb == 31) { > tcg_temp_free(tmp); > } > + > + return NO_EXIT; > } > #endif /* !USER_ONLY*/ > > @@ -3053,8 +3065,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) > /* HW_MTPR (PALcode) */ > #ifndef CONFIG_USER_ONLY > if (ctx->tb->flags & TB_FLAGS_PAL_MODE) { > - gen_mtpr(rb, insn & 0xffff); > - break; > + return gen_mtpr(ctx, rb, insn & 0xffff); > } > #endif > goto invalid_opc; > -- > 1.7.4.4 > > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 6/7] target-alpha: Implement HALT IPR. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson ` (4 preceding siblings ...) 2011-07-23 19:17 ` [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 7/7] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson 6 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel Signed-off-by: Richard Henderson <rth@twiddle.net> --- target-alpha/helper.h | 1 + target-alpha/op_helper.c | 10 ++++++++++ target-alpha/translate.c | 5 +++++ 3 files changed, 16 insertions(+), 0 deletions(-) diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 2dec57e..c352c24 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -113,6 +113,7 @@ DEF_HELPER_2(stq_c_phys, i64, i64, i64) DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void) DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64) +DEF_HELPER_1(halt, void, i64); #endif #include "def-helper.h" diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index 8f39154..ad85e4c 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -21,6 +21,7 @@ #include "host-utils.h" #include "softfloat.h" #include "helper.h" +#include "sysemu.h" #include "qemu-timer.h" /*****************************************************************************/ @@ -1215,6 +1216,15 @@ void helper_tbis(uint64_t p) { tlb_flush_page(env, p); } + +void helper_halt(uint64_t restart) +{ + if (restart) { + qemu_system_reset_request(); + } else { + qemu_system_shutdown_request(); + } +} #endif /*****************************************************************************/ diff --git a/target-alpha/translate.c b/target-alpha/translate.c index fddaff8..b1609e3 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1645,6 +1645,11 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno) tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted)); return gen_excp(ctx, EXCP_HLT, 0); + case 252: + /* HALT */ + gen_helper_halt(tmp); + return EXIT_PC_STALE; + default: /* The basic registers are data only, and unknown registers are read-zero, write-ignore. */ -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 7/7] target-alpha: Add high-resolution access to wall clock and an alarm. 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson ` (5 preceding siblings ...) 2011-07-23 19:17 ` [Qemu-devel] [PATCH 6/7] target-alpha: Implement HALT IPR Richard Henderson @ 2011-07-23 19:17 ` Richard Henderson 6 siblings, 0 replies; 17+ messages in thread From: Richard Henderson @ 2011-07-23 19:17 UTC (permalink / raw) To: qemu-devel The alarm is a fully general one-shot time comparator, which will be usable under Linux as a hrtimer source. It's much more flexible than the RTC source available on real hardware. The wall clock allows the guest access to the host timekeeping. Much like the KVM wall clock source for other guests. Both are accessed via the PALcode Cserve entry point. Signed-off-by: Richard Henderson <rth@twiddle.net> --- hw/alpha_typhoon.c | 22 ++++++++++++++++++++-- target-alpha/cpu.h | 4 ++++ target-alpha/helper.h | 4 ++++ target-alpha/op_helper.c | 15 +++++++++++++++ target-alpha/translate.c | 14 ++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 7cdf7d3..731b6ea 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -681,6 +681,16 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level) } } +static void typhoon_alarm_timer(void *opaque) +{ + TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3); + int cpu = (uintptr_t)opaque & 3; + + /* Set the ITI bit for this cpu. */ + s->cchip.misc |= 1 << (cpu + 4); + cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER); +} + PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq, CPUState *cpus[3], pci_map_irq_fn sys_map_irq) { @@ -689,14 +699,22 @@ PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq, PCIHostState *p; TyphoonState *s; PCIBus *b; - int region; + int i, region; dev = qdev_create(NULL, "typhoon-pcihost"); p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); s = container_of(p, TyphoonState, host); /* Remember the CPUs so that we can deliver interrupts to them. */ - memcpy(s->cchip.cpu, cpus, 4 * sizeof(CPUState *)); + for (i = 0; i < 4; i++) { + CPUState *env = cpus[i]; + s->cchip.cpu[i] = env; + if (env) { + env->alarm_timer = qemu_new_timer_ns(rtc_clock, + typhoon_alarm_timer, + (void *)((uintptr_t)s + i)); + } + } *p_isa_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1); *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1); diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 919be12..d0b569b 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -265,6 +265,10 @@ struct CPUAlphaState { uint64_t scratch[24]; #endif + /* This alarm doesn't exist in real hardware; we wish it did. */ + struct QEMUTimer *alarm_timer; + uint64_t alarm_expire; + #if TARGET_LONG_BITS > HOST_LONG_BITS /* temporary fixed-point registers * used to emulate 64 bits target on 32 bits hosts diff --git a/target-alpha/helper.h b/target-alpha/helper.h index c352c24..b693cee 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -113,7 +113,11 @@ DEF_HELPER_2(stq_c_phys, i64, i64, i64) DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void) DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64) + DEF_HELPER_1(halt, void, i64); + +DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64) +DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64) #endif #include "def-helper.h" diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index ad85e4c..623f1c3 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -1225,6 +1225,21 @@ void helper_halt(uint64_t restart) qemu_system_shutdown_request(); } } + +uint64_t helper_get_time(void) +{ + return qemu_get_clock_ns(rtc_clock); +} + +void helper_set_alarm(uint64_t expire) +{ + if (expire) { + env->alarm_expire = expire; + qemu_mod_timer(env->alarm_timer, expire); + } else { + qemu_del_timer(env->alarm_timer); + } +} #endif /*****************************************************************************/ diff --git a/target-alpha/translate.c b/target-alpha/translate.c index b1609e3..f386d21 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1590,6 +1590,9 @@ static int cpu_pr_data(int pr) return offsetof(CPUAlphaState, shadow[pr - 32]); case 40 ... 63: return offsetof(CPUAlphaState, scratch[pr - 40]); + + case 251: + return offsetof(CPUAlphaState, alarm_expire); } return 0; } @@ -1604,6 +1607,12 @@ static void gen_mfpr(int ra, int regno) return; } + if (regno == 250) { + /* WALL_TIME */ + gen_helper_get_time(cpu_ir[ra]); + return; + } + /* The basic registers are data only, and unknown registers are read-zero, write-ignore. */ if (data == 0) { @@ -1650,6 +1659,11 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno) gen_helper_halt(tmp); return EXIT_PC_STALE; + case 251: + /* ALARM */ + gen_helper_set_alarm(tmp); + break; + default: /* The basic registers are data only, and unknown registers are read-zero, write-ignore. */ -- 1.7.4.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-08-05 15:39 UTC | newest] Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-07-23 19:17 [Qemu-devel] [PULL 0/7] Alpha system emulation, v7 Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 1/7] Export the unassigned_mem read/write functions Richard Henderson 2011-07-24 13:28 ` Anthony Liguori 2011-07-24 16:42 ` Richard Henderson 2011-07-24 18:56 ` Anthony Liguori 2011-07-24 19:00 ` Richard Henderson 2011-07-25 1:47 ` Anthony Liguori 2011-07-25 2:14 ` Richard Henderson 2011-08-04 23:58 ` Edgar E. Iglesias 2011-08-05 15:39 ` Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 2/7] pci: Export pci_to_cpu_addr Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 3/7] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 4/7] target-alpha: Add " Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 5/7] target-alpha: Implement WAIT IPR Richard Henderson 2011-07-30 11:07 ` Blue Swirl 2011-07-23 19:17 ` [Qemu-devel] [PATCH 6/7] target-alpha: Implement HALT IPR Richard Henderson 2011-07-23 19:17 ` [Qemu-devel] [PATCH 7/7] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.