RISC-V Patches for the 5.0 Soft Freeze, Part 2
This is a fairly light-weight pull request, but I wanted to send it out to avoid the Goldfish stuff getting buried as the next PR should contain the H extension implementation. As far as this PR goes, it contains: * The addition of syscon device tree nodes for reboot and poweroff, which allows Linux to control QEMU without an additional driver. The existing device was already compatible with the syscon interface. * A fix to our GDB stub to avoid confusing XLEN and FLEN, specifically useful for rv32id-based systems. * A device emulation for the Goldfish RTC device, a simple memory-mapped RTC. * The addition of the Goldfish RTC device to the RISC-V virt board. This passes "make check" and boots buildroot for me. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAl5ByuQTHHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYid5gD/44YscK7P2tcFl+yDPJkUNV1Hja7iRM K14kuSHw2UoZ4DwQ69pmBJekrMDKHiI3HltXk51xLA6tQ9geubt6BAlwUeJfuIJQ DC9f9cN4x5OsJQZaFXcelR1vfpGntqQuKU6SXNHYTUTCL3fOEgpxaFm89pDevvxI Rvalg3OLrx4uAfjlllkpzKtcRjdytq08QJ8H6F0VbFY+uAwYosfxhst4M29XCLdA ESHqL8IgXNWcownIsx6cYwNkjOC7hE1vYwBjxbyLY85Y8frijnbB6JwVXH1YQWPz lTfCDCmBwBt7z5W16djZiib6A3Nlb7UMmOXuMFVWa9j6fECwCtC3Huvg80ofVtHB FBO03mT1FrElTZ5unJInTx8gQX2dHaDF8v6rEzYTeroaAbdexX401boWPKUYoqhR kDcdcAx4EsNfBOVQc40jAEyLHEs3yZ81os8G1H/ZafW2yj2Sob9NNvV57v8moVdp nZ+B4NNXrK+/lASnuW0eoIAcExTjhA9WDztacJR5mafTw4RmeIkbRrNPsekn8cHb FjaMFgA4+r44cUYMjuLO2zx20y3fCCmYUFP9heBbsvRhkTy0VMvMbt9B2zIY1v8n IQgVvqcrN9Epxvq+8vgC842p3TJii0KaAiF/YLZ1nHAfxRI1ax8gXDP3ak2abs0a xjC5FaAaeE0VRw== =D4dQ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-5.0-sf2' into staging RISC-V Patches for the 5.0 Soft Freeze, Part 2 This is a fairly light-weight pull request, but I wanted to send it out to avoid the Goldfish stuff getting buried as the next PR should contain the H extension implementation. As far as this PR goes, it contains: * The addition of syscon device tree nodes for reboot and poweroff, which allows Linux to control QEMU without an additional driver. The existing device was already compatible with the syscon interface. * A fix to our GDB stub to avoid confusing XLEN and FLEN, specifically useful for rv32id-based systems. * A device emulation for the Goldfish RTC device, a simple memory-mapped RTC. * The addition of the Goldfish RTC device to the RISC-V virt board. This passes "make check" and boots buildroot for me. # gpg: Signature made Mon 10 Feb 2020 21:28:04 GMT # gpg: using RSA key 2B3C3747446843B24A943A7A2E1319F35FBB1889 # gpg: issuer "palmer@dabbelt.com" # gpg: Good signature from "Palmer Dabbelt <palmer@dabbelt.com>" [unknown] # gpg: aka "Palmer Dabbelt <palmer@sifive.com>" [unknown] # gpg: aka "Palmer Dabbelt <palmerdabbelt@google.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 00CE 76D1 8349 60DF CE88 6DF8 EF4C A150 2CCB AB41 # Subkey fingerprint: 2B3C 3747 4468 43B2 4A94 3A7A 2E13 19F3 5FBB 1889 * remotes/palmer/tags/riscv-for-master-5.0-sf2: MAINTAINERS: Add maintainer entry for Goldfish RTC riscv: virt: Use Goldfish RTC device hw: rtc: Add Goldfish RTC device riscv: Separate FPU register size from core register size in gdbstub [v2] riscv/virt: Add syscon reboot and poweroff DT nodes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
971b2a1e5b
@ -562,6 +562,14 @@ F: include/hw/arm/digic.h
|
||||
F: hw/*/digic*
|
||||
F: include/hw/*/digic*
|
||||
|
||||
Goldfish RTC
|
||||
M: Anup Patel <anup.patel@wdc.com>
|
||||
M: Alistair Francis <Alistair.Francis@wdc.com>
|
||||
L: qemu-riscv@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/rtc/goldfish_rtc.c
|
||||
F: include/hw/rtc/goldfish_rtc.h
|
||||
|
||||
Gumstix
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
|
4
configure
vendored
4
configure
vendored
@ -7739,13 +7739,13 @@ case "$target_name" in
|
||||
TARGET_BASE_ARCH=riscv
|
||||
TARGET_ABI_DIR=riscv
|
||||
mttcg=yes
|
||||
gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-32bit-csr.xml riscv-32bit-virtual.xml"
|
||||
gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-csr.xml riscv-32bit-virtual.xml"
|
||||
;;
|
||||
riscv64)
|
||||
TARGET_BASE_ARCH=riscv
|
||||
TARGET_ABI_DIR=riscv
|
||||
mttcg=yes
|
||||
gdb_xml_files="riscv-64bit-cpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml"
|
||||
gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml riscv-64bit-virtual.xml"
|
||||
;;
|
||||
sh4|sh4eb)
|
||||
TARGET_ARCH=sh4
|
||||
|
@ -34,6 +34,7 @@ config RISCV_VIRT
|
||||
select PCI
|
||||
select HART
|
||||
select SERIAL
|
||||
select GOLDFISH_RTC
|
||||
select VIRTIO_MMIO
|
||||
select PCI_EXPRESS_GENERIC_BRIDGE
|
||||
select PFLASH_CFI01
|
||||
|
@ -58,6 +58,7 @@ static const struct MemmapEntry {
|
||||
[VIRT_DEBUG] = { 0x0, 0x100 },
|
||||
[VIRT_MROM] = { 0x1000, 0x11000 },
|
||||
[VIRT_TEST] = { 0x100000, 0x1000 },
|
||||
[VIRT_RTC] = { 0x101000, 0x1000 },
|
||||
[VIRT_CLINT] = { 0x2000000, 0x10000 },
|
||||
[VIRT_PLIC] = { 0xc000000, 0x4000000 },
|
||||
[VIRT_UART0] = { 0x10000000, 0x100 },
|
||||
@ -182,11 +183,10 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||
uint64_t mem_size, const char *cmdline)
|
||||
{
|
||||
void *fdt;
|
||||
int cpu;
|
||||
int cpu, i;
|
||||
uint32_t *cells;
|
||||
char *nodename;
|
||||
uint32_t plic_phandle, phandle = 1;
|
||||
int i;
|
||||
uint32_t plic_phandle, test_phandle, phandle = 1;
|
||||
hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
|
||||
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
|
||||
|
||||
@ -356,16 +356,35 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||
create_pcie_irq_map(fdt, nodename, plic_phandle);
|
||||
g_free(nodename);
|
||||
|
||||
test_phandle = phandle++;
|
||||
nodename = g_strdup_printf("/test@%lx",
|
||||
(long)memmap[VIRT_TEST].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
{
|
||||
const char compat[] = "sifive,test1\0sifive,test0";
|
||||
const char compat[] = "sifive,test1\0sifive,test0\0syscon";
|
||||
qemu_fdt_setprop(fdt, nodename, "compatible", compat, sizeof(compat));
|
||||
}
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg",
|
||||
0x0, memmap[VIRT_TEST].base,
|
||||
0x0, memmap[VIRT_TEST].size);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "phandle", test_phandle);
|
||||
test_phandle = qemu_fdt_get_phandle(fdt, nodename);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/reboot");
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-reboot");
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_phandle);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_RESET);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/poweroff");
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-poweroff");
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_phandle);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_PASS);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/uart@%lx",
|
||||
@ -386,6 +405,18 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||
}
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/rtc@%lx",
|
||||
(long)memmap[VIRT_RTC].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible",
|
||||
"google,goldfish-rtc");
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg",
|
||||
0x0, memmap[VIRT_RTC].base,
|
||||
0x0, memmap[VIRT_RTC].size);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "interrupts", RTC_IRQ);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
|
||||
qemu_fdt_add_subnode(s->fdt, nodename);
|
||||
qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "cfi-flash");
|
||||
@ -583,6 +614,9 @@ static void riscv_virt_board_init(MachineState *machine)
|
||||
0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193,
|
||||
serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
|
||||
sysbus_create_simple("goldfish_rtc", memmap[VIRT_RTC].base,
|
||||
qdev_get_gpio_in(DEVICE(s->plic), RTC_IRQ));
|
||||
|
||||
virt_flash_create(s);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->flash); i++) {
|
||||
|
@ -22,3 +22,6 @@ config MC146818RTC
|
||||
|
||||
config SUN4V_RTC
|
||||
bool
|
||||
|
||||
config GOLDFISH_RTC
|
||||
bool
|
||||
|
@ -11,3 +11,4 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
|
||||
obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
|
||||
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
|
||||
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o
|
||||
common-obj-$(CONFIG_GOLDFISH_RTC) += goldfish_rtc.o
|
||||
|
285
hw/rtc/goldfish_rtc.c
Normal file
285
hw/rtc/goldfish_rtc.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Goldfish virtual platform RTC
|
||||
*
|
||||
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* For more details on Google Goldfish virtual platform refer:
|
||||
* https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-2.0-release/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "hw/rtc/goldfish_rtc.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#define RTC_TIME_LOW 0x00
|
||||
#define RTC_TIME_HIGH 0x04
|
||||
#define RTC_ALARM_LOW 0x08
|
||||
#define RTC_ALARM_HIGH 0x0c
|
||||
#define RTC_IRQ_ENABLED 0x10
|
||||
#define RTC_CLEAR_ALARM 0x14
|
||||
#define RTC_ALARM_STATUS 0x18
|
||||
#define RTC_CLEAR_INTERRUPT 0x1c
|
||||
|
||||
static void goldfish_rtc_update(GoldfishRTCState *s)
|
||||
{
|
||||
qemu_set_irq(s->irq, (s->irq_pending & s->irq_enabled) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void goldfish_rtc_interrupt(void *opaque)
|
||||
{
|
||||
GoldfishRTCState *s = (GoldfishRTCState *)opaque;
|
||||
|
||||
s->alarm_running = 0;
|
||||
s->irq_pending = 1;
|
||||
goldfish_rtc_update(s);
|
||||
}
|
||||
|
||||
static uint64_t goldfish_rtc_get_count(GoldfishRTCState *s)
|
||||
{
|
||||
return s->tick_offset + (uint64_t)qemu_clock_get_ns(rtc_clock);
|
||||
}
|
||||
|
||||
static void goldfish_rtc_clear_alarm(GoldfishRTCState *s)
|
||||
{
|
||||
timer_del(s->timer);
|
||||
s->alarm_running = 0;
|
||||
}
|
||||
|
||||
static void goldfish_rtc_set_alarm(GoldfishRTCState *s)
|
||||
{
|
||||
uint64_t ticks = goldfish_rtc_get_count(s);
|
||||
uint64_t event = s->alarm_next;
|
||||
|
||||
if (event <= ticks) {
|
||||
goldfish_rtc_clear_alarm(s);
|
||||
goldfish_rtc_interrupt(s);
|
||||
} else {
|
||||
/*
|
||||
* We should be setting timer expiry to:
|
||||
* qemu_clock_get_ns(rtc_clock) + (event - ticks)
|
||||
* but this is equivalent to:
|
||||
* event - s->tick_offset
|
||||
*/
|
||||
timer_mod(s->timer, event - s->tick_offset);
|
||||
s->alarm_running = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t goldfish_rtc_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
GoldfishRTCState *s = opaque;
|
||||
uint64_t r = 0;
|
||||
|
||||
switch (offset) {
|
||||
case RTC_TIME_LOW:
|
||||
r = goldfish_rtc_get_count(s) & 0xffffffff;
|
||||
break;
|
||||
case RTC_TIME_HIGH:
|
||||
r = goldfish_rtc_get_count(s) >> 32;
|
||||
break;
|
||||
case RTC_ALARM_LOW:
|
||||
r = s->alarm_next & 0xffffffff;
|
||||
break;
|
||||
case RTC_ALARM_HIGH:
|
||||
r = s->alarm_next >> 32;
|
||||
break;
|
||||
case RTC_IRQ_ENABLED:
|
||||
r = s->irq_enabled;
|
||||
break;
|
||||
case RTC_ALARM_STATUS:
|
||||
r = s->alarm_running;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: offset 0x%x is UNIMP.\n", __func__, (uint32_t)offset);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_goldfish_rtc_read(offset, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void goldfish_rtc_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
GoldfishRTCState *s = opaque;
|
||||
uint64_t current_tick, new_tick;
|
||||
|
||||
switch (offset) {
|
||||
case RTC_TIME_LOW:
|
||||
current_tick = goldfish_rtc_get_count(s);
|
||||
new_tick = deposit64(current_tick, 0, 32, value);
|
||||
s->tick_offset += new_tick - current_tick;
|
||||
break;
|
||||
case RTC_TIME_HIGH:
|
||||
current_tick = goldfish_rtc_get_count(s);
|
||||
new_tick = deposit64(current_tick, 32, 32, value);
|
||||
s->tick_offset += new_tick - current_tick;
|
||||
break;
|
||||
case RTC_ALARM_LOW:
|
||||
s->alarm_next = deposit64(s->alarm_next, 0, 32, value);
|
||||
goldfish_rtc_set_alarm(s);
|
||||
break;
|
||||
case RTC_ALARM_HIGH:
|
||||
s->alarm_next = deposit64(s->alarm_next, 32, 32, value);
|
||||
break;
|
||||
case RTC_IRQ_ENABLED:
|
||||
s->irq_enabled = (uint32_t)(value & 0x1);
|
||||
goldfish_rtc_update(s);
|
||||
break;
|
||||
case RTC_CLEAR_ALARM:
|
||||
goldfish_rtc_clear_alarm(s);
|
||||
break;
|
||||
case RTC_CLEAR_INTERRUPT:
|
||||
s->irq_pending = 0;
|
||||
goldfish_rtc_update(s);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: offset 0x%x is UNIMP.\n", __func__, (uint32_t)offset);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_goldfish_rtc_write(offset, value);
|
||||
}
|
||||
|
||||
static int goldfish_rtc_pre_save(void *opaque)
|
||||
{
|
||||
uint64_t delta;
|
||||
GoldfishRTCState *s = opaque;
|
||||
|
||||
/*
|
||||
* We want to migrate this offset, which sounds straightforward.
|
||||
* Unfortunately, we cannot directly pass tick_offset because
|
||||
* rtc_clock on destination Host might not be same source Host.
|
||||
*
|
||||
* To tackle, this we pass tick_offset relative to vm_clock from
|
||||
* source Host and make it relative to rtc_clock at destination Host.
|
||||
*/
|
||||
delta = qemu_clock_get_ns(rtc_clock) -
|
||||
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
s->tick_offset_vmstate = s->tick_offset + delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int goldfish_rtc_post_load(void *opaque, int version_id)
|
||||
{
|
||||
uint64_t delta;
|
||||
GoldfishRTCState *s = opaque;
|
||||
|
||||
/*
|
||||
* We extract tick_offset from tick_offset_vmstate by doing
|
||||
* reverse math compared to pre_save() function.
|
||||
*/
|
||||
delta = qemu_clock_get_ns(rtc_clock) -
|
||||
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
s->tick_offset = s->tick_offset_vmstate - delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps goldfish_rtc_ops = {
|
||||
.read = goldfish_rtc_read,
|
||||
.write = goldfish_rtc_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription goldfish_rtc_vmstate = {
|
||||
.name = TYPE_GOLDFISH_RTC,
|
||||
.version_id = 1,
|
||||
.pre_save = goldfish_rtc_pre_save,
|
||||
.post_load = goldfish_rtc_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(tick_offset_vmstate, GoldfishRTCState),
|
||||
VMSTATE_UINT64(alarm_next, GoldfishRTCState),
|
||||
VMSTATE_UINT32(alarm_running, GoldfishRTCState),
|
||||
VMSTATE_UINT32(irq_pending, GoldfishRTCState),
|
||||
VMSTATE_UINT32(irq_enabled, GoldfishRTCState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void goldfish_rtc_reset(DeviceState *dev)
|
||||
{
|
||||
GoldfishRTCState *s = GOLDFISH_RTC(dev);
|
||||
struct tm tm;
|
||||
|
||||
timer_del(s->timer);
|
||||
|
||||
qemu_get_timedate(&tm, 0);
|
||||
s->tick_offset = mktimegm(&tm);
|
||||
s->tick_offset *= NANOSECONDS_PER_SECOND;
|
||||
s->tick_offset -= qemu_clock_get_ns(rtc_clock);
|
||||
s->tick_offset_vmstate = 0;
|
||||
s->alarm_next = 0;
|
||||
s->alarm_running = 0;
|
||||
s->irq_pending = 0;
|
||||
s->irq_enabled = 0;
|
||||
}
|
||||
|
||||
static void goldfish_rtc_realize(DeviceState *d, Error **errp)
|
||||
{
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(d);
|
||||
GoldfishRTCState *s = GOLDFISH_RTC(d);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_rtc_ops, s,
|
||||
"goldfish_rtc", 0x24);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
|
||||
}
|
||||
|
||||
static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = goldfish_rtc_realize;
|
||||
dc->reset = goldfish_rtc_reset;
|
||||
dc->vmsd = &goldfish_rtc_vmstate;
|
||||
}
|
||||
|
||||
static const TypeInfo goldfish_rtc_info = {
|
||||
.name = TYPE_GOLDFISH_RTC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(GoldfishRTCState),
|
||||
.class_init = goldfish_rtc_class_init,
|
||||
};
|
||||
|
||||
static void goldfish_rtc_register_types(void)
|
||||
{
|
||||
type_register_static(&goldfish_rtc_info);
|
||||
}
|
||||
|
||||
type_init(goldfish_rtc_register_types)
|
@ -23,3 +23,7 @@ m48txx_nvram_io_read(uint64_t addr, uint64_t value) "io read addr:0x%04" PRIx64
|
||||
m48txx_nvram_io_write(uint64_t addr, uint64_t value) "io write addr:0x%04" PRIx64 " value:0x%02" PRIx64
|
||||
m48txx_nvram_mem_read(uint32_t addr, uint32_t value) "mem read addr:0x%04x value:0x%02x"
|
||||
m48txx_nvram_mem_write(uint32_t addr, uint32_t value) "mem write addr:0x%04x value:0x%02x"
|
||||
|
||||
# goldfish_rtc.c
|
||||
goldfish_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
|
||||
goldfish_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
|
||||
|
@ -44,6 +44,7 @@ enum {
|
||||
VIRT_DEBUG,
|
||||
VIRT_MROM,
|
||||
VIRT_TEST,
|
||||
VIRT_RTC,
|
||||
VIRT_CLINT,
|
||||
VIRT_PLIC,
|
||||
VIRT_UART0,
|
||||
@ -57,6 +58,7 @@ enum {
|
||||
|
||||
enum {
|
||||
UART0_IRQ = 10,
|
||||
RTC_IRQ = 11,
|
||||
VIRTIO_IRQ = 1, /* 1 to 8 */
|
||||
VIRTIO_COUNT = 8,
|
||||
PCIE_IRQ = 0x20, /* 32 to 35 */
|
||||
|
46
include/hw/rtc/goldfish_rtc.h
Normal file
46
include/hw/rtc/goldfish_rtc.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Goldfish virtual platform RTC
|
||||
*
|
||||
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* For more details on Google Goldfish virtual platform refer:
|
||||
* https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_RTC_GOLDFISH_RTC_H
|
||||
#define HW_RTC_GOLDFISH_RTC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_GOLDFISH_RTC "goldfish_rtc"
|
||||
#define GOLDFISH_RTC(obj) \
|
||||
OBJECT_CHECK(GoldfishRTCState, (obj), TYPE_GOLDFISH_RTC)
|
||||
|
||||
typedef struct GoldfishRTCState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
QEMUTimer *timer;
|
||||
qemu_irq irq;
|
||||
|
||||
uint64_t tick_offset;
|
||||
uint64_t tick_offset_vmstate;
|
||||
uint64_t alarm_next;
|
||||
uint32_t alarm_running;
|
||||
uint32_t irq_pending;
|
||||
uint32_t irq_enabled;
|
||||
} GoldfishRTCState;
|
||||
|
||||
#endif
|
@ -303,7 +303,12 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
{
|
||||
if (n < 32) {
|
||||
return gdb_get_reg64(mem_buf, env->fpr[n]);
|
||||
if (env->misa & RVD) {
|
||||
return gdb_get_reg64(mem_buf, env->fpr[n]);
|
||||
}
|
||||
if (env->misa & RVF) {
|
||||
return gdb_get_reg32(mem_buf, env->fpr[n]);
|
||||
}
|
||||
/* there is hole between ft11 and fflags in fpu.xml */
|
||||
} else if (n < 36 && n > 32) {
|
||||
target_ulong val = 0;
|
||||
@ -403,23 +408,20 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
{
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
CPURISCVState *env = &cpu->env;
|
||||
#if defined(TARGET_RISCV32)
|
||||
if (env->misa & RVF) {
|
||||
if (env->misa & RVD) {
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
|
||||
36, "riscv-64bit-fpu.xml", 0);
|
||||
} else if (env->misa & RVF) {
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
|
||||
36, "riscv-32bit-fpu.xml", 0);
|
||||
}
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
240, "riscv-32bit-csr.xml", 0);
|
||||
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
|
||||
1, "riscv-32bit-virtual.xml", 0);
|
||||
#elif defined(TARGET_RISCV64)
|
||||
if (env->misa & RVF) {
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
|
||||
36, "riscv-64bit-fpu.xml", 0);
|
||||
}
|
||||
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
240, "riscv-64bit-csr.xml", 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user