Compare commits
	
		
			265 Commits
		
	
	
		
			pull-input
			...
			prep-for-u
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					21143b615a | ||
| 
						 | 
					fd3ece2533 | ||
| 
						 | 
					2c3445bb85 | ||
| 
						 | 
					7602e3e4a3 | ||
| 
						 | 
					613c12ec28 | ||
| 
						 | 
					5c1e1890bf | ||
| 
						 | 
					c2804ee6c0 | ||
| 
						 | 
					16c358e96e | ||
| 
						 | 
					be813ef02d | ||
| 
						 | 
					2396187076 | ||
| 
						 | 
					01207d0b78 | ||
| 
						 | 
					0ca540dbae | ||
| 
						 | 
					2a7a1a56d1 | ||
| 
						 | 
					5d371f41b4 | ||
| 
						 | 
					5223070c47 | ||
| 
						 | 
					59ca664ef8 | ||
| 
						 | 
					bceae7697f | ||
| 
						 | 
					b0b58195e4 | ||
| 
						 | 
					6299659f54 | ||
| 
						 | 
					b86b05ed60 | ||
| 
						 | 
					515b943a91 | ||
| 
						 | 
					4b35991a3b | ||
| 
						 | 
					dad1fcab91 | ||
| 
						 | 
					ed9b103d3e | ||
| 
						 | 
					c57ec3249e | ||
| 
						 | 
					13f65b2e10 | ||
| 
						 | 
					b4e5a4bffd | ||
| 
						 | 
					263cf4367f | ||
| 
						 | 
					dc65540465 | ||
| 
						 | 
					ac41881b48 | ||
| 
						 | 
					fe6c53b4bb | ||
| 
						 | 
					b0f15a5d56 | ||
| 
						 | 
					118760dfc9 | ||
| 
						 | 
					b304bf0021 | ||
| 
						 | 
					3f1506704e | ||
| 
						 | 
					0c126db27c | ||
| 
						 | 
					72c1d3af6e | ||
| 
						 | 
					2b194951c5 | ||
| 
						 | 
					c8f8f9fb2b | ||
| 
						 | 
					d2f41a1169 | ||
| 
						 | 
					43a32ed68f | ||
| 
						 | 
					b29c8f115d | ||
| 
						 | 
					0624976f61 | ||
| 
						 | 
					7c2cb42b50 | ||
| 
						 | 
					af5199347a | ||
| 
						 | 
					c9dd4074df | ||
| 
						 | 
					9b74d0d598 | ||
| 
						 | 
					4b87dc4c97 | ||
| 
						 | 
					dbb2a1326a | ||
| 
						 | 
					c3aa84b68f | ||
| 
						 | 
					e9d818b8b1 | ||
| 
						 | 
					cbc14e6f28 | ||
| 
						 | 
					16513b1b45 | ||
| 
						 | 
					e22492d332 | ||
| 
						 | 
					919372251c | ||
| 
						 | 
					863d7c9105 | ||
| 
						 | 
					12b316d4c1 | ||
| 
						 | 
					6cd859aa8a | ||
| 
						 | 
					b4c85ddcec | ||
| 
						 | 
					38ee14f4f3 | ||
| 
						 | 
					e3c1adf16e | ||
| 
						 | 
					2e7bcdb99a | ||
| 
						 | 
					5264917bcf | ||
| 
						 | 
					98bc3ab0f2 | ||
| 
						 | 
					220c8ed536 | ||
| 
						 | 
					f1b7e0e498 | ||
| 
						 | 
					175f099b30 | ||
| 
						 | 
					15d914b18d | ||
| 
						 | 
					262f6f5140 | ||
| 
						 | 
					4a4fcdf6df | ||
| 
						 | 
					4900116e6f | ||
| 
						 | 
					8f480de0c9 | ||
| 
						 | 
					5d12f961c6 | ||
| 
						 | 
					6e1f0a55a1 | ||
| 
						 | 
					8e46bbf362 | ||
| 
						 | 
					ddfa83ea06 | ||
| 
						 | 
					6cb46e1e90 | ||
| 
						 | 
					8dcf525abc | ||
| 
						 | 
					f8e2484389 | ||
| 
						 | 
					523fdc08cc | ||
| 
						 | 
					017a86f7ad | ||
| 
						 | 
					2e796c7621 | ||
| 
						 | 
					8d8db193f2 | ||
| 
						 | 
					a51a6b6ad5 | ||
| 
						 | 
					f029341494 | ||
| 
						 | 
					7763ffa017 | ||
| 
						 | 
					3353d0dcc3 | ||
| 
						 | 
					82295d8a2d | ||
| 
						 | 
					464400f6a5 | ||
| 
						 | 
					4fed9421e9 | ||
| 
						 | 
					ac4df4e608 | ||
| 
						 | 
					fd8cec932c | ||
| 
						 | 
					f53f3d0a00 | ||
| 
						 | 
					d7c698af8a | ||
| 
						 | 
					6570025e53 | ||
| 
						 | 
					80aaa0741f | ||
| 
						 | 
					6fc0303b95 | ||
| 
						 | 
					bb2b045034 | ||
| 
						 | 
					c3f8d28e45 | ||
| 
						 | 
					4089f7c6a0 | ||
| 
						 | 
					2c02f88780 | ||
| 
						 | 
					4c288acbd6 | ||
| 
						 | 
					9c83ffd859 | ||
| 
						 | 
					eb909c7f72 | ||
| 
						 | 
					c75203c8d3 | ||
| 
						 | 
					c6e0bd9b70 | ||
| 
						 | 
					8ae8e904fc | ||
| 
						 | 
					d5546c5e77 | ||
| 
						 | 
					7dc74db88b | ||
| 
						 | 
					464d9f641d | ||
| 
						 | 
					078896a9ee | ||
| 
						 | 
					cd5d031e75 | ||
| 
						 | 
					50c75136be | ||
| 
						 | 
					90ce8a061b | ||
| 
						 | 
					47ea2de2d6 | ||
| 
						 | 
					f47c3f5a80 | ||
| 
						 | 
					2fa4c042bc | ||
| 
						 | 
					64bb01aa35 | ||
| 
						 | 
					b1f7d84fd2 | ||
| 
						 | 
					85c09bc016 | ||
| 
						 | 
					7e7494627f | ||
| 
						 | 
					0f20ba62c3 | ||
| 
						 | 
					0ce470cd4c | ||
| 
						 | 
					a0fcac9c21 | ||
| 
						 | 
					c138593380 | ||
| 
						 | 
					3f94170be3 | ||
| 
						 | 
					7c43bca004 | ||
| 
						 | 
					f3c75d42ad | ||
| 
						 | 
					3707cd62db | ||
| 
						 | 
					7dff9abe63 | ||
| 
						 | 
					3c3b0ddefa | ||
| 
						 | 
					e5d7d2b0f5 | ||
| 
						 | 
					0a61f3b478 | ||
| 
						 | 
					ac174549b7 | ||
| 
						 | 
					57354f8f12 | ||
| 
						 | 
					557d52fa69 | ||
| 
						 | 
					e8f7b27b99 | ||
| 
						 | 
					b8476fc7c6 | ||
| 
						 | 
					f1064f612c | ||
| 
						 | 
					6f3dab41fb | ||
| 
						 | 
					4d82038e41 | ||
| 
						 | 
					b41da4ebb2 | ||
| 
						 | 
					2fdf78e649 | ||
| 
						 | 
					818692ff95 | ||
| 
						 | 
					e0ffe77f27 | ||
| 
						 | 
					4430e07663 | ||
| 
						 | 
					024215b242 | ||
| 
						 | 
					8203e31b54 | ||
| 
						 | 
					e13500b3c3 | ||
| 
						 | 
					f293f04ab5 | ||
| 
						 | 
					953f0f5842 | ||
| 
						 | 
					63be09365a | ||
| 
						 | 
					aa9e930c88 | ||
| 
						 | 
					56eabc7508 | ||
| 
						 | 
					111c5f54a1 | ||
| 
						 | 
					a737d3ebc8 | ||
| 
						 | 
					50f5fc0cf2 | ||
| 
						 | 
					5dffff5a47 | ||
| 
						 | 
					9b47bb490c | ||
| 
						 | 
					bb5275338d | ||
| 
						 | 
					32ea54ab5f | ||
| 
						 | 
					27b95bfe62 | ||
| 
						 | 
					9c294d5ab3 | ||
| 
						 | 
					84cab1e2f5 | ||
| 
						 | 
					e0498daab5 | ||
| 
						 | 
					71a8c019c4 | ||
| 
						 | 
					38a853375e | ||
| 
						 | 
					52a4984d97 | ||
| 
						 | 
					60511041d6 | ||
| 
						 | 
					94840e0700 | ||
| 
						 | 
					f5bc1bfa35 | ||
| 
						 | 
					3f34cf910c | ||
| 
						 | 
					61de36761b | ||
| 
						 | 
					5736245c80 | ||
| 
						 | 
					3b66da82ce | ||
| 
						 | 
					18674b2678 | ||
| 
						 | 
					6a2331d12e | ||
| 
						 | 
					133e70ee88 | ||
| 
						 | 
					eb1e7c3e51 | ||
| 
						 | 
					b36f100e17 | ||
| 
						 | 
					0658aa9cba | ||
| 
						 | 
					69b31b907b | ||
| 
						 | 
					66c3e32841 | ||
| 
						 | 
					ce8ca30b39 | ||
| 
						 | 
					6d41d146c9 | ||
| 
						 | 
					da29cb7bc7 | ||
| 
						 | 
					29a0e4e9a1 | ||
| 
						 | 
					c73860803f | ||
| 
						 | 
					28288b48a8 | ||
| 
						 | 
					fab7fe426f | ||
| 
						 | 
					1b0bd0029f | ||
| 
						 | 
					587c51f74b | ||
| 
						 | 
					5c77a786e2 | ||
| 
						 | 
					1fa6c53304 | ||
| 
						 | 
					a98eb9e99d | ||
| 
						 | 
					6a4fda3358 | ||
| 
						 | 
					e44259b6d4 | ||
| 
						 | 
					98d1eb2748 | ||
| 
						 | 
					a824bc191a | ||
| 
						 | 
					86ba37edcb | ||
| 
						 | 
					7ee19fb9d6 | ||
| 
						 | 
					3d1140bf3e | ||
| 
						 | 
					097ec5d850 | ||
| 
						 | 
					f5c0f7f981 | ||
| 
						 | 
					67a33f3727 | ||
| 
						 | 
					74698350ca | ||
| 
						 | 
					f53f81e08b | ||
| 
						 | 
					968e76bcab | ||
| 
						 | 
					cea4e57473 | ||
| 
						 | 
					2c0c52ae62 | ||
| 
						 | 
					b24d0b472b | ||
| 
						 | 
					ab9408a2d1 | ||
| 
						 | 
					3fd0aadfc1 | ||
| 
						 | 
					e16a626b82 | ||
| 
						 | 
					f026da7830 | ||
| 
						 | 
					cac7f0ba4a | ||
| 
						 | 
					e072fe796e | ||
| 
						 | 
					dbcc48fa8f | ||
| 
						 | 
					88e33d08c9 | ||
| 
						 | 
					5177d2ca93 | ||
| 
						 | 
					ed8ac5686a | ||
| 
						 | 
					354a6decf1 | ||
| 
						 | 
					959e9c9d1e | ||
| 
						 | 
					4f17e9c738 | ||
| 
						 | 
					595c6eefb7 | ||
| 
						 | 
					5cb151acb1 | ||
| 
						 | 
					bc80838f86 | ||
| 
						 | 
					d3f9df8fb8 | ||
| 
						 | 
					d32404fe42 | ||
| 
						 | 
					2009227fbe | ||
| 
						 | 
					4b98eeef50 | ||
| 
						 | 
					5e591d8812 | ||
| 
						 | 
					ee6e02c0ac | ||
| 
						 | 
					3c3cbbdc84 | ||
| 
						 | 
					59800ec8e5 | ||
| 
						 | 
					4e38181979 | ||
| 
						 | 
					3052f0d594 | ||
| 
						 | 
					09aa9a526a | ||
| 
						 | 
					6cd8712c5f | ||
| 
						 | 
					7a7c05d77d | ||
| 
						 | 
					363248e8c9 | ||
| 
						 | 
					0dc083fe10 | ||
| 
						 | 
					ca480de664 | ||
| 
						 | 
					135a129a1c | ||
| 
						 | 
					9c06a1f79f | ||
| 
						 | 
					88ccd23a0c | ||
| 
						 | 
					401949176c | ||
| 
						 | 
					0bfe9299da | ||
| 
						 | 
					81d2fb4dfd | ||
| 
						 | 
					6475c9f05c | ||
| 
						 | 
					a5100e752b | ||
| 
						 | 
					993c91a0e9 | ||
| 
						 | 
					b51910baf2 | ||
| 
						 | 
					974a196d7f | ||
| 
						 | 
					f19e00d776 | ||
| 
						 | 
					76ca310a19 | ||
| cd98d390ae | |||
| 
						 | 
					8a3ae9109e | ||
| 
						 | 
					4cf2348026 | ||
| 
						 | 
					4fa4ce7107 | ||
| 
						 | 
					fae0864573 | ||
| 
						 | 
					75b7931ec6 | ||
| 
						 | 
					f9a49dfa02 | ||
| 
						 | 
					9ba3cf540f | ||
| 
						 | 
					d77f7779b4 | 
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -13,6 +13,9 @@
 | 
			
		||||
[submodule "roms/openbios"]
 | 
			
		||||
	path = roms/openbios
 | 
			
		||||
	url = git://git.qemu-project.org/openbios.git
 | 
			
		||||
[submodule "roms/openhackware"]
 | 
			
		||||
	path = roms/openhackware
 | 
			
		||||
	url = git://git.qemu-project.org/openhackware.git
 | 
			
		||||
[submodule "roms/qemu-palcode"]
 | 
			
		||||
	path = roms/qemu-palcode
 | 
			
		||||
	url = git://github.com/rth7680/qemu-palcode.git
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,6 @@ Guest CPU Cores (KVM):
 | 
			
		||||
----------------------
 | 
			
		||||
 | 
			
		||||
Overall
 | 
			
		||||
M: Gleb Natapov <gleb@redhat.com>
 | 
			
		||||
M: Paolo Bonzini <pbonzini@redhat.com>
 | 
			
		||||
L: kvm@vger.kernel.org
 | 
			
		||||
S: Supported
 | 
			
		||||
@@ -176,12 +175,14 @@ S: Maintained
 | 
			
		||||
F: target-ppc/kvm.c
 | 
			
		||||
 | 
			
		||||
S390
 | 
			
		||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
 | 
			
		||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
 | 
			
		||||
M: Alexander Graf <agraf@suse.de>
 | 
			
		||||
S: Maintained
 | 
			
		||||
F: target-s390x/kvm.c
 | 
			
		||||
F: hw/intc/s390_flic.[hc]
 | 
			
		||||
 | 
			
		||||
X86
 | 
			
		||||
M: Gleb Natapov <gleb@redhat.com>
 | 
			
		||||
M: Marcelo Tosatti <mtosatti@redhat.com>
 | 
			
		||||
L: kvm@vger.kernel.org
 | 
			
		||||
S: Supported
 | 
			
		||||
@@ -495,10 +496,13 @@ F: hw/s390x/s390-*.c
 | 
			
		||||
 | 
			
		||||
S390 Virtio-ccw
 | 
			
		||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
 | 
			
		||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
 | 
			
		||||
M: Alexander Graf <agraf@suse.de>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: hw/s390x/s390-virtio-ccw.c
 | 
			
		||||
F: hw/s390x/css.[hc]
 | 
			
		||||
F: hw/s390x/sclp*.[hc]
 | 
			
		||||
F: hw/s390x/ipl*.[hc]
 | 
			
		||||
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
 | 
			
		||||
 | 
			
		||||
UniCore32 Machines
 | 
			
		||||
@@ -629,6 +633,7 @@ F: hw/block/virtio-blk.c
 | 
			
		||||
 | 
			
		||||
virtio-ccw
 | 
			
		||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
 | 
			
		||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: hw/s390x/virtio-ccw.[hc]
 | 
			
		||||
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -399,7 +399,7 @@ endif
 | 
			
		||||
		$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
 | 
			
		||||
	done
 | 
			
		||||
	for d in $(TARGET_DIRS); do \
 | 
			
		||||
	$(MAKE) -C $$d $@ || exit 1 ; \
 | 
			
		||||
	$(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
 | 
			
		||||
        done
 | 
			
		||||
 | 
			
		||||
# various test targets
 | 
			
		||||
 
 | 
			
		||||
@@ -21,11 +21,6 @@ block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
 | 
			
		||||
 | 
			
		||||
block-obj-m = block/
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 | 
			
		||||
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 | 
			
		||||
# only pull in the actual virtio-9p device if we also enabled virtio.
 | 
			
		||||
CONFIG_REALLY_VIRTFS=y
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
# smartcard
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								arch_init.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								arch_init.c
									
									
									
									
									
								
							@@ -164,8 +164,9 @@ static struct {
 | 
			
		||||
    uint8_t *encoded_buf;
 | 
			
		||||
    /* buffer for storing page content */
 | 
			
		||||
    uint8_t *current_buf;
 | 
			
		||||
    /* Cache for XBZRLE */
 | 
			
		||||
    /* Cache for XBZRLE, Protected by lock. */
 | 
			
		||||
    PageCache *cache;
 | 
			
		||||
    QemuMutex lock;
 | 
			
		||||
} XBZRLE = {
 | 
			
		||||
    .encoded_buf = NULL,
 | 
			
		||||
    .current_buf = NULL,
 | 
			
		||||
@@ -174,16 +175,52 @@ static struct {
 | 
			
		||||
/* buffer used for XBZRLE decoding */
 | 
			
		||||
static uint8_t *xbzrle_decoded_buf;
 | 
			
		||||
 | 
			
		||||
static void XBZRLE_cache_lock(void)
 | 
			
		||||
{
 | 
			
		||||
    if (migrate_use_xbzrle())
 | 
			
		||||
        qemu_mutex_lock(&XBZRLE.lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void XBZRLE_cache_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
    if (migrate_use_xbzrle())
 | 
			
		||||
        qemu_mutex_unlock(&XBZRLE.lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t xbzrle_cache_resize(int64_t new_size)
 | 
			
		||||
{
 | 
			
		||||
    PageCache *new_cache, *cache_to_free;
 | 
			
		||||
 | 
			
		||||
    if (new_size < TARGET_PAGE_SIZE) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* no need to lock, the current thread holds qemu big lock */
 | 
			
		||||
    if (XBZRLE.cache != NULL) {
 | 
			
		||||
        return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) *
 | 
			
		||||
            TARGET_PAGE_SIZE;
 | 
			
		||||
        /* check XBZRLE.cache again later */
 | 
			
		||||
        if (pow2floor(new_size) == migrate_xbzrle_cache_size()) {
 | 
			
		||||
            return pow2floor(new_size);
 | 
			
		||||
        }
 | 
			
		||||
        new_cache = cache_init(new_size / TARGET_PAGE_SIZE,
 | 
			
		||||
                                        TARGET_PAGE_SIZE);
 | 
			
		||||
        if (!new_cache) {
 | 
			
		||||
            DPRINTF("Error creating cache\n");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        XBZRLE_cache_lock();
 | 
			
		||||
        /* the XBZRLE.cache may have be destroyed, check it again */
 | 
			
		||||
        if (XBZRLE.cache != NULL) {
 | 
			
		||||
            cache_to_free = XBZRLE.cache;
 | 
			
		||||
            XBZRLE.cache = new_cache;
 | 
			
		||||
        } else {
 | 
			
		||||
            cache_to_free = new_cache;
 | 
			
		||||
        }
 | 
			
		||||
        XBZRLE_cache_unlock();
 | 
			
		||||
 | 
			
		||||
        cache_fini(cache_to_free);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return pow2floor(new_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -539,6 +576,8 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
 | 
			
		||||
            ret = ram_control_save_page(f, block->offset,
 | 
			
		||||
                               offset, TARGET_PAGE_SIZE, &bytes_sent);
 | 
			
		||||
 | 
			
		||||
            XBZRLE_cache_lock();
 | 
			
		||||
 | 
			
		||||
            current_addr = block->offset + offset;
 | 
			
		||||
            if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
 | 
			
		||||
                if (ret != RAM_SAVE_CONTROL_DELAYED) {
 | 
			
		||||
@@ -587,6 +626,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
 | 
			
		||||
                acct_info.norm_pages++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            XBZRLE_cache_unlock();
 | 
			
		||||
            /* if page is unmodified, continue to the next */
 | 
			
		||||
            if (bytes_sent > 0) {
 | 
			
		||||
                last_sent_block = block;
 | 
			
		||||
@@ -654,6 +694,7 @@ static void migration_end(void)
 | 
			
		||||
        migration_bitmap = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    XBZRLE_cache_lock();
 | 
			
		||||
    if (XBZRLE.cache) {
 | 
			
		||||
        cache_fini(XBZRLE.cache);
 | 
			
		||||
        g_free(XBZRLE.cache);
 | 
			
		||||
@@ -663,6 +704,7 @@ static void migration_end(void)
 | 
			
		||||
        XBZRLE.encoded_buf = NULL;
 | 
			
		||||
        XBZRLE.current_buf = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    XBZRLE_cache_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ram_migration_cancel(void *opaque)
 | 
			
		||||
@@ -693,13 +735,17 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
 | 
			
		||||
    dirty_rate_high_cnt = 0;
 | 
			
		||||
 | 
			
		||||
    if (migrate_use_xbzrle()) {
 | 
			
		||||
        qemu_mutex_lock_iothread();
 | 
			
		||||
        XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
 | 
			
		||||
                                  TARGET_PAGE_SIZE,
 | 
			
		||||
                                  TARGET_PAGE_SIZE);
 | 
			
		||||
        if (!XBZRLE.cache) {
 | 
			
		||||
            qemu_mutex_unlock_iothread();
 | 
			
		||||
            DPRINTF("Error creating cache\n");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        qemu_mutex_init(&XBZRLE.lock);
 | 
			
		||||
        qemu_mutex_unlock_iothread();
 | 
			
		||||
 | 
			
		||||
        /* We prefer not to abort if there is no memory */
 | 
			
		||||
        XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								block.c
									
									
									
									
									
								
							@@ -935,7 +935,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 | 
			
		||||
 | 
			
		||||
    bdrv_refresh_limits(bs);
 | 
			
		||||
    assert(bdrv_opt_mem_align(bs) != 0);
 | 
			
		||||
    assert(bs->request_alignment != 0);
 | 
			
		||||
    assert((bs->request_alignment != 0) || bs->sg);
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
    if (bs->is_temporary) {
 | 
			
		||||
@@ -1017,7 +1017,12 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
 | 
			
		||||
            ret = -EINVAL;
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!drv->bdrv_needs_filename) {
 | 
			
		||||
            qdict_del(*options, "filename");
 | 
			
		||||
        } else {
 | 
			
		||||
            filename = qdict_get_str(*options, "filename");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!drv->bdrv_file_open) {
 | 
			
		||||
@@ -1229,6 +1234,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
 | 
			
		||||
        ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL,
 | 
			
		||||
                             &local_err);
 | 
			
		||||
        if (!ret) {
 | 
			
		||||
            drv = bs->drv;
 | 
			
		||||
            goto done;
 | 
			
		||||
        } else if (bs->drv) {
 | 
			
		||||
            goto close_and_fail;
 | 
			
		||||
@@ -1847,11 +1853,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
 | 
			
		||||
    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
 | 
			
		||||
            bs_src->device_name);
 | 
			
		||||
    bs_dest->device_list = bs_src->device_list;
 | 
			
		||||
 | 
			
		||||
    /* keep the same entry in graph_bdrv_states
 | 
			
		||||
     * We do want to swap name but don't want to swap linked list entries
 | 
			
		||||
     */
 | 
			
		||||
    bs_dest->node_list   = bs_src->node_list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -1870,6 +1871,17 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
 | 
			
		||||
{
 | 
			
		||||
    BlockDriverState tmp;
 | 
			
		||||
 | 
			
		||||
    /* The code needs to swap the node_name but simply swapping node_list won't
 | 
			
		||||
     * work so first remove the nodes from the graph list, do the swap then
 | 
			
		||||
     * insert them back if needed.
 | 
			
		||||
     */
 | 
			
		||||
    if (bs_new->node_name[0] != '\0') {
 | 
			
		||||
        QTAILQ_REMOVE(&graph_bdrv_states, bs_new, node_list);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs_old->node_name[0] != '\0') {
 | 
			
		||||
        QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* bs_new must be anonymous and shouldn't have anything fancy enabled */
 | 
			
		||||
    assert(bs_new->device_name[0] == '\0');
 | 
			
		||||
    assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
 | 
			
		||||
@@ -1898,6 +1910,14 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
 | 
			
		||||
    assert(bs_new->io_limits_enabled == false);
 | 
			
		||||
    assert(!throttle_have_timer(&bs_new->throttle_state));
 | 
			
		||||
 | 
			
		||||
    /* insert the nodes back into the graph node list if needed */
 | 
			
		||||
    if (bs_new->node_name[0] != '\0') {
 | 
			
		||||
        QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_new, node_list);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs_old->node_name[0] != '\0') {
 | 
			
		||||
        QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bdrv_rebind(bs_new);
 | 
			
		||||
    bdrv_rebind(bs_old);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,21 +3,12 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Pipe handling mechanism in AIO implementation is derived from
 | 
			
		||||
 * block/rbd.c. Hence,
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>,
 | 
			
		||||
 *                         Josh Durgin <josh.durgin@dreamhost.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributions after 2012-01-13 are licensed under the terms of the
 | 
			
		||||
 * GNU GPL, version 2 or (at your option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
#include <glusterfs/api/glfs.h>
 | 
			
		||||
#include "block/block_int.h"
 | 
			
		||||
#include "qemu/sockets.h"
 | 
			
		||||
#include "qemu/uri.h"
 | 
			
		||||
 | 
			
		||||
typedef struct GlusterAIOCB {
 | 
			
		||||
@@ -32,9 +23,6 @@ typedef struct BDRVGlusterState {
 | 
			
		||||
    struct glfs_fd *fd;
 | 
			
		||||
} BDRVGlusterState;
 | 
			
		||||
 | 
			
		||||
#define GLUSTER_FD_READ  0
 | 
			
		||||
#define GLUSTER_FD_WRITE 1
 | 
			
		||||
 | 
			
		||||
typedef struct GlusterConf {
 | 
			
		||||
    char *server;
 | 
			
		||||
    int port;
 | 
			
		||||
 
 | 
			
		||||
@@ -1231,12 +1231,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
 | 
			
		||||
    bs->request_alignment = iscsilun->block_size;
 | 
			
		||||
 | 
			
		||||
    /* Medium changer or tape. We dont have any emulation for this so this must
 | 
			
		||||
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
 | 
			
		||||
     * to read from the device to guess the image format.
 | 
			
		||||
    /* We don't have any emulation for devices other than disks and CD-ROMs, so
 | 
			
		||||
     * this must be sg ioctl compatible. We force it to be sg, otherwise qemu
 | 
			
		||||
     * will try to read from the device to guess the image format.
 | 
			
		||||
     */
 | 
			
		||||
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
 | 
			
		||||
        iscsilun->type == TYPE_TAPE) {
 | 
			
		||||
    if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {
 | 
			
		||||
        bs->sg = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -520,9 +520,6 @@ static void mirror_complete(BlockJob *job, Error **errp)
 | 
			
		||||
 | 
			
		||||
    ret = bdrv_open_backing_file(s->target, NULL, &local_err);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        char backing_filename[PATH_MAX];
 | 
			
		||||
        bdrv_get_full_backing_filename(s->target, backing_filename,
 | 
			
		||||
                                       sizeof(backing_filename));
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -336,6 +336,17 @@ error:
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void raw_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                               Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The filename does not have to be prefixed by the protocol name, since
 | 
			
		||||
     * "file" is the default protocol; therefore, the return value of this
 | 
			
		||||
     * function call can be ignored. */
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QemuOptsList raw_runtime_opts = {
 | 
			
		||||
    .name = "raw",
 | 
			
		||||
    .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
 | 
			
		||||
@@ -1230,6 +1241,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
 | 
			
		||||
    int result = 0;
 | 
			
		||||
    int64_t total_size = 0;
 | 
			
		||||
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    /* Read out options */
 | 
			
		||||
    while (options && options->name) {
 | 
			
		||||
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
 | 
			
		||||
@@ -1412,6 +1425,7 @@ static BlockDriver bdrv_file = {
 | 
			
		||||
    .instance_size = sizeof(BDRVRawState),
 | 
			
		||||
    .bdrv_needs_filename = true,
 | 
			
		||||
    .bdrv_probe = NULL, /* no probe for protocols */
 | 
			
		||||
    .bdrv_parse_filename = raw_parse_filename,
 | 
			
		||||
    .bdrv_file_open = raw_open,
 | 
			
		||||
    .bdrv_reopen_prepare = raw_reopen_prepare,
 | 
			
		||||
    .bdrv_reopen_commit = raw_reopen_commit,
 | 
			
		||||
 
 | 
			
		||||
@@ -251,6 +251,17 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
                               Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    /* The filename does not have to be prefixed by the protocol name, since
 | 
			
		||||
     * "file" is the default protocol; therefore, the return value of this
 | 
			
		||||
     * function call can be ignored. */
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QemuOptsList raw_runtime_opts = {
 | 
			
		||||
    .name = "raw",
 | 
			
		||||
    .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
 | 
			
		||||
@@ -470,6 +481,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
 | 
			
		||||
    int fd;
 | 
			
		||||
    int64_t total_size = 0;
 | 
			
		||||
 | 
			
		||||
    strstart(filename, "file:", &filename);
 | 
			
		||||
 | 
			
		||||
    /* Read out options */
 | 
			
		||||
    while (options && options->name) {
 | 
			
		||||
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
 | 
			
		||||
@@ -504,6 +517,7 @@ static BlockDriver bdrv_file = {
 | 
			
		||||
    .protocol_name	= "file",
 | 
			
		||||
    .instance_size	= sizeof(BDRVRawState),
 | 
			
		||||
    .bdrv_needs_filename = true,
 | 
			
		||||
    .bdrv_parse_filename = raw_parse_filename,
 | 
			
		||||
    .bdrv_file_open	= raw_open,
 | 
			
		||||
    .bdrv_close		= raw_close,
 | 
			
		||||
    .bdrv_create	= raw_create,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								blockdev.c
									
									
									
									
									
								
							@@ -2266,6 +2266,7 @@ void qmp_block_job_complete(const char *device, Error **errp)
 | 
			
		||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    QmpOutputVisitor *ov = qmp_output_visitor_new();
 | 
			
		||||
    DriveInfo *dinfo;
 | 
			
		||||
    QObject *obj;
 | 
			
		||||
    QDict *qdict;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
@@ -2282,8 +2283,10 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 | 
			
		||||
     *
 | 
			
		||||
     * For now, simply forbidding the combination for all drivers will do. */
 | 
			
		||||
    if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
 | 
			
		||||
        bool direct = options->cache->has_direct && options->cache->direct;
 | 
			
		||||
        if (!options->has_cache && !direct) {
 | 
			
		||||
        bool direct = options->has_cache &&
 | 
			
		||||
                      options->cache->has_direct &&
 | 
			
		||||
                      options->cache->direct;
 | 
			
		||||
        if (!direct) {
 | 
			
		||||
            error_setg(errp, "aio=native requires cache.direct=true");
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
@@ -2301,12 +2304,18 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 | 
			
		||||
 | 
			
		||||
    qdict_flatten(qdict);
 | 
			
		||||
 | 
			
		||||
    blockdev_init(NULL, qdict, &local_err);
 | 
			
		||||
    dinfo = blockdev_init(NULL, qdict, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bdrv_key_required(dinfo->bdrv)) {
 | 
			
		||||
        drive_uninit(dinfo);
 | 
			
		||||
        error_setg(errp, "blockdev-add doesn't support encrypted devices");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
    qmp_output_visitor_cleanup(ov);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										114
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -14,13 +14,14 @@ fi
 | 
			
		||||
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
 | 
			
		||||
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
 | 
			
		||||
TMPO="${TMPDIR1}/${TMPB}.o"
 | 
			
		||||
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
 | 
			
		||||
TMPL="${TMPDIR1}/${TMPB}.lo"
 | 
			
		||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
 | 
			
		||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
 | 
			
		||||
 | 
			
		||||
# NB: do not call "exit" in the trap handler; this is buggy with some shells;
 | 
			
		||||
# see <1285349658-3122-1-git-send-email-loic.minier@linaro.org>
 | 
			
		||||
trap "rm -f $TMPC $TMPO $TMPE" EXIT INT QUIT TERM
 | 
			
		||||
trap "rm -f $TMPC $TMPO $TMPCXX $TMPE" EXIT INT QUIT TERM
 | 
			
		||||
rm -f config.log
 | 
			
		||||
 | 
			
		||||
# Print a helpful header at the top of config.log
 | 
			
		||||
@@ -30,19 +31,6 @@ printf " '%s'" "$0" "$@" >> config.log
 | 
			
		||||
echo >> config.log
 | 
			
		||||
echo "#" >> config.log
 | 
			
		||||
 | 
			
		||||
# Save the configure command line for later reuse.
 | 
			
		||||
cat <<EOD >config.status
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Generated by configure.
 | 
			
		||||
# Run this file to recreate the current configuration.
 | 
			
		||||
# Compiler output produced by configure, useful for debugging
 | 
			
		||||
# configure, is in config.log if it exists.
 | 
			
		||||
EOD
 | 
			
		||||
printf "exec" >>config.status
 | 
			
		||||
printf " '%s'" "$0" "$@" >>config.status
 | 
			
		||||
echo >>config.status
 | 
			
		||||
chmod +x config.status
 | 
			
		||||
 | 
			
		||||
error_exit() {
 | 
			
		||||
    echo
 | 
			
		||||
    echo "ERROR: $1"
 | 
			
		||||
@@ -54,10 +42,13 @@ error_exit() {
 | 
			
		||||
    exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_cc() {
 | 
			
		||||
    # Run the compiler, capturing its output to the log.
 | 
			
		||||
    echo $cc "$@" >> config.log
 | 
			
		||||
    $cc "$@" >> config.log 2>&1 || return $?
 | 
			
		||||
do_compiler() {
 | 
			
		||||
    # Run the compiler, capturing its output to the log. First argument
 | 
			
		||||
    # is compiler binary to execute.
 | 
			
		||||
    local compiler="$1"
 | 
			
		||||
    shift
 | 
			
		||||
    echo $compiler "$@" >> config.log
 | 
			
		||||
    $compiler "$@" >> config.log 2>&1 || return $?
 | 
			
		||||
    # Test passed. If this is an --enable-werror build, rerun
 | 
			
		||||
    # the test with -Werror and bail out if it fails. This
 | 
			
		||||
    # makes warning-generating-errors in configure test code
 | 
			
		||||
@@ -71,14 +62,39 @@ do_cc() {
 | 
			
		||||
           return 0
 | 
			
		||||
        ;;
 | 
			
		||||
    esac
 | 
			
		||||
    echo $cc -Werror "$@" >> config.log
 | 
			
		||||
    $cc -Werror "$@" >> config.log 2>&1 && return $?
 | 
			
		||||
    echo $compiler -Werror "$@" >> config.log
 | 
			
		||||
    $compiler -Werror "$@" >> config.log 2>&1 && return $?
 | 
			
		||||
    error_exit "configure test passed without -Werror but failed with -Werror." \
 | 
			
		||||
        "This is probably a bug in the configure script. The failing command" \
 | 
			
		||||
        "will be at the bottom of config.log." \
 | 
			
		||||
        "You can run configure with --disable-werror to bypass this check."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_cc() {
 | 
			
		||||
    do_compiler "$cc" "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_cxx() {
 | 
			
		||||
    do_compiler "$cxx" "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
update_cxxflags() {
 | 
			
		||||
    # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
 | 
			
		||||
    # options which some versions of GCC's C++ compiler complain about
 | 
			
		||||
    # because they only make sense for C programs.
 | 
			
		||||
    QEMU_CXXFLAGS=
 | 
			
		||||
    for arg in $QEMU_CFLAGS; do
 | 
			
		||||
        case $arg in
 | 
			
		||||
            -Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\
 | 
			
		||||
            -Wold-style-declaration|-Wold-style-definition|-Wredundant-decls)
 | 
			
		||||
                ;;
 | 
			
		||||
            *)
 | 
			
		||||
                QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg
 | 
			
		||||
                ;;
 | 
			
		||||
        esac
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
compile_object() {
 | 
			
		||||
  do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
 | 
			
		||||
}
 | 
			
		||||
@@ -373,7 +389,7 @@ sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
 | 
			
		||||
ARFLAGS="${ARFLAGS-rv}"
 | 
			
		||||
 | 
			
		||||
# default flags for all hosts
 | 
			
		||||
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
 | 
			
		||||
QEMU_CFLAGS="-fno-strict-aliasing -fno-common $QEMU_CFLAGS"
 | 
			
		||||
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
 | 
			
		||||
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
 | 
			
		||||
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
 | 
			
		||||
@@ -1340,6 +1356,19 @@ if test "$ARCH" = "unknown"; then
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Consult white-list to determine whether to enable werror
 | 
			
		||||
# by default.  Only enable by default for git builds
 | 
			
		||||
z_version=`cut -f3 -d. $source_path/VERSION`
 | 
			
		||||
 | 
			
		||||
if test -z "$werror" ; then
 | 
			
		||||
    if test -d "$source_path/.git" -a \
 | 
			
		||||
        "$linux" = "yes" ; then
 | 
			
		||||
        werror="yes"
 | 
			
		||||
    else
 | 
			
		||||
        werror="no"
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# check that the C compiler works.
 | 
			
		||||
cat > $TMPC <<EOF
 | 
			
		||||
int main(void) { return 0; }
 | 
			
		||||
@@ -1360,14 +1389,16 @@ EOF
 | 
			
		||||
 | 
			
		||||
    compile_object
 | 
			
		||||
 | 
			
		||||
    cat > $TMPC <<EOF
 | 
			
		||||
    cat > $TMPCXX <<EOF
 | 
			
		||||
extern "C" {
 | 
			
		||||
   int c_function(void);
 | 
			
		||||
}
 | 
			
		||||
int c_function(void) { return 42; }
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
    if (cc=$cxx do_cc $QEMU_CFLAGS -o $TMPE $TMPC $TMPO $LDFLAGS); then
 | 
			
		||||
    update_cxxflags
 | 
			
		||||
 | 
			
		||||
    if do_cxx $QEMU_CXXFLAGS -o $TMPE $TMPCXX $TMPO $LDFLAGS; then
 | 
			
		||||
        # C++ compiler $cxx works ok with C compiler $cc
 | 
			
		||||
        :
 | 
			
		||||
    else
 | 
			
		||||
@@ -1380,19 +1411,6 @@ else
 | 
			
		||||
    cxx=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Consult white-list to determine whether to enable werror
 | 
			
		||||
# by default.  Only enable by default for git builds
 | 
			
		||||
z_version=`cut -f3 -d. $source_path/VERSION`
 | 
			
		||||
 | 
			
		||||
if test -z "$werror" ; then
 | 
			
		||||
    if test -d "$source_path/.git" -a \
 | 
			
		||||
        "$linux" = "yes" ; then
 | 
			
		||||
        werror="yes"
 | 
			
		||||
    else
 | 
			
		||||
        werror="no"
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
 | 
			
		||||
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
 | 
			
		||||
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
 | 
			
		||||
@@ -4076,7 +4094,11 @@ echo "vhost-net support $vhost_net"
 | 
			
		||||
echo "vhost-scsi support $vhost_scsi"
 | 
			
		||||
echo "Trace backend     $trace_backend"
 | 
			
		||||
echo "Trace output file $trace_file-<pid>"
 | 
			
		||||
if test "$spice" = "yes"; then
 | 
			
		||||
echo "spice support     $spice ($spice_protocol_version/$spice_server_version)"
 | 
			
		||||
else
 | 
			
		||||
echo "spice support     $spice"
 | 
			
		||||
fi
 | 
			
		||||
echo "rbd support       $rbd"
 | 
			
		||||
echo "xfsctl support    $xfs"
 | 
			
		||||
echo "nss used          $smartcard_nss"
 | 
			
		||||
@@ -4937,6 +4959,12 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
 | 
			
		||||
    echo "CONFIG_ALPHA_DIS=y"  >> $config_target_mak
 | 
			
		||||
    echo "CONFIG_ALPHA_DIS=y"  >> config-all-disas.mak
 | 
			
		||||
  ;;
 | 
			
		||||
  aarch64)
 | 
			
		||||
    if test -n "${cxx}"; then
 | 
			
		||||
      echo "CONFIG_ARM_A64_DIS=y"  >> $config_target_mak
 | 
			
		||||
      echo "CONFIG_ARM_A64_DIS=y"  >> config-all-disas.mak
 | 
			
		||||
    fi
 | 
			
		||||
  ;;
 | 
			
		||||
  arm)
 | 
			
		||||
    echo "CONFIG_ARM_DIS=y"  >> $config_target_mak
 | 
			
		||||
    echo "CONFIG_ARM_DIS=y"  >> config-all-disas.mak
 | 
			
		||||
@@ -5105,3 +5133,17 @@ done
 | 
			
		||||
if test "$docs" = "yes" ; then
 | 
			
		||||
  mkdir -p QMP
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Save the configure command line for later reuse.
 | 
			
		||||
cat <<EOD >config.status
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Generated by configure.
 | 
			
		||||
# Run this file to recreate the current configuration.
 | 
			
		||||
# Compiler output produced by configure, useful for debugging
 | 
			
		||||
# configure, is in config.log if it exists.
 | 
			
		||||
EOD
 | 
			
		||||
printf "exec" >>config.status
 | 
			
		||||
printf " '%s'" "$0" "$@" >>config.status
 | 
			
		||||
echo >>config.status
 | 
			
		||||
chmod +x config.status
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								cpus.c
									
									
									
									
									
								
							@@ -1117,8 +1117,13 @@ void resume_all_vcpus(void)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* For temporary buffers for forming a name */
 | 
			
		||||
#define VCPU_THREAD_NAME_SIZE 16
 | 
			
		||||
 | 
			
		||||
static void qemu_tcg_init_vcpu(CPUState *cpu)
 | 
			
		||||
{
 | 
			
		||||
    char thread_name[VCPU_THREAD_NAME_SIZE];
 | 
			
		||||
 | 
			
		||||
    tcg_cpu_address_space_init(cpu, cpu->as);
 | 
			
		||||
 | 
			
		||||
    /* share a single thread for all cpus with TCG */
 | 
			
		||||
@@ -1127,8 +1132,10 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
 | 
			
		||||
        cpu->halt_cond = g_malloc0(sizeof(QemuCond));
 | 
			
		||||
        qemu_cond_init(cpu->halt_cond);
 | 
			
		||||
        tcg_halt_cond = cpu->halt_cond;
 | 
			
		||||
        qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, cpu,
 | 
			
		||||
                           QEMU_THREAD_JOINABLE);
 | 
			
		||||
        snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
 | 
			
		||||
                 cpu->cpu_index);
 | 
			
		||||
        qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thread_fn,
 | 
			
		||||
                           cpu, QEMU_THREAD_JOINABLE);
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
        cpu->hThread = qemu_thread_get_handle(cpu->thread);
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1144,11 +1151,15 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
 | 
			
		||||
 | 
			
		||||
static void qemu_kvm_start_vcpu(CPUState *cpu)
 | 
			
		||||
{
 | 
			
		||||
    char thread_name[VCPU_THREAD_NAME_SIZE];
 | 
			
		||||
 | 
			
		||||
    cpu->thread = g_malloc0(sizeof(QemuThread));
 | 
			
		||||
    cpu->halt_cond = g_malloc0(sizeof(QemuCond));
 | 
			
		||||
    qemu_cond_init(cpu->halt_cond);
 | 
			
		||||
    qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, cpu,
 | 
			
		||||
                       QEMU_THREAD_JOINABLE);
 | 
			
		||||
    snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
 | 
			
		||||
             cpu->cpu_index);
 | 
			
		||||
    qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
 | 
			
		||||
                       cpu, QEMU_THREAD_JOINABLE);
 | 
			
		||||
    while (!cpu->created) {
 | 
			
		||||
        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1156,10 +1167,14 @@ static void qemu_kvm_start_vcpu(CPUState *cpu)
 | 
			
		||||
 | 
			
		||||
static void qemu_dummy_start_vcpu(CPUState *cpu)
 | 
			
		||||
{
 | 
			
		||||
    char thread_name[VCPU_THREAD_NAME_SIZE];
 | 
			
		||||
 | 
			
		||||
    cpu->thread = g_malloc0(sizeof(QemuThread));
 | 
			
		||||
    cpu->halt_cond = g_malloc0(sizeof(QemuCond));
 | 
			
		||||
    qemu_cond_init(cpu->halt_cond);
 | 
			
		||||
    qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, cpu,
 | 
			
		||||
    snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
 | 
			
		||||
             cpu->cpu_index);
 | 
			
		||||
    qemu_thread_create(cpu->thread, thread_name, qemu_dummy_cpu_thread_fn, cpu,
 | 
			
		||||
                       QEMU_THREAD_JOINABLE);
 | 
			
		||||
    while (!cpu->created) {
 | 
			
		||||
        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
 | 
			
		||||
 
 | 
			
		||||
@@ -47,4 +47,5 @@ CONFIG_E500=y
 | 
			
		||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 | 
			
		||||
# For PReP
 | 
			
		||||
CONFIG_MC146818RTC=y
 | 
			
		||||
CONFIG_ETSEC=y
 | 
			
		||||
CONFIG_ISA_TESTDEV=y
 | 
			
		||||
 
 | 
			
		||||
@@ -1342,7 +1342,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
 | 
			
		||||
        ASSERT(format[5] == 'L');
 | 
			
		||||
        AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
 | 
			
		||||
        if (instr->ShiftMoveWide() > 0) {
 | 
			
		||||
          AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
 | 
			
		||||
          AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return 8;
 | 
			
		||||
@@ -1391,7 +1391,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
 | 
			
		||||
    }
 | 
			
		||||
    case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
 | 
			
		||||
      if (format[3] == 'F') {  // IFPFbits.
 | 
			
		||||
        AppendToOutput("#%d", 64 - instr->FPScale());
 | 
			
		||||
        AppendToOutput("#%" PRId64, 64 - instr->FPScale());
 | 
			
		||||
        return 8;
 | 
			
		||||
      } else {
 | 
			
		||||
        AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
 | 
			
		||||
@@ -1412,23 +1412,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
 | 
			
		||||
      return 5;
 | 
			
		||||
    }
 | 
			
		||||
    case 'P': {  // IP - Conditional compare.
 | 
			
		||||
      AppendToOutput("#%d", instr->ImmCondCmp());
 | 
			
		||||
      AppendToOutput("#%" PRId64, instr->ImmCondCmp());
 | 
			
		||||
      return 2;
 | 
			
		||||
    }
 | 
			
		||||
    case 'B': {  // Bitfields.
 | 
			
		||||
      return SubstituteBitfieldImmediateField(instr, format);
 | 
			
		||||
    }
 | 
			
		||||
    case 'E': {  // IExtract.
 | 
			
		||||
      AppendToOutput("#%d", instr->ImmS());
 | 
			
		||||
      AppendToOutput("#%" PRId64, instr->ImmS());
 | 
			
		||||
      return 8;
 | 
			
		||||
    }
 | 
			
		||||
    case 'S': {  // IS - Test and branch bit.
 | 
			
		||||
      AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
 | 
			
		||||
      AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
 | 
			
		||||
                                  instr->ImmTestBranchBit40());
 | 
			
		||||
      return 2;
 | 
			
		||||
    }
 | 
			
		||||
    case 'D': {  // IDebug - HLT and BRK instructions.
 | 
			
		||||
      AppendToOutput("#0x%x", instr->ImmException());
 | 
			
		||||
      AppendToOutput("#0x%" PRIx64, instr->ImmException());
 | 
			
		||||
      return 6;
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
@@ -1598,12 +1598,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
 | 
			
		||||
      (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
 | 
			
		||||
       (instr->ExtendMode() == UXTX))) {
 | 
			
		||||
    if (instr->ImmExtendShift() > 0) {
 | 
			
		||||
      AppendToOutput(", lsl #%d", instr->ImmExtendShift());
 | 
			
		||||
      AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
 | 
			
		||||
    if (instr->ImmExtendShift() > 0) {
 | 
			
		||||
      AppendToOutput(" #%d", instr->ImmExtendShift());
 | 
			
		||||
      AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return 3;
 | 
			
		||||
@@ -1632,7 +1632,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
 | 
			
		||||
  if (!((ext == UXTX) && (shift == 0))) {
 | 
			
		||||
    AppendToOutput(", %s", extend_mode[ext]);
 | 
			
		||||
    if (shift != 0) {
 | 
			
		||||
      AppendToOutput(" #%d", instr->SizeLS());
 | 
			
		||||
      AppendToOutput(" #%" PRId64, instr->SizeLS());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return 9;
 | 
			
		||||
 
 | 
			
		||||
@@ -123,11 +123,12 @@ And it looks like this on the wire:
 | 
			
		||||
 | 
			
		||||
Flat union types avoid the nesting on the wire. They are used whenever a
 | 
			
		||||
specific field of the base type is declared as the discriminator ('type' is
 | 
			
		||||
then no longer generated). The discriminator must always be a string field.
 | 
			
		||||
then no longer generated). The discriminator must be of enumeration type.
 | 
			
		||||
The above example can then be modified as follows:
 | 
			
		||||
 | 
			
		||||
 { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] }
 | 
			
		||||
 { 'type': 'BlockdevCommonOptions',
 | 
			
		||||
   'data': { 'driver': 'str', 'readonly': 'bool' } }
 | 
			
		||||
   'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } }
 | 
			
		||||
 { 'union': 'BlockdevOptions',
 | 
			
		||||
   'base': 'BlockdevCommonOptions',
 | 
			
		||||
   'discriminator': 'driver',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								exec.c
									
									
									
									
									
								
							@@ -1029,7 +1029,7 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
 | 
			
		||||
    hpagesize = gethugepagesize(path);
 | 
			
		||||
    if (!hpagesize) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (memory < hpagesize) {
 | 
			
		||||
@@ -1038,7 +1038,7 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && !kvm_has_sync_mmu()) {
 | 
			
		||||
        fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
 | 
			
		||||
        return NULL;
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
 | 
			
		||||
@@ -1056,7 +1056,7 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        perror("unable to create backing store for hugepages");
 | 
			
		||||
        g_free(filename);
 | 
			
		||||
        return NULL;
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
    unlink(filename);
 | 
			
		||||
    g_free(filename);
 | 
			
		||||
@@ -1076,7 +1076,7 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
    if (area == MAP_FAILED) {
 | 
			
		||||
        perror("file_ram_alloc: can't mmap RAM pages");
 | 
			
		||||
        close(fd);
 | 
			
		||||
        return (NULL);
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mem_prealloc) {
 | 
			
		||||
@@ -1120,6 +1120,12 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
 | 
			
		||||
    block->fd = fd;
 | 
			
		||||
    return area;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
    if (mem_prealloc) {
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static void *file_ram_alloc(RAMBlock *block,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
ifeq ($(CONFIG_REALLY_VIRTFS),y)
 | 
			
		||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 | 
			
		||||
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 | 
			
		||||
# only pull in the actual virtio-9p device if we also enabled virtio.
 | 
			
		||||
common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
 | 
			
		||||
else
 | 
			
		||||
common-obj-y = qemu-fsdev-dummy.o
 | 
			
		||||
 
 | 
			
		||||
@@ -595,7 +595,7 @@ static int do_readlink(struct iovec *iovec, struct iovec *out_iovec)
 | 
			
		||||
    }
 | 
			
		||||
    buffer = g_malloc(size);
 | 
			
		||||
    v9fs_string_init(&target);
 | 
			
		||||
    retval = readlink(path.data, buffer, size);
 | 
			
		||||
    retval = readlink(path.data, buffer, size - 1);
 | 
			
		||||
    if (retval > 0) {
 | 
			
		||||
        buffer[retval] = '\0';
 | 
			
		||||
        v9fs_string_sprintf(&target, "%s", buffer);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,35 +17,55 @@
 | 
			
		||||
#include "block/coroutine.h"
 | 
			
		||||
#include "virtio-9p-coth.h"
 | 
			
		||||
 | 
			
		||||
static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
 | 
			
		||||
{
 | 
			
		||||
    ssize_t len, maxlen = PATH_MAX;
 | 
			
		||||
 | 
			
		||||
    buf->data = g_malloc(PATH_MAX);
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
 | 
			
		||||
        if (len < 0) {
 | 
			
		||||
            g_free(buf->data);
 | 
			
		||||
            buf->data = NULL;
 | 
			
		||||
            buf->size = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        } else if (len == maxlen) {
 | 
			
		||||
            /*
 | 
			
		||||
             * We dodn't have space to put the NULL or we have more
 | 
			
		||||
             * to read. Increase the size and try again
 | 
			
		||||
             */
 | 
			
		||||
            maxlen *= 2;
 | 
			
		||||
            g_free(buf->data);
 | 
			
		||||
            buf->data = g_malloc(maxlen);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        /*
 | 
			
		||||
         * Null terminate the readlink output
 | 
			
		||||
         */
 | 
			
		||||
        buf->data[len] = '\0';
 | 
			
		||||
        buf->size = len;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    ssize_t len;
 | 
			
		||||
    V9fsState *s = pdu->s;
 | 
			
		||||
 | 
			
		||||
    if (v9fs_request_cancelled(pdu)) {
 | 
			
		||||
        return -EINTR;
 | 
			
		||||
    }
 | 
			
		||||
    buf->data = g_malloc(PATH_MAX);
 | 
			
		||||
    v9fs_path_read_lock(s);
 | 
			
		||||
    v9fs_co_run_in_worker(
 | 
			
		||||
        {
 | 
			
		||||
            len = s->ops->readlink(&s->ctx, path,
 | 
			
		||||
                                   buf->data, PATH_MAX - 1);
 | 
			
		||||
            if (len > -1) {
 | 
			
		||||
                buf->size = len;
 | 
			
		||||
                buf->data[len] = 0;
 | 
			
		||||
                err = 0;
 | 
			
		||||
            } else {
 | 
			
		||||
            err = __readlink(s, path, buf);
 | 
			
		||||
            if (err < 0) {
 | 
			
		||||
                err = -errno;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    v9fs_path_unlock(s);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        g_free(buf->data);
 | 
			
		||||
        buf->data = NULL;
 | 
			
		||||
        buf->size = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -498,7 +498,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
 | 
			
		||||
static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
 | 
			
		||||
                              const char *name, V9fsPath *target)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    struct file_handle *fh;
 | 
			
		||||
    int dirfd, ret, mnt_id;
 | 
			
		||||
    struct handle_data *data = (struct handle_data *)ctx->private;
 | 
			
		||||
@@ -513,7 +513,9 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
 | 
			
		||||
        dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* relative to export root */
 | 
			
		||||
        dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
 | 
			
		||||
        buffer = rpath(ctx, ".");
 | 
			
		||||
        dirfd = open(buffer, O_DIRECTORY);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    }
 | 
			
		||||
    if (dirfd < 0) {
 | 
			
		||||
        return dirfd;
 | 
			
		||||
@@ -521,7 +523,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
 | 
			
		||||
    fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
 | 
			
		||||
    fh->handle_bytes = data->handle_bytes;
 | 
			
		||||
    /* add a "./" at the beginning of the path */
 | 
			
		||||
    snprintf(buffer, PATH_MAX, "./%s", name);
 | 
			
		||||
    buffer = g_strdup_printf("./%s", name);
 | 
			
		||||
    /* flag = 0 imply don't follow symlink */
 | 
			
		||||
    ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
 | 
			
		||||
    if (!ret) {
 | 
			
		||||
@@ -531,6 +533,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
 | 
			
		||||
        g_free(fh);
 | 
			
		||||
    }
 | 
			
		||||
    close(dirfd);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,18 +42,18 @@
 | 
			
		||||
 | 
			
		||||
#define VIRTFS_META_DIR ".virtfs_metadata"
 | 
			
		||||
 | 
			
		||||
static const char *local_mapped_attr_path(FsContext *ctx,
 | 
			
		||||
                                          const char *path, char *buffer)
 | 
			
		||||
static char *local_mapped_attr_path(FsContext *ctx, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    char *dir_name;
 | 
			
		||||
    char *tmp_path = g_strdup(path);
 | 
			
		||||
    char *base_name = basename(tmp_path);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    /* NULL terminate the directory */
 | 
			
		||||
    dir_name = tmp_path;
 | 
			
		||||
    *(base_name - 1) = '\0';
 | 
			
		||||
 | 
			
		||||
    snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
 | 
			
		||||
    buffer = g_strdup_printf("%s/%s/%s/%s",
 | 
			
		||||
             ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
 | 
			
		||||
    g_free(tmp_path);
 | 
			
		||||
    return buffer;
 | 
			
		||||
@@ -92,10 +92,11 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
 | 
			
		||||
{
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
    char buf[ATTR_MAX];
 | 
			
		||||
    char attr_path[PATH_MAX];
 | 
			
		||||
    char *attr_path;
 | 
			
		||||
 | 
			
		||||
    local_mapped_attr_path(ctx, path, attr_path);
 | 
			
		||||
    attr_path = local_mapped_attr_path(ctx, path);
 | 
			
		||||
    fp = local_fopen(attr_path, "r");
 | 
			
		||||
    g_free(attr_path);
 | 
			
		||||
    if (!fp) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -118,12 +119,13 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
 | 
			
		||||
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
 | 
			
		||||
    buffer = rpath(fs_ctx, path);
 | 
			
		||||
    err =  lstat(buffer, stbuf);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        return err;
 | 
			
		||||
        goto err_out;
 | 
			
		||||
    }
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        /* Actual credentials are part of extended attrs */
 | 
			
		||||
@@ -131,41 +133,42 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 | 
			
		||||
        gid_t tmp_gid;
 | 
			
		||||
        mode_t tmp_mode;
 | 
			
		||||
        dev_t tmp_dev;
 | 
			
		||||
        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
 | 
			
		||||
                    sizeof(uid_t)) > 0) {
 | 
			
		||||
        if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
 | 
			
		||||
            stbuf->st_uid = tmp_uid;
 | 
			
		||||
        }
 | 
			
		||||
        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
 | 
			
		||||
                    sizeof(gid_t)) > 0) {
 | 
			
		||||
        if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
 | 
			
		||||
            stbuf->st_gid = tmp_gid;
 | 
			
		||||
        }
 | 
			
		||||
        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
 | 
			
		||||
        if (getxattr(buffer, "user.virtfs.mode",
 | 
			
		||||
                    &tmp_mode, sizeof(mode_t)) > 0) {
 | 
			
		||||
            stbuf->st_mode = tmp_mode;
 | 
			
		||||
        }
 | 
			
		||||
        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
 | 
			
		||||
                        sizeof(dev_t)) > 0) {
 | 
			
		||||
        if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
 | 
			
		||||
                stbuf->st_rdev = tmp_dev;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        local_mapped_file_attr(fs_ctx, path, stbuf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
err_out:
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    char attr_dir[PATH_MAX];
 | 
			
		||||
    char *attr_dir;
 | 
			
		||||
    char *tmp_path = g_strdup(path);
 | 
			
		||||
 | 
			
		||||
    snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
 | 
			
		||||
    attr_dir = g_strdup_printf("%s/%s/%s",
 | 
			
		||||
             ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
 | 
			
		||||
 | 
			
		||||
    err = mkdir(attr_dir, 0700);
 | 
			
		||||
    if (err < 0 && errno == EEXIST) {
 | 
			
		||||
        err = 0;
 | 
			
		||||
    }
 | 
			
		||||
    g_free(attr_dir);
 | 
			
		||||
    g_free(tmp_path);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
@@ -176,10 +179,11 @@ static int local_set_mapped_file_attr(FsContext *ctx,
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    char buf[ATTR_MAX];
 | 
			
		||||
    char attr_path[PATH_MAX];
 | 
			
		||||
    char *attr_path;
 | 
			
		||||
    int uid = -1, gid = -1, mode = -1, rdev = -1;
 | 
			
		||||
 | 
			
		||||
    fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
 | 
			
		||||
    attr_path = local_mapped_attr_path(ctx, path);
 | 
			
		||||
    fp = local_fopen(attr_path, "r");
 | 
			
		||||
    if (!fp) {
 | 
			
		||||
        goto create_map_file;
 | 
			
		||||
    }
 | 
			
		||||
@@ -241,6 +245,7 @@ update_map_file:
 | 
			
		||||
    fclose(fp);
 | 
			
		||||
 | 
			
		||||
err_out:
 | 
			
		||||
    g_free(attr_path);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -282,36 +287,43 @@ static int local_set_xattr(const char *path, FsCred *credp)
 | 
			
		||||
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
 | 
			
		||||
                                         FsCred *credp)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
 | 
			
		||||
                credp->fc_gid) < 0) {
 | 
			
		||||
    buffer = rpath(fs_ctx, path);
 | 
			
		||||
    if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
 | 
			
		||||
        /*
 | 
			
		||||
         * If we fail to change ownership and if we are
 | 
			
		||||
         * using security model none. Ignore the error
 | 
			
		||||
         */
 | 
			
		||||
        if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
 | 
			
		||||
            return -1;
 | 
			
		||||
            goto err;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (chmod(buffer, credp->fc_mode & 07777) < 0) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return 0;
 | 
			
		||||
err:
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
 | 
			
		||||
                              char *buf, size_t bufsz)
 | 
			
		||||
{
 | 
			
		||||
    ssize_t tsize = -1;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
 | 
			
		||||
        (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
 | 
			
		||||
        int fd;
 | 
			
		||||
        fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        fd = open(buffer, O_RDONLY | O_NOFOLLOW);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
@@ -322,7 +334,9 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
 | 
			
		||||
        return tsize;
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        tsize = readlink(buffer, buf, bufsz);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    }
 | 
			
		||||
    return tsize;
 | 
			
		||||
}
 | 
			
		||||
@@ -340,20 +354,24 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
 | 
			
		||||
static int local_open(FsContext *ctx, V9fsPath *fs_path,
 | 
			
		||||
                      int flags, V9fsFidOpenState *fs)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    fs->fd = open(buffer, flags | O_NOFOLLOW);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return fs->fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_opendir(FsContext *ctx,
 | 
			
		||||
                         V9fsPath *fs_path, V9fsFidOpenState *fs)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    fs->dir = opendir(rpath(ctx, path, buffer));
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    fs->dir = opendir(buffer);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    if (!fs->dir) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
@@ -441,18 +459,23 @@ static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
 | 
			
		||||
 | 
			
		||||
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret = -1;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        ret = local_set_xattr(buffer, credp);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        return local_set_mapped_file_attr(fs_ctx, path, credp);
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        ret = chmod(buffer, credp->fc_mode);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
@@ -462,7 +485,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
    int err = -1;
 | 
			
		||||
    int serrno = 0;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
 | 
			
		||||
@@ -470,21 +493,23 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
 | 
			
		||||
    /* Determine the security model */
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        err = mknod(rpath(fs_ctx, path, buffer),
 | 
			
		||||
                SM_LOCAL_MODE_BITS|S_IFREG, 0);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
 | 
			
		||||
        err = local_set_xattr(buffer, credp);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            serrno = errno;
 | 
			
		||||
            goto err_end;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
 | 
			
		||||
        err = mknod(rpath(fs_ctx, path, buffer),
 | 
			
		||||
                    SM_LOCAL_MODE_BITS|S_IFREG, 0);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        err = local_set_mapped_file_attr(fs_ctx, path, credp);
 | 
			
		||||
@@ -494,9 +519,10 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
        }
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
 | 
			
		||||
                credp->fc_rdev);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        err = local_post_create_passthrough(fs_ctx, path, credp);
 | 
			
		||||
@@ -508,8 +534,9 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
err_end:
 | 
			
		||||
    remove(rpath(fs_ctx, path, buffer));
 | 
			
		||||
    remove(buffer);
 | 
			
		||||
    errno = serrno;
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
out:
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
@@ -522,7 +549,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
    int err = -1;
 | 
			
		||||
    int serrno = 0;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
 | 
			
		||||
@@ -530,19 +557,23 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
 | 
			
		||||
    /* Determine the security model */
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        credp->fc_mode = credp->fc_mode|S_IFDIR;
 | 
			
		||||
        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
 | 
			
		||||
        err = local_set_xattr(buffer, credp);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            serrno = errno;
 | 
			
		||||
            goto err_end;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        credp->fc_mode = credp->fc_mode|S_IFDIR;
 | 
			
		||||
@@ -553,8 +584,10 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
        }
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        err = mkdir(buffer, credp->fc_mode);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        err = local_post_create_passthrough(fs_ctx, path, credp);
 | 
			
		||||
@@ -566,8 +599,9 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
err_end:
 | 
			
		||||
    remove(rpath(fs_ctx, path, buffer));
 | 
			
		||||
    remove(buffer);
 | 
			
		||||
    errno = serrno;
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
out:
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
@@ -626,7 +660,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 | 
			
		||||
    int err = -1;
 | 
			
		||||
    int serrno = 0;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Mark all the open to not follow symlinks
 | 
			
		||||
@@ -639,21 +673,25 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 | 
			
		||||
 | 
			
		||||
    /* Determine the security model */
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            err = fd;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        credp->fc_mode = credp->fc_mode|S_IFREG;
 | 
			
		||||
        /* Set cleint credentials in xattr */
 | 
			
		||||
        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
 | 
			
		||||
        err = local_set_xattr(buffer, credp);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            serrno = errno;
 | 
			
		||||
            goto err_end;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            err = fd;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -666,8 +704,10 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 | 
			
		||||
        }
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        fd = open(buffer, flags, credp->fc_mode);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            err = fd;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -683,8 +723,9 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 | 
			
		||||
 | 
			
		||||
err_end:
 | 
			
		||||
    close(fd);
 | 
			
		||||
    remove(rpath(fs_ctx, path, buffer));
 | 
			
		||||
    remove(buffer);
 | 
			
		||||
    errno = serrno;
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
out:
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
@@ -698,7 +739,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
    int serrno = 0;
 | 
			
		||||
    char *newpath;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
    v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
 | 
			
		||||
@@ -708,10 +749,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        int fd;
 | 
			
		||||
        ssize_t oldpath_size, write_size;
 | 
			
		||||
        fd = open(rpath(fs_ctx, newpath, buffer),
 | 
			
		||||
                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
 | 
			
		||||
                  SM_LOCAL_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, newpath);
 | 
			
		||||
        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            err = fd;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -730,7 +771,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
        close(fd);
 | 
			
		||||
        /* Set cleint credentials in symlink's xattr */
 | 
			
		||||
        credp->fc_mode = credp->fc_mode|S_IFLNK;
 | 
			
		||||
        err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
 | 
			
		||||
        err = local_set_xattr(buffer, credp);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            serrno = errno;
 | 
			
		||||
            goto err_end;
 | 
			
		||||
@@ -738,10 +779,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        int fd;
 | 
			
		||||
        ssize_t oldpath_size, write_size;
 | 
			
		||||
        fd = open(rpath(fs_ctx, newpath, buffer),
 | 
			
		||||
                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
 | 
			
		||||
                  SM_LOCAL_MODE_BITS);
 | 
			
		||||
        buffer = rpath(fs_ctx, newpath);
 | 
			
		||||
        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
 | 
			
		||||
        if (fd == -1) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            err = fd;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -767,12 +808,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
        }
 | 
			
		||||
    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
               (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
 | 
			
		||||
        buffer = rpath(fs_ctx, newpath);
 | 
			
		||||
        err = symlink(oldpath, buffer);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
 | 
			
		||||
                     credp->fc_gid);
 | 
			
		||||
        err = lchown(buffer, credp->fc_uid, credp->fc_gid);
 | 
			
		||||
        if (err == -1) {
 | 
			
		||||
            /*
 | 
			
		||||
             * If we fail to change ownership and if we are
 | 
			
		||||
@@ -788,8 +830,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
err_end:
 | 
			
		||||
    remove(rpath(fs_ctx, newpath, buffer));
 | 
			
		||||
    remove(buffer);
 | 
			
		||||
    errno = serrno;
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
out:
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return err;
 | 
			
		||||
@@ -800,13 +843,16 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    V9fsString newpath;
 | 
			
		||||
    char buffer[PATH_MAX], buffer1[PATH_MAX];
 | 
			
		||||
    char *buffer, *buffer1;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&newpath);
 | 
			
		||||
    v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
 | 
			
		||||
 | 
			
		||||
    ret = link(rpath(ctx, oldpath->data, buffer),
 | 
			
		||||
               rpath(ctx, newpath.data, buffer1));
 | 
			
		||||
    buffer = rpath(ctx, oldpath->data);
 | 
			
		||||
    buffer1 = rpath(ctx, newpath.data);
 | 
			
		||||
    ret = link(buffer, buffer1);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    g_free(buffer1);
 | 
			
		||||
 | 
			
		||||
    /* now link the virtfs_metadata files */
 | 
			
		||||
    if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
 | 
			
		||||
@@ -815,8 +861,11 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            goto err_out;
 | 
			
		||||
        }
 | 
			
		||||
        ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
 | 
			
		||||
                   local_mapped_attr_path(ctx, newpath.data, buffer1));
 | 
			
		||||
        buffer = local_mapped_attr_path(ctx, oldpath->data);
 | 
			
		||||
        buffer1 = local_mapped_attr_path(ctx, newpath.data);
 | 
			
		||||
        ret = link(buffer, buffer1);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        g_free(buffer1);
 | 
			
		||||
        if (ret < 0 && errno != ENOENT) {
 | 
			
		||||
            goto err_out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -828,17 +877,21 @@ err_out:
 | 
			
		||||
 | 
			
		||||
static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    return truncate(rpath(ctx, path, buffer), size);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = truncate(buffer, size);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_rename(FsContext *ctx, const char *oldpath,
 | 
			
		||||
                        const char *newpath)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    char buffer[PATH_MAX], buffer1[PATH_MAX];
 | 
			
		||||
    char *buffer, *buffer1;
 | 
			
		||||
 | 
			
		||||
    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        err = local_create_mapped_attr_dir(ctx, newpath);
 | 
			
		||||
@@ -846,50 +899,69 @@ static int local_rename(FsContext *ctx, const char *oldpath,
 | 
			
		||||
            return err;
 | 
			
		||||
        }
 | 
			
		||||
        /* rename the .virtfs_metadata files */
 | 
			
		||||
        err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
 | 
			
		||||
                     local_mapped_attr_path(ctx, newpath, buffer1));
 | 
			
		||||
        buffer = local_mapped_attr_path(ctx, oldpath);
 | 
			
		||||
        buffer1 = local_mapped_attr_path(ctx, newpath);
 | 
			
		||||
        err = rename(buffer, buffer1);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        g_free(buffer1);
 | 
			
		||||
        if (err < 0 && errno != ENOENT) {
 | 
			
		||||
            return err;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, oldpath);
 | 
			
		||||
    buffer1 = rpath(ctx, newpath);
 | 
			
		||||
    err = rename(buffer, buffer1);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    g_free(buffer1);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret = -1;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
 | 
			
		||||
        (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
 | 
			
		||||
        (fs_ctx->export_flags & V9FS_SM_NONE)) {
 | 
			
		||||
        return lchown(rpath(fs_ctx, path, buffer),
 | 
			
		||||
                      credp->fc_uid, credp->fc_gid);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
 | 
			
		||||
        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
 | 
			
		||||
        buffer = rpath(fs_ctx, path);
 | 
			
		||||
        ret = local_set_xattr(buffer, credp);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        return local_set_mapped_file_attr(fs_ctx, path, credp);
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_utimensat(FsContext *s, V9fsPath *fs_path,
 | 
			
		||||
                           const struct timespec *buf)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    return qemu_utimens(rpath(s, path, buffer), buf);
 | 
			
		||||
    buffer = rpath(s, path);
 | 
			
		||||
    ret = qemu_utimens(buffer, buf);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_remove(FsContext *ctx, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int err;
 | 
			
		||||
    struct stat stbuf;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 | 
			
		||||
        err =  lstat(rpath(ctx, path, buffer), &stbuf);
 | 
			
		||||
        buffer = rpath(ctx, path);
 | 
			
		||||
        err =  lstat(buffer, &stbuf);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            goto err_out;
 | 
			
		||||
        }
 | 
			
		||||
@@ -898,8 +970,10 @@ static int local_remove(FsContext *ctx, const char *path)
 | 
			
		||||
         * directory
 | 
			
		||||
         */
 | 
			
		||||
        if (S_ISDIR(stbuf.st_mode)) {
 | 
			
		||||
            sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR);
 | 
			
		||||
            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
 | 
			
		||||
                                     path, VIRTFS_META_DIR);
 | 
			
		||||
            err = remove(buffer);
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            if (err < 0 && errno != ENOENT) {
 | 
			
		||||
                /*
 | 
			
		||||
                 * We didn't had the .virtfs_metadata file. May be file created
 | 
			
		||||
@@ -912,7 +986,9 @@ static int local_remove(FsContext *ctx, const char *path)
 | 
			
		||||
         * Now remove the name from parent directory
 | 
			
		||||
         * .virtfs_metadata directory
 | 
			
		||||
         */
 | 
			
		||||
        err = remove(local_mapped_attr_path(ctx, path, buffer));
 | 
			
		||||
        buffer = local_mapped_attr_path(ctx, path);
 | 
			
		||||
        err = remove(buffer);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        if (err < 0 && errno != ENOENT) {
 | 
			
		||||
            /*
 | 
			
		||||
             * We didn't had the .virtfs_metadata file. May be file created
 | 
			
		||||
@@ -921,7 +997,10 @@ static int local_remove(FsContext *ctx, const char *path)
 | 
			
		||||
            goto err_out;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return remove(rpath(ctx, path, buffer));
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    err = remove(buffer);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
err_out:
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
@@ -946,10 +1025,14 @@ static int local_fsync(FsContext *ctx, int fid_type,
 | 
			
		||||
 | 
			
		||||
static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
    char *path = fs_path->data;
 | 
			
		||||
 | 
			
		||||
    return statfs(rpath(s, path, buffer), stbuf);
 | 
			
		||||
    buffer = rpath(s, path);
 | 
			
		||||
    ret = statfs(buffer, stbuf);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
 | 
			
		||||
@@ -1022,7 +1105,7 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    V9fsString fullname;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    v9fs_string_init(&fullname);
 | 
			
		||||
 | 
			
		||||
@@ -1033,9 +1116,10 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
 | 
			
		||||
             * If directory remove .virtfs_metadata contained in the
 | 
			
		||||
             * directory
 | 
			
		||||
             */
 | 
			
		||||
            sprintf(buffer, "%s/%s/%s", ctx->fs_root,
 | 
			
		||||
            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
 | 
			
		||||
                                     fullname.data, VIRTFS_META_DIR);
 | 
			
		||||
            ret = remove(buffer);
 | 
			
		||||
            g_free(buffer);
 | 
			
		||||
            if (ret < 0 && errno != ENOENT) {
 | 
			
		||||
                /*
 | 
			
		||||
                 * We didn't had the .virtfs_metadata file. May be file created
 | 
			
		||||
@@ -1048,7 +1132,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
 | 
			
		||||
         * Now remove the name from parent directory
 | 
			
		||||
         * .virtfs_metadata directory.
 | 
			
		||||
         */
 | 
			
		||||
        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
 | 
			
		||||
        buffer = local_mapped_attr_path(ctx, fullname.data);
 | 
			
		||||
        ret = remove(buffer);
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        if (ret < 0 && errno != ENOENT) {
 | 
			
		||||
            /*
 | 
			
		||||
             * We didn't had the .virtfs_metadata file. May be file created
 | 
			
		||||
@@ -1058,10 +1144,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* Remove the name finally */
 | 
			
		||||
    ret = remove(rpath(ctx, fullname.data, buffer));
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    buffer = rpath(ctx, fullname.data);
 | 
			
		||||
    ret = remove(buffer);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
 | 
			
		||||
err_out:
 | 
			
		||||
    v9fs_string_free(&fullname);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,13 @@
 | 
			
		||||
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
                                const char *name, void *value, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    ssize_t ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
@@ -52,17 +57,23 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
 | 
			
		||||
                            void *value, size_t size, int flags)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
 | 
			
		||||
            size, flags);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mp_pacl_removexattr(FsContext *ctx,
 | 
			
		||||
                               const char *path, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret  = lremovexattr(buffer, MAP_ACL_ACCESS);
 | 
			
		||||
    if (ret == -1 && errno == ENODATA) {
 | 
			
		||||
        /*
 | 
			
		||||
         * We don't get ENODATA error when trying to remove a
 | 
			
		||||
@@ -72,14 +83,20 @@ static int mp_pacl_removexattr(FsContext *ctx,
 | 
			
		||||
        errno = 0;
 | 
			
		||||
        ret = 0;
 | 
			
		||||
    }
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
                                const char *name, void *value, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    ssize_t ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
@@ -104,17 +121,23 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
 | 
			
		||||
                            void *value, size_t size, int flags)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
 | 
			
		||||
            size, flags);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mp_dacl_removexattr(FsContext *ctx,
 | 
			
		||||
                               const char *path, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret  = lremovexattr(buffer, MAP_ACL_DEFAULT);
 | 
			
		||||
    if (ret == -1 && errno == ENODATA) {
 | 
			
		||||
        /*
 | 
			
		||||
         * We don't get ENODATA error when trying to remove a
 | 
			
		||||
@@ -124,6 +147,7 @@ static int mp_dacl_removexattr(FsContext *ctx,
 | 
			
		||||
        errno = 0;
 | 
			
		||||
        ret = 0;
 | 
			
		||||
    }
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,9 @@
 | 
			
		||||
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
                                const char *name, void *value, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    ssize_t ret;
 | 
			
		||||
 | 
			
		||||
    if (strncmp(name, "user.virtfs.", 12) == 0) {
 | 
			
		||||
        /*
 | 
			
		||||
         * Don't allow fetch of user.virtfs namesapce
 | 
			
		||||
@@ -30,7 +32,10 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
        errno = ENOATTR;
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lgetxattr(buffer, name, value, size);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
@@ -69,7 +74,9 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
 | 
			
		||||
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
 | 
			
		||||
                            void *value, size_t size, int flags)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (strncmp(name, "user.virtfs.", 12) == 0) {
 | 
			
		||||
        /*
 | 
			
		||||
         * Don't allow fetch of user.virtfs namesapce
 | 
			
		||||
@@ -78,13 +85,18 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
 | 
			
		||||
        errno = EACCES;
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lsetxattr(buffer, name, value, size, flags);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mp_user_removexattr(FsContext *ctx,
 | 
			
		||||
                               const char *path, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (strncmp(name, "user.virtfs.", 12) == 0) {
 | 
			
		||||
        /*
 | 
			
		||||
         * Don't allow fetch of user.virtfs namesapce
 | 
			
		||||
@@ -93,7 +105,10 @@ static int mp_user_removexattr(FsContext *ctx,
 | 
			
		||||
        errno = EACCES;
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return lremovexattr(rpath(ctx, path, buffer), name);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lremovexattr(buffer, name);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
XattrOperations mapped_user_xattr = {
 | 
			
		||||
 
 | 
			
		||||
@@ -67,21 +67,24 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
 | 
			
		||||
                        void *value, size_t vsize)
 | 
			
		||||
{
 | 
			
		||||
    ssize_t size = 0;
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    void *ovalue = value;
 | 
			
		||||
    XattrOperations *xops;
 | 
			
		||||
    char *orig_value, *orig_value_start;
 | 
			
		||||
    ssize_t xattr_len, parsed_len = 0, attr_len;
 | 
			
		||||
 | 
			
		||||
    /* Get the actual len */
 | 
			
		||||
    xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    xattr_len = llistxattr(buffer, value, 0);
 | 
			
		||||
    if (xattr_len <= 0) {
 | 
			
		||||
        g_free(buffer);
 | 
			
		||||
        return xattr_len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Now fetch the xattr and find the actual size */
 | 
			
		||||
    orig_value = g_malloc(xattr_len);
 | 
			
		||||
    xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
 | 
			
		||||
    xattr_len = llistxattr(buffer, orig_value, xattr_len);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
 | 
			
		||||
    /* store the orig pointer */
 | 
			
		||||
    orig_value_start = orig_value;
 | 
			
		||||
 
 | 
			
		||||
@@ -54,23 +54,38 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
 | 
			
		||||
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
                                  const char *name, void *value, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    ssize_t ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lgetxattr(buffer, name, value, size);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int pt_setxattr(FsContext *ctx, const char *path,
 | 
			
		||||
                              const char *name, void *value,
 | 
			
		||||
                              size_t size, int flags)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lsetxattr(buffer, name, value, size, flags);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int pt_removexattr(FsContext *ctx,
 | 
			
		||||
                                 const char *path, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[PATH_MAX];
 | 
			
		||||
    return lremovexattr(rpath(ctx, path, buffer), name);
 | 
			
		||||
    char *buffer;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    buffer = rpath(ctx, path);
 | 
			
		||||
    ret = lremovexattr(path, name);
 | 
			
		||||
    g_free(buffer);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <utime.h>
 | 
			
		||||
#include <sys/resource.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include "hw/virtio/virtio.h"
 | 
			
		||||
#include "fsdev/file-op-9p.h"
 | 
			
		||||
#include "fsdev/virtio-9p-marshal.h"
 | 
			
		||||
@@ -112,10 +113,9 @@ enum p9_proto_version {
 | 
			
		||||
 | 
			
		||||
#define FID_REFERENCED          0x1
 | 
			
		||||
#define FID_NON_RECLAIMABLE     0x2
 | 
			
		||||
static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
 | 
			
		||||
static inline char *rpath(FsContext *ctx, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
 | 
			
		||||
    return buffer;
 | 
			
		||||
    return g_strdup_printf("%s/%s", ctx->fs_root, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
devices-dirs-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 | 
			
		||||
devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
 | 
			
		||||
devices-dirs-$(CONFIG_ACPI) += acpi/
 | 
			
		||||
devices-dirs-$(CONFIG_SOFTMMU) += audio/
 | 
			
		||||
devices-dirs-$(CONFIG_SOFTMMU) += block/
 | 
			
		||||
 
 | 
			
		||||
@@ -110,10 +110,10 @@
 | 
			
		||||
#define MP_PHY_88E3015          0x01410E20
 | 
			
		||||
 | 
			
		||||
/* TX descriptor status */
 | 
			
		||||
#define MP_ETH_TX_OWN           (1 << 31)
 | 
			
		||||
#define MP_ETH_TX_OWN           (1U << 31)
 | 
			
		||||
 | 
			
		||||
/* RX descriptor status */
 | 
			
		||||
#define MP_ETH_RX_OWN           (1 << 31)
 | 
			
		||||
#define MP_ETH_RX_OWN           (1U << 31)
 | 
			
		||||
 | 
			
		||||
/* Interrupt cause/mask bits */
 | 
			
		||||
#define MP_ETH_IRQ_RX_BIT       0
 | 
			
		||||
 
 | 
			
		||||
@@ -809,22 +809,26 @@ static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
 | 
			
		||||
                uint32_t diff, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
    if (s->compat1509) {
 | 
			
		||||
        if (diff & (1 << 31))			/* MCBSP3_CLK_HIZ_DI */
 | 
			
		||||
            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
 | 
			
		||||
                            (value >> 31) & 1);
 | 
			
		||||
        if (diff & (1 << 1))			/* CLK32K */
 | 
			
		||||
            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
 | 
			
		||||
                            (~value >> 1) & 1);
 | 
			
		||||
        if (diff & (1U << 31)) {
 | 
			
		||||
            /* MCBSP3_CLK_HIZ_DI */
 | 
			
		||||
            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"), (value >> 31) & 1);
 | 
			
		||||
        }
 | 
			
		||||
        if (diff & (1 << 1)) {
 | 
			
		||||
            /* CLK32K */
 | 
			
		||||
            omap_clk_onoff(omap_findclk(s, "clk32k_out"), (~value >> 1) & 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
 | 
			
		||||
                uint32_t diff, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
    if (diff & (1 << 31))			/* CONF_MOD_UART3_CLK_MODE_R */
 | 
			
		||||
    if (diff & (1U << 31)) {
 | 
			
		||||
        /* CONF_MOD_UART3_CLK_MODE_R */
 | 
			
		||||
        omap_clk_reparent(omap_findclk(s, "uart3_ck"),
 | 
			
		||||
                          omap_findclk(s, ((value >> 31) & 1) ?
 | 
			
		||||
                                       "ck_48m" : "armper_ck"));
 | 
			
		||||
    }
 | 
			
		||||
    if (diff & (1 << 30))			/* CONF_MOD_UART2_CLK_MODE_R */
 | 
			
		||||
         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
 | 
			
		||||
                         omap_findclk(s, ((value >> 30) & 1) ?
 | 
			
		||||
 
 | 
			
		||||
@@ -259,7 +259,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
        /* Idle */
 | 
			
		||||
        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
 | 
			
		||||
        if (!(s->cm_regs[CCCR >> 2] & (1U << 31))) { /* CPDIS */
 | 
			
		||||
            cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -496,7 +496,7 @@ typedef struct {
 | 
			
		||||
#define SSCR0_SSE	(1 << 7)
 | 
			
		||||
#define SSCR0_RIM	(1 << 22)
 | 
			
		||||
#define SSCR0_TIM	(1 << 23)
 | 
			
		||||
#define SSCR0_MOD	(1 << 31)
 | 
			
		||||
#define SSCR0_MOD       (1U << 31)
 | 
			
		||||
#define SSCR0_DSS(x)	(((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
 | 
			
		||||
#define SSCR1_RIE	(1 << 0)
 | 
			
		||||
#define SSCR1_TIE	(1 << 1)
 | 
			
		||||
@@ -1006,7 +1006,7 @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
    case RTTR:
 | 
			
		||||
        if (!(s->rttr & (1 << 31))) {
 | 
			
		||||
        if (!(s->rttr & (1U << 31))) {
 | 
			
		||||
            pxa2xx_rtc_hzupdate(s);
 | 
			
		||||
            s->rttr = value;
 | 
			
		||||
            pxa2xx_rtc_alarm_update(s, s->rtsr);
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bank = line >> 5;
 | 
			
		||||
    mask = 1 << (line & 31);
 | 
			
		||||
    mask = 1U << (line & 31);
 | 
			
		||||
 | 
			
		||||
    if (level) {
 | 
			
		||||
        s->status[bank] |= s->rising[bank] & mask &
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
 | 
			
		||||
 | 
			
		||||
    for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
 | 
			
		||||
        irq = s->priority[i] & 0x3f;
 | 
			
		||||
        if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
 | 
			
		||||
        if ((s->priority[i] & (1U << 31)) && irq < PXA2XX_PIC_SRCS) {
 | 
			
		||||
            /* Source peripheral ID is valid.  */
 | 
			
		||||
            bit = 1 << (irq & 31);
 | 
			
		||||
            int_set = (irq >= 32);
 | 
			
		||||
@@ -119,7 +119,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
 | 
			
		||||
            if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
 | 
			
		||||
                /* IRQ asserted */
 | 
			
		||||
                ichp &= 0x0000ffff;
 | 
			
		||||
                ichp |= (1 << 31) | (irq << 16);
 | 
			
		||||
                ichp |= (1U << 31) | (irq << 16);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -358,7 +358,7 @@ static void start_data_plane_bh(void *opaque)
 | 
			
		||||
 | 
			
		||||
    qemu_bh_delete(s->start_bh);
 | 
			
		||||
    s->start_bh = NULL;
 | 
			
		||||
    qemu_thread_create(&s->thread, data_plane_thread,
 | 
			
		||||
    qemu_thread_create(&s->thread, "data_plane", data_plane_thread,
 | 
			
		||||
                       s, QEMU_THREAD_JOINABLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,8 @@
 | 
			
		||||
 | 
			
		||||
#include <zlib.h>
 | 
			
		||||
 | 
			
		||||
bool rom_file_in_ram = true;
 | 
			
		||||
bool option_rom_has_mr = false;
 | 
			
		||||
bool rom_file_has_mr = true;
 | 
			
		||||
 | 
			
		||||
static int roms_loaded;
 | 
			
		||||
 | 
			
		||||
@@ -284,12 +285,30 @@ static void *load_at(int fd, int offset, int size)
 | 
			
		||||
#define SZ		64
 | 
			
		||||
#include "hw/elf_ops.h"
 | 
			
		||||
 | 
			
		||||
const char *load_elf_strerror(int error)
 | 
			
		||||
{
 | 
			
		||||
    switch (error) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        return "No error";
 | 
			
		||||
    case ELF_LOAD_FAILED:
 | 
			
		||||
        return "Failed to load ELF";
 | 
			
		||||
    case ELF_LOAD_NOT_ELF:
 | 
			
		||||
        return "The image is not ELF";
 | 
			
		||||
    case ELF_LOAD_WRONG_ARCH:
 | 
			
		||||
        return "The image is from incompatible architecture";
 | 
			
		||||
    case ELF_LOAD_WRONG_ENDIAN:
 | 
			
		||||
        return "The image has incorrect endianness";
 | 
			
		||||
    default:
 | 
			
		||||
        return "Unknown error";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return < 0 if error, otherwise the number of bytes loaded in memory */
 | 
			
		||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
             uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
 | 
			
		||||
{
 | 
			
		||||
    int fd, data_order, target_data_order, must_swab, ret;
 | 
			
		||||
    int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
 | 
			
		||||
    uint8_t e_ident[EI_NIDENT];
 | 
			
		||||
 | 
			
		||||
    fd = open(filename, O_RDONLY | O_BINARY);
 | 
			
		||||
@@ -302,8 +321,10 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
    if (e_ident[0] != ELFMAG0 ||
 | 
			
		||||
        e_ident[1] != ELFMAG1 ||
 | 
			
		||||
        e_ident[2] != ELFMAG2 ||
 | 
			
		||||
        e_ident[3] != ELFMAG3)
 | 
			
		||||
        e_ident[3] != ELFMAG3) {
 | 
			
		||||
        ret = ELF_LOAD_NOT_ELF;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef HOST_WORDS_BIGENDIAN
 | 
			
		||||
    data_order = ELFDATA2MSB;
 | 
			
		||||
#else
 | 
			
		||||
@@ -317,6 +338,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (target_data_order != e_ident[EI_DATA]) {
 | 
			
		||||
        ret = ELF_LOAD_WRONG_ENDIAN;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -329,12 +351,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(fd);
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
    close(fd);
 | 
			
		||||
    return -1;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bswap_uboot_header(uboot_image_header_t *hdr)
 | 
			
		||||
@@ -624,7 +643,8 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
			
		||||
                 hwaddr addr, int32_t bootindex)
 | 
			
		||||
                 hwaddr addr, int32_t bootindex,
 | 
			
		||||
                 bool option_rom)
 | 
			
		||||
{
 | 
			
		||||
    Rom *rom;
 | 
			
		||||
    int rc, fd = -1;
 | 
			
		||||
@@ -676,7 +696,7 @@ int rom_add_file(const char *file, const char *fw_dir,
 | 
			
		||||
                 basename);
 | 
			
		||||
        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
 | 
			
		||||
 | 
			
		||||
        if (rom_file_in_ram) {
 | 
			
		||||
        if ((!option_rom || option_rom_has_mr) && rom_file_has_mr) {
 | 
			
		||||
            data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
 | 
			
		||||
        } else {
 | 
			
		||||
            data = rom->data;
 | 
			
		||||
@@ -720,7 +740,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
			
		||||
 | 
			
		||||
        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
 | 
			
		||||
 | 
			
		||||
        if (rom_file_in_ram) {
 | 
			
		||||
        if (rom_file_has_mr) {
 | 
			
		||||
            data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
 | 
			
		||||
        } else {
 | 
			
		||||
            data = rom->data;
 | 
			
		||||
@@ -755,12 +775,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
 | 
			
		||||
 | 
			
		||||
int rom_add_vga(const char *file)
 | 
			
		||||
{
 | 
			
		||||
    return rom_add_file(file, "vgaroms", 0, -1);
 | 
			
		||||
    return rom_add_file(file, "vgaroms", 0, -1, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rom_add_option(const char *file, int32_t bootindex)
 | 
			
		||||
{
 | 
			
		||||
    return rom_add_file(file, "genroms", 0, bootindex);
 | 
			
		||||
    return rom_add_file(file, "genroms", 0, bootindex, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rom_reset(void *unused)
 | 
			
		||||
 
 | 
			
		||||
@@ -440,27 +440,33 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 | 
			
		||||
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    const char *typename = object_get_typename(OBJECT(bus));
 | 
			
		||||
    BusClass *bc;
 | 
			
		||||
    char *buf;
 | 
			
		||||
    int i,len;
 | 
			
		||||
    int i, len, bus_id;
 | 
			
		||||
 | 
			
		||||
    bus->parent = parent;
 | 
			
		||||
 | 
			
		||||
    if (name) {
 | 
			
		||||
        bus->name = g_strdup(name);
 | 
			
		||||
    } else if (bus->parent && bus->parent->id) {
 | 
			
		||||
        /* parent device has id -> use it for bus name */
 | 
			
		||||
        /* parent device has id -> use it plus parent-bus-id for bus name */
 | 
			
		||||
        bus_id = bus->parent->num_child_bus;
 | 
			
		||||
 | 
			
		||||
        len = strlen(bus->parent->id) + 16;
 | 
			
		||||
        buf = g_malloc(len);
 | 
			
		||||
        snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
 | 
			
		||||
        snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
 | 
			
		||||
        bus->name = buf;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* no id -> use lowercase bus type for bus name */
 | 
			
		||||
        /* no id -> use lowercase bus type plus global bus-id for bus name */
 | 
			
		||||
        bc = BUS_GET_CLASS(bus);
 | 
			
		||||
        bus_id = bc->automatic_ids++;
 | 
			
		||||
 | 
			
		||||
        len = strlen(typename) + 16;
 | 
			
		||||
        buf = g_malloc(len);
 | 
			
		||||
        len = snprintf(buf, len, "%s.%d", typename,
 | 
			
		||||
                       bus->parent ? bus->parent->num_child_bus : 0);
 | 
			
		||||
        for (i = 0; i < len; i++)
 | 
			
		||||
        len = snprintf(buf, len, "%s.%d", typename, bus_id);
 | 
			
		||||
        for (i = 0; i < len; i++) {
 | 
			
		||||
            buf[i] = qemu_tolower(buf[i]);
 | 
			
		||||
        }
 | 
			
		||||
        bus->name = buf;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -992,7 +992,7 @@ wait_more:
 | 
			
		||||
 | 
			
		||||
    /* vfb */
 | 
			
		||||
    fb = container_of(xfb, struct XenFB, c.xendev);
 | 
			
		||||
    fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb);
 | 
			
		||||
    fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb);
 | 
			
		||||
    fb->have_console = 1;
 | 
			
		||||
 | 
			
		||||
    /* vkbd */
 | 
			
		||||
 
 | 
			
		||||
@@ -466,9 +466,15 @@ static void acpi_align_size(GArray *blob, unsigned align)
 | 
			
		||||
    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get pointer within table in a safe manner */
 | 
			
		||||
#define ACPI_BUILD_PTR(table, size, off, type) \
 | 
			
		||||
    ((type *)(acpi_data_get_ptr(table, size, off, sizeof(type))))
 | 
			
		||||
/* Set a value within table in a safe manner */
 | 
			
		||||
#define ACPI_BUILD_SET_LE(table, size, off, bits, val) \
 | 
			
		||||
    do { \
 | 
			
		||||
        uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \
 | 
			
		||||
        memcpy(acpi_data_get_ptr(table, size, off, \
 | 
			
		||||
                                 (bits) / BITS_PER_BYTE), \
 | 
			
		||||
               &ACPI_BUILD_SET_LE_val, \
 | 
			
		||||
               (bits) / BITS_PER_BYTE); \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
 | 
			
		||||
                                      unsigned off, unsigned size)
 | 
			
		||||
@@ -643,6 +649,21 @@ static inline char acpi_get_hex(uint32_t val)
 | 
			
		||||
#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
 | 
			
		||||
#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
 | 
			
		||||
 | 
			
		||||
#define ACPI_PCINOHP_OFFSET_HEX (*ssdt_pcinohp_name - *ssdt_pcinohp_start + 1)
 | 
			
		||||
#define ACPI_PCINOHP_OFFSET_ADR (*ssdt_pcinohp_adr - *ssdt_pcinohp_start)
 | 
			
		||||
#define ACPI_PCINOHP_SIZEOF (*ssdt_pcinohp_end - *ssdt_pcinohp_start)
 | 
			
		||||
#define ACPI_PCINOHP_AML (ssdp_pcihp_aml + *ssdt_pcinohp_start)
 | 
			
		||||
 | 
			
		||||
#define ACPI_PCIVGA_OFFSET_HEX (*ssdt_pcivga_name - *ssdt_pcivga_start + 1)
 | 
			
		||||
#define ACPI_PCIVGA_OFFSET_ADR (*ssdt_pcivga_adr - *ssdt_pcivga_start)
 | 
			
		||||
#define ACPI_PCIVGA_SIZEOF (*ssdt_pcivga_end - *ssdt_pcivga_start)
 | 
			
		||||
#define ACPI_PCIVGA_AML (ssdp_pcihp_aml + *ssdt_pcivga_start)
 | 
			
		||||
 | 
			
		||||
#define ACPI_PCIQXL_OFFSET_HEX (*ssdt_pciqxl_name - *ssdt_pciqxl_start + 1)
 | 
			
		||||
#define ACPI_PCIQXL_OFFSET_ADR (*ssdt_pciqxl_adr - *ssdt_pciqxl_start)
 | 
			
		||||
#define ACPI_PCIQXL_SIZEOF (*ssdt_pciqxl_end - *ssdt_pciqxl_start)
 | 
			
		||||
#define ACPI_PCIQXL_AML (ssdp_pcihp_aml + *ssdt_pciqxl_start)
 | 
			
		||||
 | 
			
		||||
#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
 | 
			
		||||
#define ACPI_SSDT_HEADER_LENGTH 36
 | 
			
		||||
 | 
			
		||||
@@ -677,6 +698,33 @@ static void patch_pcihp(int slot, uint8_t *ssdt_ptr)
 | 
			
		||||
    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_pcinohp(int slot, uint8_t *ssdt_ptr)
 | 
			
		||||
{
 | 
			
		||||
    unsigned devfn = PCI_DEVFN(slot, 0);
 | 
			
		||||
 | 
			
		||||
    ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
 | 
			
		||||
    ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
 | 
			
		||||
    ssdt_ptr[ACPI_PCINOHP_OFFSET_ADR + 2] = slot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_pcivga(int slot, uint8_t *ssdt_ptr)
 | 
			
		||||
{
 | 
			
		||||
    unsigned devfn = PCI_DEVFN(slot, 0);
 | 
			
		||||
 | 
			
		||||
    ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
 | 
			
		||||
    ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX + 1] = acpi_get_hex(devfn);
 | 
			
		||||
    ssdt_ptr[ACPI_PCIVGA_OFFSET_ADR + 2] = slot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_pciqxl(int slot, uint8_t *ssdt_ptr)
 | 
			
		||||
{
 | 
			
		||||
    unsigned devfn = PCI_DEVFN(slot, 0);
 | 
			
		||||
 | 
			
		||||
    ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
 | 
			
		||||
    ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX + 1] = acpi_get_hex(devfn);
 | 
			
		||||
    ssdt_ptr[ACPI_PCIQXL_OFFSET_ADR + 2] = slot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Assign BSEL property to all buses.  In the future, this can be changed
 | 
			
		||||
 * to only assign to buses that support hotplug.
 | 
			
		||||
 */
 | 
			
		||||
@@ -737,6 +785,10 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
 | 
			
		||||
    AcpiBuildPciBusHotplugState *parent = child->parent;
 | 
			
		||||
    GArray *bus_table = build_alloc_array();
 | 
			
		||||
    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
 | 
			
		||||
    DECLARE_BITMAP(slot_device_present, PCI_SLOT_MAX);
 | 
			
		||||
    DECLARE_BITMAP(slot_device_system, PCI_SLOT_MAX);
 | 
			
		||||
    DECLARE_BITMAP(slot_device_vga, PCI_SLOT_MAX);
 | 
			
		||||
    DECLARE_BITMAP(slot_device_qxl, PCI_SLOT_MAX);
 | 
			
		||||
    uint8_t op;
 | 
			
		||||
    int i;
 | 
			
		||||
    QObject *bsel;
 | 
			
		||||
@@ -764,40 +816,82 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
 | 
			
		||||
        build_append_byte(bus_table, 0x08); /* NameOp */
 | 
			
		||||
        build_append_nameseg(bus_table, "BSEL");
 | 
			
		||||
        build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
 | 
			
		||||
 | 
			
		||||
        memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* No bsel - no slots are hot-pluggable */
 | 
			
		||||
        memset(slot_hotplug_enable, 0x00, sizeof slot_hotplug_enable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
 | 
			
		||||
    memset(slot_device_present, 0x00, sizeof slot_device_present);
 | 
			
		||||
    memset(slot_device_system, 0x00, sizeof slot_device_present);
 | 
			
		||||
    memset(slot_device_vga, 0x00, sizeof slot_device_vga);
 | 
			
		||||
    memset(slot_device_qxl, 0x00, sizeof slot_device_qxl);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
 | 
			
		||||
        DeviceClass *dc;
 | 
			
		||||
        PCIDeviceClass *pc;
 | 
			
		||||
        PCIDevice *pdev = bus->devices[i];
 | 
			
		||||
        int slot = PCI_SLOT(i);
 | 
			
		||||
 | 
			
		||||
        if (!pdev) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set_bit(slot, slot_device_present);
 | 
			
		||||
        pc = PCI_DEVICE_GET_CLASS(pdev);
 | 
			
		||||
        dc = DEVICE_GET_CLASS(pdev);
 | 
			
		||||
 | 
			
		||||
            if (!dc->hotpluggable || pc->is_bridge) {
 | 
			
		||||
                int slot = PCI_SLOT(i);
 | 
			
		||||
        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
 | 
			
		||||
            set_bit(slot, slot_device_system);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
 | 
			
		||||
            set_bit(slot, slot_device_vga);
 | 
			
		||||
 | 
			
		||||
            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
 | 
			
		||||
                set_bit(slot, slot_device_qxl);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!dc->hotpluggable || pc->is_bridge) {
 | 
			
		||||
            clear_bit(slot, slot_hotplug_enable);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        /* Append Device object for each slot which supports eject */
 | 
			
		||||
    /* Append Device object for each slot */
 | 
			
		||||
    for (i = 0; i < PCI_SLOT_MAX; i++) {
 | 
			
		||||
        bool can_eject = test_bit(i, slot_hotplug_enable);
 | 
			
		||||
        bool present = test_bit(i, slot_device_present);
 | 
			
		||||
        bool vga = test_bit(i, slot_device_vga);
 | 
			
		||||
        bool qxl = test_bit(i, slot_device_qxl);
 | 
			
		||||
        bool system = test_bit(i, slot_device_system);
 | 
			
		||||
        if (can_eject) {
 | 
			
		||||
            void *pcihp = acpi_data_push(bus_table,
 | 
			
		||||
                                         ACPI_PCIHP_SIZEOF);
 | 
			
		||||
            memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
 | 
			
		||||
            patch_pcihp(i, pcihp);
 | 
			
		||||
            bus_hotplug_support = true;
 | 
			
		||||
        } else if (qxl) {
 | 
			
		||||
            void *pcihp = acpi_data_push(bus_table,
 | 
			
		||||
                                         ACPI_PCIQXL_SIZEOF);
 | 
			
		||||
            memcpy(pcihp, ACPI_PCIQXL_AML, ACPI_PCIQXL_SIZEOF);
 | 
			
		||||
            patch_pciqxl(i, pcihp);
 | 
			
		||||
        } else if (vga) {
 | 
			
		||||
            void *pcihp = acpi_data_push(bus_table,
 | 
			
		||||
                                         ACPI_PCIVGA_SIZEOF);
 | 
			
		||||
            memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);
 | 
			
		||||
            patch_pcivga(i, pcihp);
 | 
			
		||||
        } else if (system) {
 | 
			
		||||
            /* Nothing to do: system devices are in DSDT. */
 | 
			
		||||
        } else if (present) {
 | 
			
		||||
            void *pcihp = acpi_data_push(bus_table,
 | 
			
		||||
                                         ACPI_PCINOHP_SIZEOF);
 | 
			
		||||
            memcpy(pcihp, ACPI_PCINOHP_AML, ACPI_PCINOHP_SIZEOF);
 | 
			
		||||
            patch_pcinohp(i, pcihp);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bsel) {
 | 
			
		||||
        method = build_alloc_method("DVNT", 2);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < PCI_SLOT_MAX; i++) {
 | 
			
		||||
@@ -886,22 +980,17 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
 | 
			
		||||
 | 
			
		||||
static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    *ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) =
 | 
			
		||||
        cpu_to_le32(pci->w32.begin);
 | 
			
		||||
    ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin);
 | 
			
		||||
 | 
			
		||||
    *ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) =
 | 
			
		||||
        cpu_to_le32(pci->w32.end - 1);
 | 
			
		||||
    ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1);
 | 
			
		||||
 | 
			
		||||
    if (pci->w64.end || pci->w64.begin) {
 | 
			
		||||
        *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1;
 | 
			
		||||
        *ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) =
 | 
			
		||||
            cpu_to_le64(pci->w64.begin);
 | 
			
		||||
        *ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) =
 | 
			
		||||
            cpu_to_le64(pci->w64.end - 1);
 | 
			
		||||
        *ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) =
 | 
			
		||||
            cpu_to_le64(pci->w64.end - pci->w64.begin);
 | 
			
		||||
        ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1);
 | 
			
		||||
        ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin);
 | 
			
		||||
        ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1);
 | 
			
		||||
        ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin);
 | 
			
		||||
    } else {
 | 
			
		||||
        *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0;
 | 
			
		||||
        ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -976,7 +1065,14 @@ build_ssdt(GArray *table_data, GArray *linker,
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            AcpiBuildPciBusHotplugState hotplug_state;
 | 
			
		||||
            PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
 | 
			
		||||
            Object *pci_host;
 | 
			
		||||
            PCIBus *bus = NULL;
 | 
			
		||||
            bool ambiguous;
 | 
			
		||||
 | 
			
		||||
            pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
 | 
			
		||||
            if (!ambiguous && pci_host) {
 | 
			
		||||
                bus = PCI_HOST_BRIDGE(pci_host)->bus;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            build_pci_bus_state_init(&hotplug_state, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,8 @@ DefinitionBlock (
 | 
			
		||||
            Name(_HID, EisaId("PNP0A03"))
 | 
			
		||||
            Name(_ADR, 0x00)
 | 
			
		||||
            Name(_UID, 1)
 | 
			
		||||
//#define PX13 S0B_
 | 
			
		||||
//            External(PX13, DeviceObj)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -87,34 +89,6 @@ DefinitionBlock (
 | 
			
		||||
#include "acpi-dsdt-hpet.dsl"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/****************************************************************
 | 
			
		||||
 * VGA
 | 
			
		||||
 ****************************************************************/
 | 
			
		||||
 | 
			
		||||
    Scope(\_SB.PCI0) {
 | 
			
		||||
        Device(VGA) {
 | 
			
		||||
            Name(_ADR, 0x00020000)
 | 
			
		||||
            OperationRegion(PCIC, PCI_Config, Zero, 0x4)
 | 
			
		||||
            Field(PCIC, DWordAcc, NoLock, Preserve) {
 | 
			
		||||
                VEND, 32
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S1D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S2D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S3D, 0, NotSerialized) {
 | 
			
		||||
                If (LEqual(VEND, 0x1001b36)) {
 | 
			
		||||
                    Return (0x03)           // QXL
 | 
			
		||||
                } Else {
 | 
			
		||||
                    Return (0x00)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/****************************************************************
 | 
			
		||||
 * PIIX4 PM
 | 
			
		||||
 ****************************************************************/
 | 
			
		||||
@@ -132,6 +106,9 @@ DefinitionBlock (
 | 
			
		||||
 ****************************************************************/
 | 
			
		||||
 | 
			
		||||
    Scope(\_SB.PCI0) {
 | 
			
		||||
 | 
			
		||||
        External(ISA, DeviceObj)
 | 
			
		||||
 | 
			
		||||
        Device(ISA) {
 | 
			
		||||
            Name(_ADR, 0x00010000)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x44,
 | 
			
		||||
0x54,
 | 
			
		||||
0x87,
 | 
			
		||||
0x85,
 | 
			
		||||
0x11,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xb8,
 | 
			
		||||
0x8b,
 | 
			
		||||
0x42,
 | 
			
		||||
0x58,
 | 
			
		||||
0x50,
 | 
			
		||||
@@ -146,7 +146,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x1,
 | 
			
		||||
0x10,
 | 
			
		||||
0x4e,
 | 
			
		||||
0x15,
 | 
			
		||||
0x18,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
@@ -163,9 +163,9 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x11,
 | 
			
		||||
0x42,
 | 
			
		||||
0x7,
 | 
			
		||||
0xa,
 | 
			
		||||
0x6e,
 | 
			
		||||
0xa,
 | 
			
		||||
0x9e,
 | 
			
		||||
0x88,
 | 
			
		||||
0xd,
 | 
			
		||||
0x0,
 | 
			
		||||
@@ -217,11 +217,59 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x0,
 | 
			
		||||
0xd,
 | 
			
		||||
0xff,
 | 
			
		||||
0xad,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa1,
 | 
			
		||||
0x88,
 | 
			
		||||
0xd,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xc,
 | 
			
		||||
0x3,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xf,
 | 
			
		||||
0xae,
 | 
			
		||||
0xff,
 | 
			
		||||
0xae,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xf1,
 | 
			
		||||
0x0,
 | 
			
		||||
0x88,
 | 
			
		||||
0xd,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xc,
 | 
			
		||||
0x3,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x20,
 | 
			
		||||
0xaf,
 | 
			
		||||
0xdf,
 | 
			
		||||
0xaf,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xc0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x88,
 | 
			
		||||
0xd,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xc,
 | 
			
		||||
0x3,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xe4,
 | 
			
		||||
0xaf,
 | 
			
		||||
0xff,
 | 
			
		||||
0xff,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xf3,
 | 
			
		||||
0x1c,
 | 
			
		||||
0x50,
 | 
			
		||||
0x87,
 | 
			
		||||
0x17,
 | 
			
		||||
0x0,
 | 
			
		||||
@@ -347,7 +395,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x45,
 | 
			
		||||
0x53,
 | 
			
		||||
0xa,
 | 
			
		||||
0x5c,
 | 
			
		||||
0x8c,
 | 
			
		||||
0x50,
 | 
			
		||||
0x53,
 | 
			
		||||
0x33,
 | 
			
		||||
@@ -358,7 +406,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x45,
 | 
			
		||||
0x53,
 | 
			
		||||
0xa,
 | 
			
		||||
0x60,
 | 
			
		||||
0x90,
 | 
			
		||||
0x50,
 | 
			
		||||
0x45,
 | 
			
		||||
0x33,
 | 
			
		||||
@@ -369,7 +417,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x45,
 | 
			
		||||
0x53,
 | 
			
		||||
0xa,
 | 
			
		||||
0x68,
 | 
			
		||||
0x98,
 | 
			
		||||
0x50,
 | 
			
		||||
0x4c,
 | 
			
		||||
0x33,
 | 
			
		||||
@@ -638,103 +686,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x79,
 | 
			
		||||
0x0,
 | 
			
		||||
0x10,
 | 
			
		||||
0x40,
 | 
			
		||||
0x6,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x42,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x50,
 | 
			
		||||
0x43,
 | 
			
		||||
0x49,
 | 
			
		||||
0x30,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x43,
 | 
			
		||||
0x5,
 | 
			
		||||
0x56,
 | 
			
		||||
0x47,
 | 
			
		||||
0x41,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x41,
 | 
			
		||||
0x44,
 | 
			
		||||
0x52,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x2,
 | 
			
		||||
0x0,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x80,
 | 
			
		||||
0x50,
 | 
			
		||||
0x43,
 | 
			
		||||
0x49,
 | 
			
		||||
0x43,
 | 
			
		||||
0x2,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa,
 | 
			
		||||
0x4,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x81,
 | 
			
		||||
0xb,
 | 
			
		||||
0x50,
 | 
			
		||||
0x43,
 | 
			
		||||
0x49,
 | 
			
		||||
0x43,
 | 
			
		||||
0x3,
 | 
			
		||||
0x56,
 | 
			
		||||
0x45,
 | 
			
		||||
0x4e,
 | 
			
		||||
0x44,
 | 
			
		||||
0x20,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x31,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x32,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x19,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x33,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa0,
 | 
			
		||||
0xe,
 | 
			
		||||
0x93,
 | 
			
		||||
0x56,
 | 
			
		||||
0x45,
 | 
			
		||||
0x4e,
 | 
			
		||||
0x44,
 | 
			
		||||
0xc,
 | 
			
		||||
0x36,
 | 
			
		||||
0x1b,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xa4,
 | 
			
		||||
0xa,
 | 
			
		||||
0x3,
 | 
			
		||||
0xa1,
 | 
			
		||||
0x3,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x10,
 | 
			
		||||
0x25,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x5f,
 | 
			
		||||
@@ -860,7 +811,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x4e,
 | 
			
		||||
0x1,
 | 
			
		||||
0x10,
 | 
			
		||||
0x4b,
 | 
			
		||||
0x4a,
 | 
			
		||||
0x1e,
 | 
			
		||||
0x2f,
 | 
			
		||||
0x3,
 | 
			
		||||
@@ -878,7 +829,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x5f,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2d,
 | 
			
		||||
0x2c,
 | 
			
		||||
0x53,
 | 
			
		||||
0x4d,
 | 
			
		||||
0x43,
 | 
			
		||||
@@ -898,9 +849,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x54,
 | 
			
		||||
0x41,
 | 
			
		||||
0xb,
 | 
			
		||||
0x0,
 | 
			
		||||
0xff,
 | 
			
		||||
0xa,
 | 
			
		||||
0xf0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x43,
 | 
			
		||||
@@ -4061,7 +4011,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x1,
 | 
			
		||||
0x10,
 | 
			
		||||
0x47,
 | 
			
		||||
0xe,
 | 
			
		||||
0x11,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x42,
 | 
			
		||||
@@ -4291,6 +4241,54 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x3,
 | 
			
		||||
0x75,
 | 
			
		||||
0x60,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x50,
 | 
			
		||||
0x52,
 | 
			
		||||
0x45,
 | 
			
		||||
0x53,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x48,
 | 
			
		||||
0x49,
 | 
			
		||||
0x44,
 | 
			
		||||
0xd,
 | 
			
		||||
0x41,
 | 
			
		||||
0x43,
 | 
			
		||||
0x50,
 | 
			
		||||
0x49,
 | 
			
		||||
0x30,
 | 
			
		||||
0x30,
 | 
			
		||||
0x30,
 | 
			
		||||
0x34,
 | 
			
		||||
0x0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x43,
 | 
			
		||||
0x52,
 | 
			
		||||
0x53,
 | 
			
		||||
0x11,
 | 
			
		||||
0xd,
 | 
			
		||||
0xa,
 | 
			
		||||
0xa,
 | 
			
		||||
0x47,
 | 
			
		||||
0x1,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaf,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaf,
 | 
			
		||||
0x0,
 | 
			
		||||
0x20,
 | 
			
		||||
0x79,
 | 
			
		||||
0x0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x54,
 | 
			
		||||
0x41,
 | 
			
		||||
0xa,
 | 
			
		||||
0xb,
 | 
			
		||||
0x10,
 | 
			
		||||
0x42,
 | 
			
		||||
0xc,
 | 
			
		||||
@@ -4488,5 +4486,5 @@ static unsigned char AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x0
 | 
			
		||||
};
 | 
			
		||||
static unsigned short piix_dsdt_applesmc_sta[] = {
 | 
			
		||||
0x384
 | 
			
		||||
0x353
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -221,10 +221,16 @@ static void pc_init1(QEMUMachineInitArgs *args,
 | 
			
		||||
    } else {
 | 
			
		||||
        for(i = 0; i < MAX_IDE_BUS; i++) {
 | 
			
		||||
            ISADevice *dev;
 | 
			
		||||
            char busname[] = "ide.0";
 | 
			
		||||
            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
 | 
			
		||||
                               ide_irq[i],
 | 
			
		||||
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
 | 
			
		||||
            idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0");
 | 
			
		||||
            /*
 | 
			
		||||
             * The ide bus name is ide.0 for the first bus and ide.1 for the
 | 
			
		||||
             * second one.
 | 
			
		||||
             */
 | 
			
		||||
            busname[4] = '0' + i;
 | 
			
		||||
            idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -260,13 +266,14 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args)
 | 
			
		||||
{
 | 
			
		||||
    smbios_type1_defaults = false;
 | 
			
		||||
    gigabyte_align = false;
 | 
			
		||||
    option_rom_has_mr = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
 | 
			
		||||
{
 | 
			
		||||
    pc_compat_1_7(args);
 | 
			
		||||
    has_pci_info = false;
 | 
			
		||||
    rom_file_in_ram = false;
 | 
			
		||||
    rom_file_has_mr = false;
 | 
			
		||||
    has_acpi_build = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -244,13 +244,14 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args)
 | 
			
		||||
{
 | 
			
		||||
    smbios_type1_defaults = false;
 | 
			
		||||
    gigabyte_align = false;
 | 
			
		||||
    option_rom_has_mr = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
 | 
			
		||||
{
 | 
			
		||||
    pc_compat_1_7(args);
 | 
			
		||||
    has_pci_info = false;
 | 
			
		||||
    rom_file_in_ram = false;
 | 
			
		||||
    rom_file_has_mr = false;
 | 
			
		||||
    has_acpi_build = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,8 @@ DefinitionBlock (
 | 
			
		||||
            Name(_ADR, 0x00)
 | 
			
		||||
            Name(_UID, 1)
 | 
			
		||||
 | 
			
		||||
            External(ISA, DeviceObj)
 | 
			
		||||
 | 
			
		||||
            // _OSC: based on sample of ACPI3.0b spec
 | 
			
		||||
            Name(SUPP, 0) // PCI _OSC Support Field value
 | 
			
		||||
            Name(CTRL, 0) // PCI _OSC Control Field value
 | 
			
		||||
@@ -133,26 +135,6 @@ DefinitionBlock (
 | 
			
		||||
#include "acpi-dsdt-hpet.dsl"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/****************************************************************
 | 
			
		||||
 * VGA
 | 
			
		||||
 ****************************************************************/
 | 
			
		||||
 | 
			
		||||
    Scope(\_SB.PCI0) {
 | 
			
		||||
        Device(VGA) {
 | 
			
		||||
            Name(_ADR, 0x00010000)
 | 
			
		||||
            Method(_S1D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S2D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S3D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/****************************************************************
 | 
			
		||||
 * LPC ISA bridge
 | 
			
		||||
 ****************************************************************/
 | 
			
		||||
@@ -160,8 +142,7 @@ DefinitionBlock (
 | 
			
		||||
    Scope(\_SB.PCI0) {
 | 
			
		||||
        /* PCI D31:f0 LPC ISA bridge */
 | 
			
		||||
        Device(ISA) {
 | 
			
		||||
            /* PCI D31:f0 */
 | 
			
		||||
            Name(_ADR, 0x001f0000)
 | 
			
		||||
            Name (_ADR, 0x001F0000)  // _ADR: Address
 | 
			
		||||
 | 
			
		||||
            /* ICH9 PCI to ISA irq remapping */
 | 
			
		||||
            OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x44,
 | 
			
		||||
0x54,
 | 
			
		||||
0xdf,
 | 
			
		||||
0xd7,
 | 
			
		||||
0x1c,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xff,
 | 
			
		||||
0x3e,
 | 
			
		||||
0x42,
 | 
			
		||||
0x58,
 | 
			
		||||
0x50,
 | 
			
		||||
@@ -415,11 +415,11 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xf7,
 | 
			
		||||
0xd7,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xf8,
 | 
			
		||||
0xd8,
 | 
			
		||||
0xc,
 | 
			
		||||
0x88,
 | 
			
		||||
0xd,
 | 
			
		||||
@@ -853,61 +853,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x79,
 | 
			
		||||
0x0,
 | 
			
		||||
0x10,
 | 
			
		||||
0x36,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x42,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x50,
 | 
			
		||||
0x43,
 | 
			
		||||
0x49,
 | 
			
		||||
0x30,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2a,
 | 
			
		||||
0x56,
 | 
			
		||||
0x47,
 | 
			
		||||
0x41,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x41,
 | 
			
		||||
0x44,
 | 
			
		||||
0x52,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x31,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x32,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x33,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x10,
 | 
			
		||||
0x4c,
 | 
			
		||||
0x7,
 | 
			
		||||
0x2e,
 | 
			
		||||
@@ -1033,7 +978,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x4e,
 | 
			
		||||
0x1,
 | 
			
		||||
0x10,
 | 
			
		||||
0x4b,
 | 
			
		||||
0x4a,
 | 
			
		||||
0x1e,
 | 
			
		||||
0x2f,
 | 
			
		||||
0x3,
 | 
			
		||||
@@ -1051,7 +996,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x5f,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2d,
 | 
			
		||||
0x2c,
 | 
			
		||||
0x53,
 | 
			
		||||
0x4d,
 | 
			
		||||
0x43,
 | 
			
		||||
@@ -1071,9 +1016,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x54,
 | 
			
		||||
0x41,
 | 
			
		||||
0xb,
 | 
			
		||||
0x0,
 | 
			
		||||
0xff,
 | 
			
		||||
0xa,
 | 
			
		||||
0xf0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x43,
 | 
			
		||||
@@ -7016,7 +6960,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x1,
 | 
			
		||||
0x10,
 | 
			
		||||
0x47,
 | 
			
		||||
0xe,
 | 
			
		||||
0x11,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x42,
 | 
			
		||||
@@ -7121,8 +7065,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x54,
 | 
			
		||||
0x1,
 | 
			
		||||
0xb,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaf,
 | 
			
		||||
0xd8,
 | 
			
		||||
0xc,
 | 
			
		||||
0xa,
 | 
			
		||||
0x20,
 | 
			
		||||
0x5b,
 | 
			
		||||
@@ -7246,6 +7190,54 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x3,
 | 
			
		||||
0x75,
 | 
			
		||||
0x60,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x50,
 | 
			
		||||
0x52,
 | 
			
		||||
0x45,
 | 
			
		||||
0x53,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x48,
 | 
			
		||||
0x49,
 | 
			
		||||
0x44,
 | 
			
		||||
0xd,
 | 
			
		||||
0x41,
 | 
			
		||||
0x43,
 | 
			
		||||
0x50,
 | 
			
		||||
0x49,
 | 
			
		||||
0x30,
 | 
			
		||||
0x30,
 | 
			
		||||
0x30,
 | 
			
		||||
0x34,
 | 
			
		||||
0x0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x43,
 | 
			
		||||
0x52,
 | 
			
		||||
0x53,
 | 
			
		||||
0x11,
 | 
			
		||||
0xd,
 | 
			
		||||
0xa,
 | 
			
		||||
0xa,
 | 
			
		||||
0x47,
 | 
			
		||||
0x1,
 | 
			
		||||
0xd8,
 | 
			
		||||
0xc,
 | 
			
		||||
0xd8,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x20,
 | 
			
		||||
0x79,
 | 
			
		||||
0x0,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x54,
 | 
			
		||||
0x41,
 | 
			
		||||
0xa,
 | 
			
		||||
0xb,
 | 
			
		||||
0x10,
 | 
			
		||||
0x4f,
 | 
			
		||||
0x8,
 | 
			
		||||
@@ -7392,5 +7384,5 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 | 
			
		||||
0x0
 | 
			
		||||
};
 | 
			
		||||
static unsigned short q35_dsdt_applesmc_sta[] = {
 | 
			
		||||
0x431
 | 
			
		||||
0x3fa
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -46,5 +46,55 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_START ssdt_pcinohp_start
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_END ssdt_pcinohp_end
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_STRING ssdt_pcinohp_name
 | 
			
		||||
 | 
			
		||||
        // Extract the offsets of the device name, address dword and the slot
 | 
			
		||||
        // name byte - we fill them in for each device.
 | 
			
		||||
        Device(SBB) {
 | 
			
		||||
            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcinohp_adr
 | 
			
		||||
            Name(_ADR, 0xAA0000)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_START ssdt_pcivga_start
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_END ssdt_pcivga_end
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_STRING ssdt_pcivga_name
 | 
			
		||||
 | 
			
		||||
        // Extract the offsets of the device name, address dword and the slot
 | 
			
		||||
        // name byte - we fill them in for each device.
 | 
			
		||||
        Device(SCC) {
 | 
			
		||||
            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcivga_adr
 | 
			
		||||
            Name(_ADR, 0xAA0000)
 | 
			
		||||
            Method(_S1D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S2D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S3D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_START ssdt_pciqxl_start
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_END ssdt_pciqxl_end
 | 
			
		||||
        ACPI_EXTRACT_DEVICE_STRING ssdt_pciqxl_name
 | 
			
		||||
 | 
			
		||||
        // Extract the offsets of the device name, address dword and the slot
 | 
			
		||||
        // name byte - we fill them in for each device.
 | 
			
		||||
        Device(SDD) {
 | 
			
		||||
            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pciqxl_adr
 | 
			
		||||
            Name(_ADR, 0xAA0000)
 | 
			
		||||
            Method(_S1D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S2D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x00)
 | 
			
		||||
            }
 | 
			
		||||
            Method(_S3D, 0, NotSerialized) {
 | 
			
		||||
                Return (0x03)           // QXL
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,38 @@
 | 
			
		||||
static unsigned char ssdt_pcihp_name[] = {
 | 
			
		||||
0x33
 | 
			
		||||
0x34
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcivga_end[] = {
 | 
			
		||||
0x99
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcivga_name[] = {
 | 
			
		||||
0x70
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcihp_adr[] = {
 | 
			
		||||
0x44
 | 
			
		||||
0x45
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcinohp_end[] = {
 | 
			
		||||
0x6d
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcihp_end[] = {
 | 
			
		||||
0x5b
 | 
			
		||||
0x5c
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pciqxl_start[] = {
 | 
			
		||||
0x99
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcinohp_name[] = {
 | 
			
		||||
0x5f
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdp_pcihp_aml[] = {
 | 
			
		||||
0x53,
 | 
			
		||||
0x53,
 | 
			
		||||
0x44,
 | 
			
		||||
0x54,
 | 
			
		||||
0x5b,
 | 
			
		||||
0xc6,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0x1,
 | 
			
		||||
0xe8,
 | 
			
		||||
0x6b,
 | 
			
		||||
0x42,
 | 
			
		||||
0x58,
 | 
			
		||||
0x50,
 | 
			
		||||
@@ -45,7 +60,8 @@ static unsigned char ssdp_pcihp_aml[] = {
 | 
			
		||||
0x13,
 | 
			
		||||
0x20,
 | 
			
		||||
0x10,
 | 
			
		||||
0x36,
 | 
			
		||||
0x41,
 | 
			
		||||
0xa,
 | 
			
		||||
0x5c,
 | 
			
		||||
0x2e,
 | 
			
		||||
0x5f,
 | 
			
		||||
@@ -98,11 +114,138 @@ static unsigned char ssdp_pcihp_aml[] = {
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x55,
 | 
			
		||||
0x4e
 | 
			
		||||
0x4e,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0xf,
 | 
			
		||||
0x53,
 | 
			
		||||
0x42,
 | 
			
		||||
0x42,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x41,
 | 
			
		||||
0x44,
 | 
			
		||||
0x52,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaa,
 | 
			
		||||
0x0,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2a,
 | 
			
		||||
0x53,
 | 
			
		||||
0x43,
 | 
			
		||||
0x43,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x41,
 | 
			
		||||
0x44,
 | 
			
		||||
0x52,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaa,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x31,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x32,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x33,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x5b,
 | 
			
		||||
0x82,
 | 
			
		||||
0x2b,
 | 
			
		||||
0x53,
 | 
			
		||||
0x44,
 | 
			
		||||
0x44,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x41,
 | 
			
		||||
0x44,
 | 
			
		||||
0x52,
 | 
			
		||||
0xc,
 | 
			
		||||
0x0,
 | 
			
		||||
0x0,
 | 
			
		||||
0xaa,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x31,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x8,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x32,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0x0,
 | 
			
		||||
0x14,
 | 
			
		||||
0x9,
 | 
			
		||||
0x5f,
 | 
			
		||||
0x53,
 | 
			
		||||
0x33,
 | 
			
		||||
0x44,
 | 
			
		||||
0x0,
 | 
			
		||||
0xa4,
 | 
			
		||||
0xa,
 | 
			
		||||
0x3
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pciqxl_adr[] = {
 | 
			
		||||
0xa6
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcinohp_adr[] = {
 | 
			
		||||
0x69
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcivga_adr[] = {
 | 
			
		||||
0x7a
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pciqxl_name[] = {
 | 
			
		||||
0x9c
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcivga_start[] = {
 | 
			
		||||
0x6d
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pciqxl_end[] = {
 | 
			
		||||
0xc6
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcihp_start[] = {
 | 
			
		||||
0x30
 | 
			
		||||
0x31
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcihp_id[] = {
 | 
			
		||||
0x3d
 | 
			
		||||
0x3e
 | 
			
		||||
};
 | 
			
		||||
static unsigned char ssdt_pcinohp_start[] = {
 | 
			
		||||
0x5c
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@
 | 
			
		||||
#define AHCI_PORT_PRIV_DMA_SZ     (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
 | 
			
		||||
                                   AHCI_RX_FIS_SZ)
 | 
			
		||||
 | 
			
		||||
#define AHCI_IRQ_ON_SG            (1 << 31)
 | 
			
		||||
#define AHCI_IRQ_ON_SG            (1U << 31)
 | 
			
		||||
#define AHCI_CMD_ATAPI            (1 << 5)
 | 
			
		||||
#define AHCI_CMD_WRITE            (1 << 6)
 | 
			
		||||
#define AHCI_CMD_PREFETCH         (1 << 7)
 | 
			
		||||
@@ -61,7 +61,7 @@
 | 
			
		||||
/* HOST_CTL bits */
 | 
			
		||||
#define HOST_CTL_RESET            (1 << 0)  /* reset controller; self-clear */
 | 
			
		||||
#define HOST_CTL_IRQ_EN           (1 << 1)  /* global IRQ enable */
 | 
			
		||||
#define HOST_CTL_AHCI_EN          (1 << 31) /* AHCI enabled */
 | 
			
		||||
#define HOST_CTL_AHCI_EN          (1U << 31) /* AHCI enabled */
 | 
			
		||||
 | 
			
		||||
/* HOST_CAP bits */
 | 
			
		||||
#define HOST_CAP_SSC              (1 << 14) /* Slumber capable */
 | 
			
		||||
@@ -69,7 +69,7 @@
 | 
			
		||||
#define HOST_CAP_CLO              (1 << 24) /* Command List Override support */
 | 
			
		||||
#define HOST_CAP_SSS              (1 << 27) /* Staggered Spin-up */
 | 
			
		||||
#define HOST_CAP_NCQ              (1 << 30) /* Native Command Queueing */
 | 
			
		||||
#define HOST_CAP_64               (1 << 31) /* PCI DAC (64-bit DMA) support */
 | 
			
		||||
#define HOST_CAP_64               (1U << 31) /* PCI DAC (64-bit DMA) support */
 | 
			
		||||
 | 
			
		||||
/* registers for each SATA port */
 | 
			
		||||
#define PORT_LST_ADDR             0x00 /* command list DMA addr */
 | 
			
		||||
@@ -89,7 +89,7 @@
 | 
			
		||||
#define PORT_RESERVED             0x3c /* reserved */
 | 
			
		||||
 | 
			
		||||
/* PORT_IRQ_{STAT,MASK} bits */
 | 
			
		||||
#define PORT_IRQ_COLD_PRES        (1 << 31) /* cold presence detect */
 | 
			
		||||
#define PORT_IRQ_COLD_PRES        (1U << 31) /* cold presence detect */
 | 
			
		||||
#define PORT_IRQ_TF_ERR           (1 << 30) /* task file error */
 | 
			
		||||
#define PORT_IRQ_HBUS_ERR         (1 << 29) /* host bus fatal error */
 | 
			
		||||
#define PORT_IRQ_HBUS_DATA_ERR    (1 << 28) /* host bus data error */
 | 
			
		||||
@@ -151,7 +151,7 @@
 | 
			
		||||
#define PORT_IRQ_STAT_HBDS        (1 << 28) /* Host Bus Data Error Status */
 | 
			
		||||
#define PORT_IRQ_STAT_HBFS        (1 << 29) /* Host Bus Fatal Error Status */
 | 
			
		||||
#define PORT_IRQ_STAT_TFES        (1 << 30) /* Task File Error Status */
 | 
			
		||||
#define PORT_IRQ_STAT_CPDS        (1 << 31) /* Code Port Detect Status */
 | 
			
		||||
#define PORT_IRQ_STAT_CPDS        (1U << 31) /* Code Port Detect Status */
 | 
			
		||||
 | 
			
		||||
/* ap->flags bits */
 | 
			
		||||
#define AHCI_FLAG_NO_NCQ                  (1 << 24)
 | 
			
		||||
 
 | 
			
		||||
@@ -281,7 +281,7 @@ static void kbd_write_command(void *opaque, hwaddr addr,
 | 
			
		||||
        kbd_update_irq(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case KBD_CCMD_READ_INPORT:
 | 
			
		||||
        kbd_queue(s, 0x00, 0);
 | 
			
		||||
        kbd_queue(s, 0x80, 0);
 | 
			
		||||
        break;
 | 
			
		||||
    case KBD_CCMD_READ_OUTPORT:
 | 
			
		||||
        kbd_queue(s, s->outport, 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -93,9 +93,6 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
 | 
			
		||||
        uint32_t mask = 1 << vector;
 | 
			
		||||
        uint64_t entry = s->ioredtbl[vector];
 | 
			
		||||
 | 
			
		||||
        if (entry & (1 << IOAPIC_LVT_POLARITY_SHIFT)) {
 | 
			
		||||
            level = !level;
 | 
			
		||||
        }
 | 
			
		||||
        if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
 | 
			
		||||
            IOAPIC_TRIGGER_LEVEL) {
 | 
			
		||||
            /* level triggered */
 | 
			
		||||
 
 | 
			
		||||
@@ -228,7 +228,7 @@ int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
 | 
			
		||||
 | 
			
		||||
    encap.cap = KVM_CAP_IRQ_MPIC;
 | 
			
		||||
    encap.args[0] = opp->fd;
 | 
			
		||||
    encap.args[1] = cs->cpu_index;
 | 
			
		||||
    encap.args[1] = kvm_arch_vcpu_id(cs);
 | 
			
		||||
 | 
			
		||||
    return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,17 @@
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "qapi/visitor.h"
 | 
			
		||||
 | 
			
		||||
static int get_cpu_index_by_dt_id(int cpu_dt_id)
 | 
			
		||||
{
 | 
			
		||||
    PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
 | 
			
		||||
 | 
			
		||||
    if (cpu) {
 | 
			
		||||
        return cpu->parent_obj.cpu_index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cs = CPU(cpu);
 | 
			
		||||
@@ -659,7 +670,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
                          target_ulong opcode, target_ulong *args)
 | 
			
		||||
{
 | 
			
		||||
    target_ulong server = args[0];
 | 
			
		||||
    target_ulong server = get_cpu_index_by_dt_id(args[0]);
 | 
			
		||||
    target_ulong mfrr = args[1];
 | 
			
		||||
 | 
			
		||||
    if (server >= spapr->icp->nr_servers) {
 | 
			
		||||
@@ -728,7 +739,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nr = rtas_ld(args, 0);
 | 
			
		||||
    server = rtas_ld(args, 1);
 | 
			
		||||
    server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
 | 
			
		||||
    priority = rtas_ld(args, 2);
 | 
			
		||||
 | 
			
		||||
    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ static void icp_get_kvm_state(ICPState *ss)
 | 
			
		||||
    ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, ®);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        error_report("Unable to retrieve KVM interrupt controller state"
 | 
			
		||||
                " for CPU %d: %s", ss->cs->cpu_index, strerror(errno));
 | 
			
		||||
                " for CPU %ld: %s", kvm_arch_vcpu_id(ss->cs), strerror(errno));
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -97,7 +97,7 @@ static int icp_set_kvm_state(ICPState *ss, int version_id)
 | 
			
		||||
    ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, ®);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        error_report("Unable to restore KVM interrupt controller state (0x%"
 | 
			
		||||
                PRIx64 ") for CPU %d: %s", state, ss->cs->cpu_index,
 | 
			
		||||
                PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(ss->cs),
 | 
			
		||||
                strerror(errno));
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
@@ -325,15 +325,15 @@ static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
 | 
			
		||||
        struct kvm_enable_cap xics_enable_cap = {
 | 
			
		||||
            .cap = KVM_CAP_IRQ_XICS,
 | 
			
		||||
            .flags = 0,
 | 
			
		||||
            .args = {icpkvm->kernel_xics_fd, cs->cpu_index, 0, 0},
 | 
			
		||||
            .args = {icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs), 0, 0},
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        ss->cs = cs;
 | 
			
		||||
 | 
			
		||||
        ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            error_report("Unable to connect CPU%d to kernel XICS: %s",
 | 
			
		||||
                    cs->cpu_index, strerror(errno));
 | 
			
		||||
            error_report("Unable to connect CPU%ld to kernel XICS: %s",
 | 
			
		||||
                    kvm_arch_vcpu_id(cs), strerror(errno));
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
 | 
			
		||||
                           &entry, &kernel_low, &kernel_high, 1,
 | 
			
		||||
                           ELF_MACHINE, 0);
 | 
			
		||||
 | 
			
		||||
    if (!kernel_size) {
 | 
			
		||||
    if (kernel_size <= 0) {
 | 
			
		||||
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
			
		||||
                loader_params->kernel_filename);
 | 
			
		||||
        exit(1);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,3 +32,6 @@ obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_VIRTIO) += virtio-net.o
 | 
			
		||||
obj-y += vhost_net.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
 | 
			
		||||
			fsl_etsec/rings.o fsl_etsec/miim.o
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										465
									
								
								hw/net/fsl_etsec/etsec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								hw/net/fsl_etsec/etsec.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,465 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
#include "trace.h"
 | 
			
		||||
#include "hw/ptimer.h"
 | 
			
		||||
#include "etsec.h"
 | 
			
		||||
#include "registers.h"
 | 
			
		||||
 | 
			
		||||
/* #define HEX_DUMP */
 | 
			
		||||
/* #define DEBUG_REGISTER */
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_REGISTER
 | 
			
		||||
static const int debug_etsec = 1;
 | 
			
		||||
#else
 | 
			
		||||
static const int debug_etsec;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define DPRINTF(fmt, ...) do {                 \
 | 
			
		||||
    if (debug_etsec) {                         \
 | 
			
		||||
        qemu_log(fmt , ## __VA_ARGS__);        \
 | 
			
		||||
    }                                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC          *etsec     = opaque;
 | 
			
		||||
    uint32_t        reg_index = addr / 4;
 | 
			
		||||
    eTSEC_Register *reg       = NULL;
 | 
			
		||||
    uint32_t        ret       = 0x0;
 | 
			
		||||
 | 
			
		||||
    assert(reg_index < ETSEC_REG_NUMBER);
 | 
			
		||||
 | 
			
		||||
    reg = &etsec->regs[reg_index];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    switch (reg->access) {
 | 
			
		||||
    case ACC_WO:
 | 
			
		||||
        ret = 0x00000000;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case ACC_RW:
 | 
			
		||||
    case ACC_W1C:
 | 
			
		||||
    case ACC_RO:
 | 
			
		||||
    default:
 | 
			
		||||
        ret = reg->value;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DPRINTF("Read  0x%08x @ 0x" TARGET_FMT_plx
 | 
			
		||||
            "                            : %s (%s)\n",
 | 
			
		||||
            ret, addr, reg->name, reg->desc);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_tstat(eTSEC          *etsec,
 | 
			
		||||
                        eTSEC_Register *reg,
 | 
			
		||||
                        uint32_t        reg_index,
 | 
			
		||||
                        uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 8; i++) {
 | 
			
		||||
        /* Check THLTi flag in TSTAT */
 | 
			
		||||
        if (value & (1 << (31 - i))) {
 | 
			
		||||
            etsec_walk_tx_ring(etsec, i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Write 1 to clear */
 | 
			
		||||
    reg->value &= ~value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_rstat(eTSEC          *etsec,
 | 
			
		||||
                        eTSEC_Register *reg,
 | 
			
		||||
                        uint32_t        reg_index,
 | 
			
		||||
                        uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 8; i++) {
 | 
			
		||||
        /* Check QHLTi flag in RSTAT */
 | 
			
		||||
        if (value & (1 << (23 - i)) && !(reg->value & (1 << (23 - i)))) {
 | 
			
		||||
            etsec_walk_rx_ring(etsec, i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Write 1 to clear */
 | 
			
		||||
    reg->value &= ~value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_tbasex(eTSEC          *etsec,
 | 
			
		||||
                         eTSEC_Register *reg,
 | 
			
		||||
                         uint32_t        reg_index,
 | 
			
		||||
                         uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    reg->value = value & ~0x7;
 | 
			
		||||
 | 
			
		||||
    /* Copy this value in the ring's TxBD pointer */
 | 
			
		||||
    etsec->regs[TBPTR0 + (reg_index - TBASE0)].value = value & ~0x7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_rbasex(eTSEC          *etsec,
 | 
			
		||||
                         eTSEC_Register *reg,
 | 
			
		||||
                         uint32_t        reg_index,
 | 
			
		||||
                         uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    reg->value = value & ~0x7;
 | 
			
		||||
 | 
			
		||||
    /* Copy this value in the ring's RxBD pointer */
 | 
			
		||||
    etsec->regs[RBPTR0 + (reg_index - RBASE0)].value = value & ~0x7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_ievent(eTSEC          *etsec,
 | 
			
		||||
                         eTSEC_Register *reg,
 | 
			
		||||
                         uint32_t        reg_index,
 | 
			
		||||
                         uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    /* Write 1 to clear */
 | 
			
		||||
    reg->value &= ~value;
 | 
			
		||||
 | 
			
		||||
    if (!(reg->value & (IEVENT_TXF | IEVENT_TXF))) {
 | 
			
		||||
        qemu_irq_lower(etsec->tx_irq);
 | 
			
		||||
    }
 | 
			
		||||
    if (!(reg->value & (IEVENT_RXF | IEVENT_RXF))) {
 | 
			
		||||
        qemu_irq_lower(etsec->rx_irq);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!(reg->value & (IEVENT_MAG | IEVENT_GTSC | IEVENT_GRSC | IEVENT_TXC |
 | 
			
		||||
                        IEVENT_RXC | IEVENT_BABR | IEVENT_BABT | IEVENT_LC |
 | 
			
		||||
                        IEVENT_CRL | IEVENT_FGPI | IEVENT_FIR | IEVENT_FIQ |
 | 
			
		||||
                        IEVENT_DPE | IEVENT_PERR | IEVENT_EBERR | IEVENT_TXE |
 | 
			
		||||
                        IEVENT_XFUN | IEVENT_BSY | IEVENT_MSRO | IEVENT_MMRD |
 | 
			
		||||
                        IEVENT_MMRW))) {
 | 
			
		||||
        qemu_irq_lower(etsec->err_irq);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_dmactrl(eTSEC          *etsec,
 | 
			
		||||
                          eTSEC_Register *reg,
 | 
			
		||||
                          uint32_t        reg_index,
 | 
			
		||||
                          uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
    reg->value = value;
 | 
			
		||||
 | 
			
		||||
    if (value & DMACTRL_GRS) {
 | 
			
		||||
 | 
			
		||||
        if (etsec->rx_buffer_len != 0) {
 | 
			
		||||
            /* Graceful receive stop delayed until end of frame */
 | 
			
		||||
        } else {
 | 
			
		||||
            /* Graceful receive stop now */
 | 
			
		||||
            etsec->regs[IEVENT].value |= IEVENT_GRSC;
 | 
			
		||||
            if (etsec->regs[IMASK].value & IMASK_GRSCEN) {
 | 
			
		||||
                qemu_irq_raise(etsec->err_irq);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (value & DMACTRL_GTS) {
 | 
			
		||||
 | 
			
		||||
        if (etsec->tx_buffer_len != 0) {
 | 
			
		||||
            /* Graceful transmit stop delayed until end of frame */
 | 
			
		||||
        } else {
 | 
			
		||||
            /* Graceful transmit stop now */
 | 
			
		||||
            etsec->regs[IEVENT].value |= IEVENT_GTSC;
 | 
			
		||||
            if (etsec->regs[IMASK].value & IMASK_GTSCEN) {
 | 
			
		||||
                qemu_irq_raise(etsec->err_irq);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!(value & DMACTRL_WOP)) {
 | 
			
		||||
        /* Start polling */
 | 
			
		||||
        ptimer_stop(etsec->ptimer);
 | 
			
		||||
        ptimer_set_count(etsec->ptimer, 1);
 | 
			
		||||
        ptimer_run(etsec->ptimer, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void etsec_write(void     *opaque,
 | 
			
		||||
                        hwaddr    addr,
 | 
			
		||||
                        uint64_t  value,
 | 
			
		||||
                        unsigned  size)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC          *etsec     = opaque;
 | 
			
		||||
    uint32_t        reg_index = addr / 4;
 | 
			
		||||
    eTSEC_Register *reg       = NULL;
 | 
			
		||||
    uint32_t        before    = 0x0;
 | 
			
		||||
 | 
			
		||||
    assert(reg_index < ETSEC_REG_NUMBER);
 | 
			
		||||
 | 
			
		||||
    reg = &etsec->regs[reg_index];
 | 
			
		||||
    before = reg->value;
 | 
			
		||||
 | 
			
		||||
    switch (reg_index) {
 | 
			
		||||
    case IEVENT:
 | 
			
		||||
        write_ievent(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case DMACTRL:
 | 
			
		||||
        write_dmactrl(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case TSTAT:
 | 
			
		||||
        write_tstat(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case RSTAT:
 | 
			
		||||
        write_rstat(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case TBASE0 ... TBASE7:
 | 
			
		||||
        write_tbasex(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case RBASE0 ... RBASE7:
 | 
			
		||||
        write_rbasex(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case MIIMCFG ... MIIMIND:
 | 
			
		||||
        etsec_write_miim(etsec, reg, reg_index, value);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        /* Default handling */
 | 
			
		||||
        switch (reg->access) {
 | 
			
		||||
 | 
			
		||||
        case ACC_RW:
 | 
			
		||||
        case ACC_WO:
 | 
			
		||||
            reg->value = value;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ACC_W1C:
 | 
			
		||||
            reg->value &= ~value;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ACC_RO:
 | 
			
		||||
        default:
 | 
			
		||||
            /* Read Only or Unknown register */
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DPRINTF("Write 0x%08x @ 0x" TARGET_FMT_plx
 | 
			
		||||
            " val:0x%08x->0x%08x : %s (%s)\n",
 | 
			
		||||
            (unsigned int)value, addr, before, reg->value,
 | 
			
		||||
            reg->name, reg->desc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const MemoryRegionOps etsec_ops = {
 | 
			
		||||
    .read = etsec_read,
 | 
			
		||||
    .write = etsec_write,
 | 
			
		||||
    .endianness = DEVICE_NATIVE_ENDIAN,
 | 
			
		||||
    .impl = {
 | 
			
		||||
        .min_access_size = 4,
 | 
			
		||||
        .max_access_size = 4,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void etsec_timer_hit(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC *etsec = opaque;
 | 
			
		||||
 | 
			
		||||
    ptimer_stop(etsec->ptimer);
 | 
			
		||||
 | 
			
		||||
    if (!(etsec->regs[DMACTRL].value & DMACTRL_WOP)) {
 | 
			
		||||
 | 
			
		||||
        if (!(etsec->regs[DMACTRL].value & DMACTRL_GTS)) {
 | 
			
		||||
            etsec_walk_tx_ring(etsec, 0);
 | 
			
		||||
        }
 | 
			
		||||
        ptimer_set_count(etsec->ptimer, 1);
 | 
			
		||||
        ptimer_run(etsec->ptimer, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void etsec_reset(DeviceState *d)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC *etsec = ETSEC_COMMON(d);
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    int reg_index = 0;
 | 
			
		||||
 | 
			
		||||
    /* Default value for all registers */
 | 
			
		||||
    for (i = 0; i < ETSEC_REG_NUMBER; i++) {
 | 
			
		||||
        etsec->regs[i].name   = "Reserved";
 | 
			
		||||
        etsec->regs[i].desc   = "";
 | 
			
		||||
        etsec->regs[i].access = ACC_UNKNOWN;
 | 
			
		||||
        etsec->regs[i].value  = 0x00000000;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Set-up known registers */
 | 
			
		||||
    for (i = 0; eTSEC_registers_def[i].name != NULL; i++) {
 | 
			
		||||
 | 
			
		||||
        reg_index = eTSEC_registers_def[i].offset / 4;
 | 
			
		||||
 | 
			
		||||
        etsec->regs[reg_index].name   = eTSEC_registers_def[i].name;
 | 
			
		||||
        etsec->regs[reg_index].desc   = eTSEC_registers_def[i].desc;
 | 
			
		||||
        etsec->regs[reg_index].access = eTSEC_registers_def[i].access;
 | 
			
		||||
        etsec->regs[reg_index].value  = eTSEC_registers_def[i].reset;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    etsec->tx_buffer     = NULL;
 | 
			
		||||
    etsec->tx_buffer_len = 0;
 | 
			
		||||
    etsec->rx_buffer     = NULL;
 | 
			
		||||
    etsec->rx_buffer_len = 0;
 | 
			
		||||
 | 
			
		||||
    etsec->phy_status =
 | 
			
		||||
        MII_SR_EXTENDED_CAPS    | MII_SR_LINK_STATUS   | MII_SR_AUTONEG_CAPS  |
 | 
			
		||||
        MII_SR_AUTONEG_COMPLETE | MII_SR_PREAMBLE_SUPPRESS |
 | 
			
		||||
        MII_SR_EXTENDED_STATUS  | MII_SR_100T2_HD_CAPS | MII_SR_100T2_FD_CAPS |
 | 
			
		||||
        MII_SR_10T_HD_CAPS      | MII_SR_10T_FD_CAPS   | MII_SR_100X_HD_CAPS  |
 | 
			
		||||
        MII_SR_100X_FD_CAPS     | MII_SR_100T4_CAPS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void etsec_cleanup(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    /* qemu_log("eTSEC cleanup\n"); */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int etsec_can_receive(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC *etsec = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
    return etsec->rx_buffer_len == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t etsec_receive(NetClientState *nc,
 | 
			
		||||
                             const uint8_t  *buf,
 | 
			
		||||
                             size_t          size)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC *etsec = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
#if defined(HEX_DUMP)
 | 
			
		||||
    fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
 | 
			
		||||
    qemu_hexdump(buf, stderr, "", size);
 | 
			
		||||
#endif
 | 
			
		||||
    etsec_rx_ring_write(etsec, buf, size);
 | 
			
		||||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void etsec_set_link_status(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC *etsec = qemu_get_nic_opaque(nc);
 | 
			
		||||
 | 
			
		||||
    etsec_miim_link_status(etsec, nc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static NetClientInfo net_etsec_info = {
 | 
			
		||||
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
 | 
			
		||||
    .size = sizeof(NICState),
 | 
			
		||||
    .can_receive = etsec_can_receive,
 | 
			
		||||
    .receive = etsec_receive,
 | 
			
		||||
    .cleanup = etsec_cleanup,
 | 
			
		||||
    .link_status_changed = etsec_set_link_status,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void etsec_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC        *etsec = ETSEC_COMMON(dev);
 | 
			
		||||
 | 
			
		||||
    etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf,
 | 
			
		||||
                              object_get_typename(OBJECT(dev)), dev->id, etsec);
 | 
			
		||||
    qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    etsec->bh     = qemu_bh_new(etsec_timer_hit, etsec);
 | 
			
		||||
    etsec->ptimer = ptimer_init(etsec->bh);
 | 
			
		||||
    ptimer_set_freq(etsec->ptimer, 100);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void etsec_instance_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    eTSEC        *etsec = ETSEC_COMMON(obj);
 | 
			
		||||
    SysBusDevice *sbd   = SYS_BUS_DEVICE(obj);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&etsec->io_area, OBJECT(etsec), &etsec_ops, etsec,
 | 
			
		||||
                          "eTSEC", 0x1000);
 | 
			
		||||
    sysbus_init_mmio(sbd, &etsec->io_area);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(sbd, &etsec->tx_irq);
 | 
			
		||||
    sysbus_init_irq(sbd, &etsec->rx_irq);
 | 
			
		||||
    sysbus_init_irq(sbd, &etsec->err_irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property etsec_properties[] = {
 | 
			
		||||
    DEFINE_NIC_PROPERTIES(eTSEC, conf),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void etsec_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->realize = etsec_realize;
 | 
			
		||||
    dc->reset = etsec_reset;
 | 
			
		||||
    dc->props = etsec_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static TypeInfo etsec_info = {
 | 
			
		||||
    .name                  = "eTSEC",
 | 
			
		||||
    .parent                = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size         = sizeof(eTSEC),
 | 
			
		||||
    .class_init            = etsec_class_init,
 | 
			
		||||
    .instance_init         = etsec_instance_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void etsec_register_types(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&etsec_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(etsec_register_types)
 | 
			
		||||
 | 
			
		||||
DeviceState *etsec_create(hwaddr         base,
 | 
			
		||||
                          MemoryRegion * mr,
 | 
			
		||||
                          NICInfo      * nd,
 | 
			
		||||
                          qemu_irq       tx_irq,
 | 
			
		||||
                          qemu_irq       rx_irq,
 | 
			
		||||
                          qemu_irq       err_irq)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
 | 
			
		||||
    dev = qdev_create(NULL, "eTSEC");
 | 
			
		||||
    qdev_set_nic_properties(dev, nd);
 | 
			
		||||
 | 
			
		||||
    if (qdev_init(dev)) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, err_irq);
 | 
			
		||||
 | 
			
		||||
    memory_region_add_subregion(mr, base,
 | 
			
		||||
                                SYS_BUS_DEVICE(dev)->mmio[0].memory);
 | 
			
		||||
 | 
			
		||||
    return dev;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										174
									
								
								hw/net/fsl_etsec/etsec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								hw/net/fsl_etsec/etsec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _ETSEC_H_
 | 
			
		||||
#define _ETSEC_H_
 | 
			
		||||
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
#include "net/net.h"
 | 
			
		||||
#include "hw/ptimer.h"
 | 
			
		||||
 | 
			
		||||
/* Buffer Descriptors */
 | 
			
		||||
 | 
			
		||||
typedef struct eTSEC_rxtx_bd {
 | 
			
		||||
    uint16_t flags;
 | 
			
		||||
    uint16_t length;
 | 
			
		||||
    uint32_t bufptr;
 | 
			
		||||
} eTSEC_rxtx_bd;
 | 
			
		||||
 | 
			
		||||
#define BD_WRAP       (1 << 13)
 | 
			
		||||
#define BD_INTERRUPT  (1 << 12)
 | 
			
		||||
#define BD_LAST       (1 << 11)
 | 
			
		||||
 | 
			
		||||
#define BD_TX_READY     (1 << 15)
 | 
			
		||||
#define BD_TX_PADCRC    (1 << 14)
 | 
			
		||||
#define BD_TX_TC        (1 << 10)
 | 
			
		||||
#define BD_TX_PREDEF    (1 << 9)
 | 
			
		||||
#define BD_TX_HFELC     (1 << 7)
 | 
			
		||||
#define BD_TX_CFRL      (1 << 6)
 | 
			
		||||
#define BD_TX_RC_MASK   0xF
 | 
			
		||||
#define BD_TX_RC_OFFSET 0x2
 | 
			
		||||
#define BD_TX_TOEUN     (1 << 1)
 | 
			
		||||
#define BD_TX_TR        (1 << 0)
 | 
			
		||||
 | 
			
		||||
#define BD_RX_EMPTY     (1 << 15)
 | 
			
		||||
#define BD_RX_RO1       (1 << 14)
 | 
			
		||||
#define BD_RX_FIRST     (1 << 10)
 | 
			
		||||
#define BD_RX_MISS      (1 << 8)
 | 
			
		||||
#define BD_RX_BROADCAST (1 << 7)
 | 
			
		||||
#define BD_RX_MULTICAST (1 << 6)
 | 
			
		||||
#define BD_RX_LG        (1 << 5)
 | 
			
		||||
#define BD_RX_NO        (1 << 4)
 | 
			
		||||
#define BD_RX_SH        (1 << 3)
 | 
			
		||||
#define BD_RX_CR        (1 << 2)
 | 
			
		||||
#define BD_RX_OV        (1 << 1)
 | 
			
		||||
#define BD_RX_TR        (1 << 0)
 | 
			
		||||
 | 
			
		||||
/* Tx FCB flags */
 | 
			
		||||
#define FCB_TX_VLN     (1 << 7)
 | 
			
		||||
#define FCB_TX_IP      (1 << 6)
 | 
			
		||||
#define FCB_TX_IP6     (1 << 5)
 | 
			
		||||
#define FCB_TX_TUP     (1 << 4)
 | 
			
		||||
#define FCB_TX_UDP     (1 << 3)
 | 
			
		||||
#define FCB_TX_CIP     (1 << 2)
 | 
			
		||||
#define FCB_TX_CTU     (1 << 1)
 | 
			
		||||
#define FCB_TX_NPH     (1 << 0)
 | 
			
		||||
 | 
			
		||||
/* PHY Status Register */
 | 
			
		||||
#define MII_SR_EXTENDED_CAPS     0x0001    /* Extended register capabilities */
 | 
			
		||||
#define MII_SR_JABBER_DETECT     0x0002    /* Jabber Detected */
 | 
			
		||||
#define MII_SR_LINK_STATUS       0x0004    /* Link Status 1 = link */
 | 
			
		||||
#define MII_SR_AUTONEG_CAPS      0x0008    /* Auto Neg Capable */
 | 
			
		||||
#define MII_SR_REMOTE_FAULT      0x0010    /* Remote Fault Detect */
 | 
			
		||||
#define MII_SR_AUTONEG_COMPLETE  0x0020    /* Auto Neg Complete */
 | 
			
		||||
#define MII_SR_PREAMBLE_SUPPRESS 0x0040    /* Preamble may be suppressed */
 | 
			
		||||
#define MII_SR_EXTENDED_STATUS   0x0100    /* Ext. status info in Reg 0x0F */
 | 
			
		||||
#define MII_SR_100T2_HD_CAPS     0x0200    /* 100T2 Half Duplex Capable */
 | 
			
		||||
#define MII_SR_100T2_FD_CAPS     0x0400    /* 100T2 Full Duplex Capable */
 | 
			
		||||
#define MII_SR_10T_HD_CAPS       0x0800    /* 10T   Half Duplex Capable */
 | 
			
		||||
#define MII_SR_10T_FD_CAPS       0x1000    /* 10T   Full Duplex Capable */
 | 
			
		||||
#define MII_SR_100X_HD_CAPS      0x2000    /* 100X  Half Duplex Capable */
 | 
			
		||||
#define MII_SR_100X_FD_CAPS      0x4000    /* 100X  Full Duplex Capable */
 | 
			
		||||
#define MII_SR_100T4_CAPS        0x8000    /* 100T4 Capable */
 | 
			
		||||
 | 
			
		||||
/* eTSEC */
 | 
			
		||||
 | 
			
		||||
/* Number of register in the device */
 | 
			
		||||
#define ETSEC_REG_NUMBER 1024
 | 
			
		||||
 | 
			
		||||
typedef struct eTSEC_Register {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *desc;
 | 
			
		||||
    uint32_t    access;
 | 
			
		||||
    uint32_t    value;
 | 
			
		||||
} eTSEC_Register;
 | 
			
		||||
 | 
			
		||||
typedef struct eTSEC {
 | 
			
		||||
    SysBusDevice  busdev;
 | 
			
		||||
 | 
			
		||||
    MemoryRegion  io_area;
 | 
			
		||||
 | 
			
		||||
    eTSEC_Register regs[ETSEC_REG_NUMBER];
 | 
			
		||||
 | 
			
		||||
    NICState *nic;
 | 
			
		||||
    NICConf   conf;
 | 
			
		||||
 | 
			
		||||
    /* Tx */
 | 
			
		||||
 | 
			
		||||
    uint8_t       *tx_buffer;
 | 
			
		||||
    uint32_t       tx_buffer_len;
 | 
			
		||||
    eTSEC_rxtx_bd  first_bd;
 | 
			
		||||
 | 
			
		||||
    /* Rx */
 | 
			
		||||
 | 
			
		||||
    uint8_t       *rx_buffer;
 | 
			
		||||
    uint32_t       rx_buffer_len;
 | 
			
		||||
    uint32_t       rx_remaining_data;
 | 
			
		||||
    uint8_t        rx_first_in_frame;
 | 
			
		||||
    uint8_t        rx_fcb_size;
 | 
			
		||||
    eTSEC_rxtx_bd  rx_first_bd;
 | 
			
		||||
    uint8_t        rx_fcb[10];
 | 
			
		||||
    uint32_t       rx_padding;
 | 
			
		||||
 | 
			
		||||
    /* IRQs */
 | 
			
		||||
    qemu_irq     tx_irq;
 | 
			
		||||
    qemu_irq     rx_irq;
 | 
			
		||||
    qemu_irq     err_irq;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    uint16_t phy_status;
 | 
			
		||||
    uint16_t phy_control;
 | 
			
		||||
 | 
			
		||||
    /* Polling */
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
    struct ptimer_state *ptimer;
 | 
			
		||||
 | 
			
		||||
} eTSEC;
 | 
			
		||||
 | 
			
		||||
#define TYPE_ETSEC_COMMON "eTSEC"
 | 
			
		||||
#define ETSEC_COMMON(obj) \
 | 
			
		||||
     OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON)
 | 
			
		||||
 | 
			
		||||
#define eTSEC_TRANSMIT 1
 | 
			
		||||
#define eTSEC_RECEIVE  2
 | 
			
		||||
 | 
			
		||||
DeviceState *etsec_create(hwaddr        base,
 | 
			
		||||
                          MemoryRegion *mr,
 | 
			
		||||
                          NICInfo      *nd,
 | 
			
		||||
                          qemu_irq      tx_irq,
 | 
			
		||||
                          qemu_irq      rx_irq,
 | 
			
		||||
                          qemu_irq      err_irq);
 | 
			
		||||
 | 
			
		||||
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr);
 | 
			
		||||
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr);
 | 
			
		||||
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size);
 | 
			
		||||
 | 
			
		||||
void etsec_write_miim(eTSEC          *etsec,
 | 
			
		||||
                      eTSEC_Register *reg,
 | 
			
		||||
                      uint32_t        reg_index,
 | 
			
		||||
                      uint32_t        value);
 | 
			
		||||
 | 
			
		||||
void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc);
 | 
			
		||||
 | 
			
		||||
#endif /* ! _ETSEC_H_ */
 | 
			
		||||
							
								
								
									
										146
									
								
								hw/net/fsl_etsec/miim.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								hw/net/fsl_etsec/miim.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "etsec.h"
 | 
			
		||||
#include "registers.h"
 | 
			
		||||
 | 
			
		||||
/* #define DEBUG_MIIM */
 | 
			
		||||
 | 
			
		||||
#define MIIM_CONTROL    0
 | 
			
		||||
#define MIIM_STATUS     1
 | 
			
		||||
#define MIIM_PHY_ID_1   2
 | 
			
		||||
#define MIIM_PHY_ID_2   3
 | 
			
		||||
#define MIIM_T2_STATUS  10
 | 
			
		||||
#define MIIM_EXT_STATUS 15
 | 
			
		||||
 | 
			
		||||
static void miim_read_cycle(eTSEC *etsec)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t  phy;
 | 
			
		||||
    uint8_t  addr;
 | 
			
		||||
    uint16_t value;
 | 
			
		||||
 | 
			
		||||
    phy  = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
 | 
			
		||||
    (void)phy; /* Unreferenced */
 | 
			
		||||
    addr = etsec->regs[MIIMADD].value & 0x1F;
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
    case MIIM_CONTROL:
 | 
			
		||||
        value = etsec->phy_control;
 | 
			
		||||
        break;
 | 
			
		||||
    case MIIM_STATUS:
 | 
			
		||||
        value = etsec->phy_status;
 | 
			
		||||
        break;
 | 
			
		||||
    case MIIM_T2_STATUS:
 | 
			
		||||
        value = 0x1800;           /* Local and remote receivers OK */
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        value = 0x0;
 | 
			
		||||
        break;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_MIIM
 | 
			
		||||
    qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    etsec->regs[MIIMSTAT].value = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void miim_write_cycle(eTSEC *etsec)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t  phy;
 | 
			
		||||
    uint8_t  addr;
 | 
			
		||||
    uint16_t value;
 | 
			
		||||
 | 
			
		||||
    phy   = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
 | 
			
		||||
    (void)phy; /* Unreferenced */
 | 
			
		||||
    addr  = etsec->regs[MIIMADD].value & 0x1F;
 | 
			
		||||
    value = etsec->regs[MIIMCON].value & 0xffff;
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_MIIM
 | 
			
		||||
    qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
    case MIIM_CONTROL:
 | 
			
		||||
        etsec->phy_control = value & ~(0x8100);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void etsec_write_miim(eTSEC          *etsec,
 | 
			
		||||
                      eTSEC_Register *reg,
 | 
			
		||||
                      uint32_t        reg_index,
 | 
			
		||||
                      uint32_t        value)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    switch (reg_index) {
 | 
			
		||||
 | 
			
		||||
    case MIIMCOM:
 | 
			
		||||
        /* Read and scan cycle */
 | 
			
		||||
 | 
			
		||||
        if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) {
 | 
			
		||||
            /* Read */
 | 
			
		||||
            miim_read_cycle(etsec);
 | 
			
		||||
        }
 | 
			
		||||
        reg->value = value;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case MIIMCON:
 | 
			
		||||
        reg->value = value & 0xffff;
 | 
			
		||||
        miim_write_cycle(etsec);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        /* Default handling */
 | 
			
		||||
        switch (reg->access) {
 | 
			
		||||
 | 
			
		||||
        case ACC_RW:
 | 
			
		||||
        case ACC_WO:
 | 
			
		||||
            reg->value = value;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ACC_W1C:
 | 
			
		||||
            reg->value &= ~value;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ACC_RO:
 | 
			
		||||
        default:
 | 
			
		||||
            /* Read Only or Unknown register */
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    /* Set link status */
 | 
			
		||||
    if (nc->link_down) {
 | 
			
		||||
        etsec->phy_status &= ~MII_SR_LINK_STATUS;
 | 
			
		||||
    } else {
 | 
			
		||||
        etsec->phy_status |= MII_SR_LINK_STATUS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										295
									
								
								hw/net/fsl_etsec/registers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								hw/net/fsl_etsec/registers.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,295 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#include "registers.h"
 | 
			
		||||
 | 
			
		||||
const eTSEC_Register_Definition eTSEC_registers_def[] = {
 | 
			
		||||
{0x000, "TSEC_ID",  "Controller ID register",    ACC_RO,  0x01240000},
 | 
			
		||||
{0x004, "TSEC_ID2", "Controller ID register 2",  ACC_RO,  0x003000F0},
 | 
			
		||||
{0x010, "IEVENT",   "Interrupt event register",  ACC_W1C, 0x00000000},
 | 
			
		||||
{0x014, "IMASK",    "Interrupt mask register",   ACC_RW,  0x00000000},
 | 
			
		||||
{0x018, "EDIS",     "Error disabled register",   ACC_RW,  0x00000000},
 | 
			
		||||
{0x020, "ECNTRL",   "Ethernet control register", ACC_RW,  0x00000040},
 | 
			
		||||
{0x028, "PTV",      "Pause time value register", ACC_RW,  0x00000000},
 | 
			
		||||
{0x02C, "DMACTRL",  "DMA control register",      ACC_RW,  0x00000000},
 | 
			
		||||
{0x030, "TBIPA",    "TBI PHY address register",  ACC_RW,  0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC FIFO Control and Status Registers */
 | 
			
		||||
 | 
			
		||||
{0x058, "FIFO_RX_ALARM",          "FIFO receive alarm start threshold register",    ACC_RW, 0x00000040},
 | 
			
		||||
{0x05C, "FIFO_RX_ALARM_SHUTOFF",  "FIFO receive alarm shut-off threshold register", ACC_RW, 0x00000080},
 | 
			
		||||
{0x08C, "FIFO_TX_THR",            "FIFO transmit threshold register",               ACC_RW, 0x00000080},
 | 
			
		||||
{0x098, "FIFO_TX_STARVE",         "FIFO transmit starve register",                  ACC_RW, 0x00000040},
 | 
			
		||||
{0x09C, "FIFO_TX_STARVE_SHUTOFF", "FIFO transmit starve shut-off register",         ACC_RW, 0x00000080},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Transmit Control and Status Registers */
 | 
			
		||||
 | 
			
		||||
{0x100, "TCTRL",        "Transmit control register",                ACC_RW,  0x00000000},
 | 
			
		||||
{0x104, "TSTAT",        "Transmit status register",                 ACC_W1C, 0x00000000},
 | 
			
		||||
{0x108, "DFVLAN",       "Default VLAN control word",                ACC_RW,  0x81000000},
 | 
			
		||||
{0x110, "TXIC",         "Transmit interrupt coalescing register",   ACC_RW,  0x00000000},
 | 
			
		||||
{0x114, "TQUEUE",       "Transmit queue control register",          ACC_RW,  0x00008000},
 | 
			
		||||
{0x140, "TR03WT",       "TxBD Rings 0-3 round-robin weightings",    ACC_RW,  0x00000000},
 | 
			
		||||
{0x144, "TR47WT",       "TxBD Rings 4-7 round-robin weightings",    ACC_RW,  0x00000000},
 | 
			
		||||
{0x180, "TBDBPH",       "Tx data buffer pointer high bits",         ACC_RW,  0x00000000},
 | 
			
		||||
{0x184, "TBPTR0",       "TxBD pointer for ring 0",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x18C, "TBPTR1",       "TxBD pointer for ring 1",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x194, "TBPTR2",       "TxBD pointer for ring 2",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x19C, "TBPTR3",       "TxBD pointer for ring 3",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x1A4, "TBPTR4",       "TxBD pointer for ring 4",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x1AC, "TBPTR5",       "TxBD pointer for ring 5",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x1B4, "TBPTR6",       "TxBD pointer for ring 6",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x1BC, "TBPTR7",       "TxBD pointer for ring 7",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x200, "TBASEH",       "TxBD base address high bits",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x204, "TBASE0",       "TxBD base address of ring 0",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x20C, "TBASE1",       "TxBD base address of ring 1",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x214, "TBASE2",       "TxBD base address of ring 2",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x21C, "TBASE3",       "TxBD base address of ring 3",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x224, "TBASE4",       "TxBD base address of ring 4",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x22C, "TBASE5",       "TxBD base address of ring 5",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x234, "TBASE6",       "TxBD base address of ring 6",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x23C, "TBASE7",       "TxBD base address of ring 7",              ACC_RW,  0x00000000},
 | 
			
		||||
{0x280, "TMR_TXTS1_ID", "Tx time stamp identification tag (set 1)", ACC_RO,  0x00000000},
 | 
			
		||||
{0x284, "TMR_TXTS2_ID", "Tx time stamp identification tag (set 2)", ACC_RO,  0x00000000},
 | 
			
		||||
{0x2C0, "TMR_TXTS1_H",  "Tx time stamp high (set 1)",               ACC_RO,  0x00000000},
 | 
			
		||||
{0x2C4, "TMR_TXTS1_L",  "Tx time stamp high (set 1)",               ACC_RO,  0x00000000},
 | 
			
		||||
{0x2C8, "TMR_TXTS2_H",  "Tx time stamp high (set 2)",               ACC_RO,  0x00000000},
 | 
			
		||||
{0x2CC, "TMR_TXTS2_L",  "Tx time stamp high (set 2)",               ACC_RO,  0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Receive Control and Status Registers */
 | 
			
		||||
 | 
			
		||||
{0x300, "RCTRL",      "Receive control register",                     ACC_RW,  0x00000000},
 | 
			
		||||
{0x304, "RSTAT",      "Receive status register",                      ACC_W1C, 0x00000000},
 | 
			
		||||
{0x310, "RXIC",       "Receive interrupt coalescing register",        ACC_RW,  0x00000000},
 | 
			
		||||
{0x314, "RQUEUE",     "Receive queue control register.",              ACC_RW,  0x00800080},
 | 
			
		||||
{0x330, "RBIFX",      "Receive bit field extract control register",   ACC_RW,  0x00000000},
 | 
			
		||||
{0x334, "RQFAR",      "Receive queue filing table address register",  ACC_RW,  0x00000000},
 | 
			
		||||
{0x338, "RQFCR",      "Receive queue filing table control register",  ACC_RW,  0x00000000},
 | 
			
		||||
{0x33C, "RQFPR",      "Receive queue filing table property register", ACC_RW,  0x00000000},
 | 
			
		||||
{0x340, "MRBLR",      "Maximum receive buffer length register",       ACC_RW,  0x00000000},
 | 
			
		||||
{0x380, "RBDBPH",     "Rx data buffer pointer high bits",             ACC_RW,  0x00000000},
 | 
			
		||||
{0x384, "RBPTR0",     "RxBD pointer for ring 0",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x38C, "RBPTR1",     "RxBD pointer for ring 1",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x394, "RBPTR2",     "RxBD pointer for ring 2",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x39C, "RBPTR3",     "RxBD pointer for ring 3",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x3A4, "RBPTR4",     "RxBD pointer for ring 4",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x3AC, "RBPTR5",     "RxBD pointer for ring 5",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x3B4, "RBPTR6",     "RxBD pointer for ring 6",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x3BC, "RBPTR7",     "RxBD pointer for ring 7",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0x400, "RBASEH",     "RxBD base address high bits",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x404, "RBASE0",     "RxBD base address of ring 0",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x40C, "RBASE1",     "RxBD base address of ring 1",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x414, "RBASE2",     "RxBD base address of ring 2",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x41C, "RBASE3",     "RxBD base address of ring 3",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x424, "RBASE4",     "RxBD base address of ring 4",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x42C, "RBASE5",     "RxBD base address of ring 5",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x434, "RBASE6",     "RxBD base address of ring 6",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x43C, "RBASE7",     "RxBD base address of ring 7",                  ACC_RW,  0x00000000},
 | 
			
		||||
{0x4C0, "TMR_RXTS_H", "Rx timer time stamp register high",            ACC_RW,  0x00000000},
 | 
			
		||||
{0x4C4, "TMR_RXTS_L", "Rx timer time stamp register low",             ACC_RW,  0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC MAC Registers */
 | 
			
		||||
 | 
			
		||||
{0x500, "MACCFG1",     "MAC configuration register 1",          ACC_RW, 0x00000000},
 | 
			
		||||
{0x504, "MACCFG2",     "MAC configuration register 2",          ACC_RW, 0x00007000},
 | 
			
		||||
{0x508, "IPGIFG",      "Inter-packet/inter-frame gap register", ACC_RW, 0x40605060},
 | 
			
		||||
{0x50C, "HAFDUP",      "Half-duplex control",                   ACC_RW, 0x00A1F037},
 | 
			
		||||
{0x510, "MAXFRM",      "Maximum frame length",                  ACC_RW, 0x00000600},
 | 
			
		||||
{0x520, "MIIMCFG",     "MII management configuration",          ACC_RW, 0x00000007},
 | 
			
		||||
{0x524, "MIIMCOM",     "MII management command",                ACC_RW, 0x00000000},
 | 
			
		||||
{0x528, "MIIMADD",     "MII management address",                ACC_RW, 0x00000000},
 | 
			
		||||
{0x52C, "MIIMCON",     "MII management control",                ACC_WO, 0x00000000},
 | 
			
		||||
{0x530, "MIIMSTAT",    "MII management status",                 ACC_RO, 0x00000000},
 | 
			
		||||
{0x534, "MIIMIND",     "MII management indicator",              ACC_RO, 0x00000000},
 | 
			
		||||
{0x53C, "IFSTAT",      "Interface status",                      ACC_RO, 0x00000000},
 | 
			
		||||
{0x540, "MACSTNADDR1", "MAC station address register 1",        ACC_RW, 0x00000000},
 | 
			
		||||
{0x544, "MACSTNADDR2", "MAC station address register 2",        ACC_RW, 0x00000000},
 | 
			
		||||
{0x548, "MAC01ADDR1",  "MAC exact match address 1, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x54C, "MAC01ADDR2",  "MAC exact match address 1, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x550, "MAC02ADDR1",  "MAC exact match address 2, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x554, "MAC02ADDR2",  "MAC exact match address 2, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x558, "MAC03ADDR1",  "MAC exact match address 3, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x55C, "MAC03ADDR2",  "MAC exact match address 3, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x560, "MAC04ADDR1",  "MAC exact match address 4, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x564, "MAC04ADDR2",  "MAC exact match address 4, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x568, "MAC05ADDR1",  "MAC exact match address 5, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x56C, "MAC05ADDR2",  "MAC exact match address 5, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x570, "MAC06ADDR1",  "MAC exact match address 6, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x574, "MAC06ADDR2",  "MAC exact match address 6, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x578, "MAC07ADDR1",  "MAC exact match address 7, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x57C, "MAC07ADDR2",  "MAC exact match address 7, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x580, "MAC08ADDR1",  "MAC exact match address 8, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x584, "MAC08ADDR2",  "MAC exact match address 8, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x588, "MAC09ADDR1",  "MAC exact match address 9, part 1",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x58C, "MAC09ADDR2",  "MAC exact match address 9, part 2",     ACC_RW, 0x00000000},
 | 
			
		||||
{0x590, "MAC10ADDR1",  "MAC exact match address 10, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x594, "MAC10ADDR2",  "MAC exact match address 10, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x598, "MAC11ADDR1",  "MAC exact match address 11, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x59C, "MAC11ADDR2",  "MAC exact match address 11, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5A0, "MAC12ADDR1",  "MAC exact match address 12, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5A4, "MAC12ADDR2",  "MAC exact match address 12, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5A8, "MAC13ADDR1",  "MAC exact match address 13, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5AC, "MAC13ADDR2",  "MAC exact match address 13, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5B0, "MAC14ADDR1",  "MAC exact match address 14, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5B4, "MAC14ADDR2",  "MAC exact match address 14, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5B8, "MAC15ADDR1",  "MAC exact match address 15, part 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x5BC, "MAC15ADDR2",  "MAC exact match address 15, part 2",    ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC, "Transmit", "and", Receive, Counters */
 | 
			
		||||
 | 
			
		||||
{0x680, "TR64",  "Transmit and receive 64-byte frame counter ",                   ACC_RW, 0x00000000},
 | 
			
		||||
{0x684, "TR127", "Transmit and receive 65- to 127-byte frame counter",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x688, "TR255", "Transmit and receive 128- to 255-byte frame counter",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x68C, "TR511", "Transmit and receive 256- to 511-byte frame counter",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x690, "TR1K",  "Transmit and receive 512- to 1023-byte frame counter",          ACC_RW, 0x00000000},
 | 
			
		||||
{0x694, "TRMAX", "Transmit and receive 1024- to 1518-byte frame counter",         ACC_RW, 0x00000000},
 | 
			
		||||
{0x698, "TRMGV", "Transmit and receive 1519- to 1522-byte good VLAN frame count", ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Receive Counters */
 | 
			
		||||
 | 
			
		||||
{0x69C, "RBYT", "Receive byte counter",                  ACC_RW, 0x00000000},
 | 
			
		||||
{0x6A0, "RPKT", "Receive packet counter",                ACC_RW, 0x00000000},
 | 
			
		||||
{0x6A4, "RFCS", "Receive FCS error counter",             ACC_RW, 0x00000000},
 | 
			
		||||
{0x6A8, "RMCA", "Receive multicast packet counter",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6AC, "RBCA", "Receive broadcast packet counter",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6B0, "RXCF", "Receive control frame packet counter ", ACC_RW, 0x00000000},
 | 
			
		||||
{0x6B4, "RXPF", "Receive PAUSE frame packet counter",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x6B8, "RXUO", "Receive unknown OP code counter ",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6BC, "RALN", "Receive alignment error counter ",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6C0, "RFLR", "Receive frame length error counter ",   ACC_RW, 0x00000000},
 | 
			
		||||
{0x6C4, "RCDE", "Receive code error counter ",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x6C8, "RCSE", "Receive carrier sense error counter",   ACC_RW, 0x00000000},
 | 
			
		||||
{0x6CC, "RUND", "Receive undersize packet counter",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6D0, "ROVR", "Receive oversize packet counter ",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x6D4, "RFRG", "Receive fragments counter",             ACC_RW, 0x00000000},
 | 
			
		||||
{0x6D8, "RJBR", "Receive jabber counter ",               ACC_RW, 0x00000000},
 | 
			
		||||
{0x6DC, "RDRP", "Receive drop counter",                  ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Transmit Counters */
 | 
			
		||||
 | 
			
		||||
{0x6E0, "TBYT", "Transmit byte counter",                       ACC_RW, 0x00000000},
 | 
			
		||||
{0x6E4, "TPKT", "Transmit packet counter",                     ACC_RW, 0x00000000},
 | 
			
		||||
{0x6E8, "TMCA", "Transmit multicast packet counter ",          ACC_RW, 0x00000000},
 | 
			
		||||
{0x6EC, "TBCA", "Transmit broadcast packet counter ",          ACC_RW, 0x00000000},
 | 
			
		||||
{0x6F0, "TXPF", "Transmit PAUSE control frame counter ",       ACC_RW, 0x00000000},
 | 
			
		||||
{0x6F4, "TDFR", "Transmit deferral packet counter ",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x6F8, "TEDF", "Transmit excessive deferral packet counter ", ACC_RW, 0x00000000},
 | 
			
		||||
{0x6FC, "TSCL", "Transmit single collision packet counter",    ACC_RW, 0x00000000},
 | 
			
		||||
{0x700, "TMCL", "Transmit multiple collision packet counter",  ACC_RW, 0x00000000},
 | 
			
		||||
{0x704, "TLCL", "Transmit late collision packet counter",      ACC_RW, 0x00000000},
 | 
			
		||||
{0x708, "TXCL", "Transmit excessive collision packet counter", ACC_RW, 0x00000000},
 | 
			
		||||
{0x70C, "TNCL", "Transmit total collision counter ",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x714, "TDRP", "Transmit drop frame counter",                 ACC_RW, 0x00000000},
 | 
			
		||||
{0x718, "TJBR", "Transmit jabber frame counter ",              ACC_RW, 0x00000000},
 | 
			
		||||
{0x71C, "TFCS", "Transmit FCS error counter",                  ACC_RW, 0x00000000},
 | 
			
		||||
{0x720, "TXCF", "Transmit control frame counter ",             ACC_RW, 0x00000000},
 | 
			
		||||
{0x724, "TOVR", "Transmit oversize frame counter",             ACC_RW, 0x00000000},
 | 
			
		||||
{0x728, "TUND", "Transmit undersize frame counter ",           ACC_RW, 0x00000000},
 | 
			
		||||
{0x72C, "TFRG", "Transmit fragments frame counter ",           ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Counter Control and TOE Statistics Registers */
 | 
			
		||||
 | 
			
		||||
{0x730, "CAR1", "Carry register one register",           ACC_W1C, 0x00000000},
 | 
			
		||||
{0x734, "CAR2", "Carry register two register ",          ACC_W1C, 0x00000000},
 | 
			
		||||
{0x738, "CAM1", "Carry register one mask register ",     ACC_RW,  0xFE03FFFF},
 | 
			
		||||
{0x73C, "CAM2", "Carry register two mask register ",     ACC_RW,  0x000FFFFD},
 | 
			
		||||
{0x740, "RREJ", "Receive filer rejected packet counter", ACC_RW,  0x00000000},
 | 
			
		||||
 | 
			
		||||
/* Hash Function Registers */
 | 
			
		||||
 | 
			
		||||
{0x800, "IGADDR0", "Individual/group address register 0", ACC_RW, 0x00000000},
 | 
			
		||||
{0x804, "IGADDR1", "Individual/group address register 1", ACC_RW, 0x00000000},
 | 
			
		||||
{0x808, "IGADDR2", "Individual/group address register 2", ACC_RW, 0x00000000},
 | 
			
		||||
{0x80C, "IGADDR3", "Individual/group address register 3", ACC_RW, 0x00000000},
 | 
			
		||||
{0x810, "IGADDR4", "Individual/group address register 4", ACC_RW, 0x00000000},
 | 
			
		||||
{0x814, "IGADDR5", "Individual/group address register 5", ACC_RW, 0x00000000},
 | 
			
		||||
{0x818, "IGADDR6", "Individual/group address register 6", ACC_RW, 0x00000000},
 | 
			
		||||
{0x81C, "IGADDR7", "Individual/group address register 7", ACC_RW, 0x00000000},
 | 
			
		||||
{0x880, "GADDR0",  "Group address register 0",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x884, "GADDR1",  "Group address register 1",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x888, "GADDR2",  "Group address register 2",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x88C, "GADDR3",  "Group address register 3",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x890, "GADDR4",  "Group address register 4",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x894, "GADDR5",  "Group address register 5",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x898, "GADDR6",  "Group address register 6",            ACC_RW, 0x00000000},
 | 
			
		||||
{0x89C, "GADDR7",  "Group address register 7",            ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC DMA Attribute Registers */
 | 
			
		||||
 | 
			
		||||
{0xBF8, "ATTR",    "Attribute register",                                  ACC_RW, 0x00000000},
 | 
			
		||||
{0xBFC, "ATTRELI", "Attribute extract length and extract index register", ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* eTSEC Lossless Flow Control Registers */
 | 
			
		||||
 | 
			
		||||
{0xC00, "RQPRM0",  "Receive Queue Parameters register 0 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC04, "RQPRM1",  "Receive Queue Parameters register 1 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC08, "RQPRM2",  "Receive Queue Parameters register 2 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC0C, "RQPRM3",  "Receive Queue Parameters register 3 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC10, "RQPRM4",  "Receive Queue Parameters register 4 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC14, "RQPRM5",  "Receive Queue Parameters register 5 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC18, "RQPRM6",  "Receive Queue Parameters register 6 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC1C, "RQPRM7",  "Receive Queue Parameters register 7 ", ACC_RW, 0x00000000},
 | 
			
		||||
{0xC44, "RFBPTR0", "Last Free RxBD pointer for ring 0",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC4C, "RFBPTR1", "Last Free RxBD pointer for ring 1",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC54, "RFBPTR2", "Last Free RxBD pointer for ring 2",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC5C, "RFBPTR3", "Last Free RxBD pointer for ring 3",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC64, "RFBPTR4", "Last Free RxBD pointer for ring 4",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC6C, "RFBPTR5", "Last Free RxBD pointer for ring 5",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC74, "RFBPTR6", "Last Free RxBD pointer for ring 6",    ACC_RW, 0x00000000},
 | 
			
		||||
{0xC7C, "RFBPTR7", "Last Free RxBD pointer for ring 7",    ACC_RW, 0x00000000},
 | 
			
		||||
 | 
			
		||||
/* eTSEC Future Expansion Space */
 | 
			
		||||
 | 
			
		||||
/* Reserved*/
 | 
			
		||||
 | 
			
		||||
/* eTSEC IEEE 1588 Registers */
 | 
			
		||||
 | 
			
		||||
{0xE00, "TMR_CTRL",     "Timer control register",                          ACC_RW,  0x00010001},
 | 
			
		||||
{0xE04, "TMR_TEVENT",   "time stamp event register",                       ACC_W1C, 0x00000000},
 | 
			
		||||
{0xE08, "TMR_TEMASK",   "Timer event mask register",                       ACC_RW,  0x00000000},
 | 
			
		||||
{0xE0C, "TMR_PEVENT",   "time stamp event register",                       ACC_RW,  0x00000000},
 | 
			
		||||
{0xE10, "TMR_PEMASK",   "Timer event mask register",                       ACC_RW,  0x00000000},
 | 
			
		||||
{0xE14, "TMR_STAT",     "time stamp status register",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0xE18, "TMR_CNT_H",    "timer counter high register",                     ACC_RW,  0x00000000},
 | 
			
		||||
{0xE1C, "TMR_CNT_L",    "timer counter low register",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0xE20, "TMR_ADD",      "Timer drift compensation addend register",        ACC_RW,  0x00000000},
 | 
			
		||||
{0xE24, "TMR_ACC",      "Timer accumulator register",                      ACC_RW,  0x00000000},
 | 
			
		||||
{0xE28, "TMR_PRSC",     "Timer prescale",                                  ACC_RW,  0x00000002},
 | 
			
		||||
{0xE30, "TMROFF_H",     "Timer offset high",                               ACC_RW,  0x00000000},
 | 
			
		||||
{0xE34, "TMROFF_L",     "Timer offset low",                                ACC_RW,  0x00000000},
 | 
			
		||||
{0xE40, "TMR_ALARM1_H", "Timer alarm 1 high register",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE44, "TMR_ALARM1_L", "Timer alarm 1 high register",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE48, "TMR_ALARM2_H", "Timer alarm 2 high register",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE4C, "TMR_ALARM2_L", "Timer alarm 2 high register",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE80, "TMR_FIPER1",   "Timer fixed period interval",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE84, "TMR_FIPER2",   "Timer fixed period interval",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xE88, "TMR_FIPER3",   "Timer fixed period interval",                     ACC_RW,  0xFFFFFFFF},
 | 
			
		||||
{0xEA0, "TMR_ETTS1_H",  "Time stamp of general purpose external trigger ", ACC_RW,  0x00000000},
 | 
			
		||||
{0xEA4, "TMR_ETTS1_L",  "Time stamp of general purpose external trigger",  ACC_RW,  0x00000000},
 | 
			
		||||
{0xEA8, "TMR_ETTS2_H",  "Time stamp of general purpose external trigger ", ACC_RW,  0x00000000},
 | 
			
		||||
{0xEAC, "TMR_ETTS2_L",  "Time stamp of general purpose external trigger",  ACC_RW,  0x00000000},
 | 
			
		||||
 | 
			
		||||
/* End Of Table */
 | 
			
		||||
{0x0, 0x0, 0x0, 0x0, 0x0}
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										320
									
								
								hw/net/fsl_etsec/registers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								hw/net/fsl_etsec/registers.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,320 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _ETSEC_REGISTERS_H_
 | 
			
		||||
#define _ETSEC_REGISTERS_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
enum eTSEC_Register_Access_Type {
 | 
			
		||||
    ACC_RW      = 1,            /* Read/Write */
 | 
			
		||||
    ACC_RO      = 2,            /* Read Only */
 | 
			
		||||
    ACC_WO      = 3,            /* Write Only */
 | 
			
		||||
    ACC_W1C     = 4,            /* Write 1 to clear */
 | 
			
		||||
    ACC_UNKNOWN = 5             /* Unknown register*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct eTSEC_Register_Definition {
 | 
			
		||||
    uint32_t                         offset;
 | 
			
		||||
    const char                      *name;
 | 
			
		||||
    const char                      *desc;
 | 
			
		||||
    enum eTSEC_Register_Access_Type  access;
 | 
			
		||||
    uint32_t                         reset;
 | 
			
		||||
} eTSEC_Register_Definition;
 | 
			
		||||
 | 
			
		||||
extern const eTSEC_Register_Definition eTSEC_registers_def[];
 | 
			
		||||
 | 
			
		||||
#define DMACTRL_LE  (1 << 15)
 | 
			
		||||
#define DMACTRL_GRS (1 <<  4)
 | 
			
		||||
#define DMACTRL_GTS (1 <<  3)
 | 
			
		||||
#define DMACTRL_WOP (1 <<  0)
 | 
			
		||||
 | 
			
		||||
#define IEVENT_PERR  (1 <<  0)
 | 
			
		||||
#define IEVENT_DPE   (1 <<  1)
 | 
			
		||||
#define IEVENT_FIQ   (1 <<  2)
 | 
			
		||||
#define IEVENT_FIR   (1 <<  3)
 | 
			
		||||
#define IEVENT_FGPI  (1 <<  4)
 | 
			
		||||
#define IEVENT_RXF   (1 <<  7)
 | 
			
		||||
#define IEVENT_GRSC  (1 <<  8)
 | 
			
		||||
#define IEVENT_MMRW  (1 <<  9)
 | 
			
		||||
#define IEVENT_MMRD  (1 << 10)
 | 
			
		||||
#define IEVENT_MAG   (1 << 11)
 | 
			
		||||
#define IEVENT_RXB   (1 << 15)
 | 
			
		||||
#define IEVENT_XFUN  (1 << 16)
 | 
			
		||||
#define IEVENT_CRL   (1 << 17)
 | 
			
		||||
#define IEVENT_LC    (1 << 18)
 | 
			
		||||
#define IEVENT_TXF   (1 << 20)
 | 
			
		||||
#define IEVENT_TXB   (1 << 21)
 | 
			
		||||
#define IEVENT_TXE   (1 << 22)
 | 
			
		||||
#define IEVENT_TXC   (1 << 23)
 | 
			
		||||
#define IEVENT_BABT  (1 << 24)
 | 
			
		||||
#define IEVENT_GTSC  (1 << 25)
 | 
			
		||||
#define IEVENT_MSRO  (1 << 26)
 | 
			
		||||
#define IEVENT_EBERR (1 << 28)
 | 
			
		||||
#define IEVENT_BSY   (1 << 29)
 | 
			
		||||
#define IEVENT_RXC   (1 << 30)
 | 
			
		||||
#define IEVENT_BABR  (1 << 31)
 | 
			
		||||
 | 
			
		||||
#define IMASK_RXFEN  (1 <<  7)
 | 
			
		||||
#define IMASK_GRSCEN (1 <<  8)
 | 
			
		||||
#define IMASK_RXBEN  (1 << 15)
 | 
			
		||||
#define IMASK_TXFEN  (1 << 20)
 | 
			
		||||
#define IMASK_TXBEN  (1 << 21)
 | 
			
		||||
#define IMASK_GTSCEN (1 << 25)
 | 
			
		||||
 | 
			
		||||
#define MACCFG1_TX_EN  (1 << 0)
 | 
			
		||||
#define MACCFG1_RX_EN  (1 << 2)
 | 
			
		||||
 | 
			
		||||
#define MACCFG2_CRC_EN  (1 << 1)
 | 
			
		||||
#define MACCFG2_PADCRC  (1 << 2)
 | 
			
		||||
 | 
			
		||||
#define MIIMCOM_READ (1 << 0)
 | 
			
		||||
#define MIIMCOM_SCAN (1 << 1)
 | 
			
		||||
 | 
			
		||||
#define RCTRL_PRSDEP_MASK   (0x3)
 | 
			
		||||
#define RCTRL_PRSDEP_OFFSET (6)
 | 
			
		||||
#define RCTRL_RSF           (1 << 2)
 | 
			
		||||
 | 
			
		||||
/* Index of each register */
 | 
			
		||||
 | 
			
		||||
#define TSEC_ID      (0x000 / 4)
 | 
			
		||||
#define TSEC_ID2     (0x004 / 4)
 | 
			
		||||
#define IEVENT       (0x010 / 4)
 | 
			
		||||
#define IMASK        (0x014 / 4)
 | 
			
		||||
#define EDIS         (0x018 / 4)
 | 
			
		||||
#define ECNTRL       (0x020 / 4)
 | 
			
		||||
#define PTV          (0x028 / 4)
 | 
			
		||||
#define DMACTRL      (0x02C / 4)
 | 
			
		||||
#define TBIPA        (0x030 / 4)
 | 
			
		||||
#define TCTRL        (0x100 / 4)
 | 
			
		||||
#define TSTAT        (0x104 / 4)
 | 
			
		||||
#define DFVLAN       (0x108 / 4)
 | 
			
		||||
#define TXIC         (0x110 / 4)
 | 
			
		||||
#define TQUEUE       (0x114 / 4)
 | 
			
		||||
#define TR03WT       (0x140 / 4)
 | 
			
		||||
#define TR47WT       (0x144 / 4)
 | 
			
		||||
#define TBDBPH       (0x180 / 4)
 | 
			
		||||
#define TBPTR0       (0x184 / 4)
 | 
			
		||||
#define TBPTR1       (0x18C / 4)
 | 
			
		||||
#define TBPTR2       (0x194 / 4)
 | 
			
		||||
#define TBPTR3       (0x19C / 4)
 | 
			
		||||
#define TBPTR4       (0x1A4 / 4)
 | 
			
		||||
#define TBPTR5       (0x1AC / 4)
 | 
			
		||||
#define TBPTR6       (0x1B4 / 4)
 | 
			
		||||
#define TBPTR7       (0x1BC / 4)
 | 
			
		||||
#define TBASEH       (0x200 / 4)
 | 
			
		||||
#define TBASE0       (0x204 / 4)
 | 
			
		||||
#define TBASE1       (0x20C / 4)
 | 
			
		||||
#define TBASE2       (0x214 / 4)
 | 
			
		||||
#define TBASE3       (0x21C / 4)
 | 
			
		||||
#define TBASE4       (0x224 / 4)
 | 
			
		||||
#define TBASE5       (0x22C / 4)
 | 
			
		||||
#define TBASE6       (0x234 / 4)
 | 
			
		||||
#define TBASE7       (0x23C / 4)
 | 
			
		||||
#define TMR_TXTS1_ID (0x280 / 4)
 | 
			
		||||
#define TMR_TXTS2_ID (0x284 / 4)
 | 
			
		||||
#define TMR_TXTS1_H  (0x2C0 / 4)
 | 
			
		||||
#define TMR_TXTS1_L  (0x2C4 / 4)
 | 
			
		||||
#define TMR_TXTS2_H  (0x2C8 / 4)
 | 
			
		||||
#define TMR_TXTS2_L  (0x2CC / 4)
 | 
			
		||||
#define RCTRL        (0x300 / 4)
 | 
			
		||||
#define RSTAT        (0x304 / 4)
 | 
			
		||||
#define RXIC         (0x310 / 4)
 | 
			
		||||
#define RQUEUE       (0x314 / 4)
 | 
			
		||||
#define RBIFX        (0x330 / 4)
 | 
			
		||||
#define RQFAR        (0x334 / 4)
 | 
			
		||||
#define RQFCR        (0x338 / 4)
 | 
			
		||||
#define RQFPR        (0x33C / 4)
 | 
			
		||||
#define MRBLR        (0x340 / 4)
 | 
			
		||||
#define RBDBPH       (0x380 / 4)
 | 
			
		||||
#define RBPTR0       (0x384 / 4)
 | 
			
		||||
#define RBPTR1       (0x38C / 4)
 | 
			
		||||
#define RBPTR2       (0x394 / 4)
 | 
			
		||||
#define RBPTR3       (0x39C / 4)
 | 
			
		||||
#define RBPTR4       (0x3A4 / 4)
 | 
			
		||||
#define RBPTR5       (0x3AC / 4)
 | 
			
		||||
#define RBPTR6       (0x3B4 / 4)
 | 
			
		||||
#define RBPTR7       (0x3BC / 4)
 | 
			
		||||
#define RBASEH       (0x400 / 4)
 | 
			
		||||
#define RBASE0       (0x404 / 4)
 | 
			
		||||
#define RBASE1       (0x40C / 4)
 | 
			
		||||
#define RBASE2       (0x414 / 4)
 | 
			
		||||
#define RBASE3       (0x41C / 4)
 | 
			
		||||
#define RBASE4       (0x424 / 4)
 | 
			
		||||
#define RBASE5       (0x42C / 4)
 | 
			
		||||
#define RBASE6       (0x434 / 4)
 | 
			
		||||
#define RBASE7       (0x43C / 4)
 | 
			
		||||
#define TMR_RXTS_H   (0x4C0 / 4)
 | 
			
		||||
#define TMR_RXTS_L   (0x4C4 / 4)
 | 
			
		||||
#define MACCFG1      (0x500 / 4)
 | 
			
		||||
#define MACCFG2      (0x504 / 4)
 | 
			
		||||
#define IPGIFG       (0x508 / 4)
 | 
			
		||||
#define HAFDUP       (0x50C / 4)
 | 
			
		||||
#define MAXFRM       (0x510 / 4)
 | 
			
		||||
#define MIIMCFG      (0x520 / 4)
 | 
			
		||||
#define MIIMCOM      (0x524 / 4)
 | 
			
		||||
#define MIIMADD      (0x528 / 4)
 | 
			
		||||
#define MIIMCON      (0x52C / 4)
 | 
			
		||||
#define MIIMSTAT     (0x530 / 4)
 | 
			
		||||
#define MIIMIND      (0x534 / 4)
 | 
			
		||||
#define IFSTAT       (0x53C / 4)
 | 
			
		||||
#define MACSTNADDR1  (0x540 / 4)
 | 
			
		||||
#define MACSTNADDR2  (0x544 / 4)
 | 
			
		||||
#define MAC01ADDR1   (0x548 / 4)
 | 
			
		||||
#define MAC01ADDR2   (0x54C / 4)
 | 
			
		||||
#define MAC02ADDR1   (0x550 / 4)
 | 
			
		||||
#define MAC02ADDR2   (0x554 / 4)
 | 
			
		||||
#define MAC03ADDR1   (0x558 / 4)
 | 
			
		||||
#define MAC03ADDR2   (0x55C / 4)
 | 
			
		||||
#define MAC04ADDR1   (0x560 / 4)
 | 
			
		||||
#define MAC04ADDR2   (0x564 / 4)
 | 
			
		||||
#define MAC05ADDR1   (0x568 / 4)
 | 
			
		||||
#define MAC05ADDR2   (0x56C / 4)
 | 
			
		||||
#define MAC06ADDR1   (0x570 / 4)
 | 
			
		||||
#define MAC06ADDR2   (0x574 / 4)
 | 
			
		||||
#define MAC07ADDR1   (0x578 / 4)
 | 
			
		||||
#define MAC07ADDR2   (0x57C / 4)
 | 
			
		||||
#define MAC08ADDR1   (0x580 / 4)
 | 
			
		||||
#define MAC08ADDR2   (0x584 / 4)
 | 
			
		||||
#define MAC09ADDR1   (0x588 / 4)
 | 
			
		||||
#define MAC09ADDR2   (0x58C / 4)
 | 
			
		||||
#define MAC10ADDR1   (0x590 / 4)
 | 
			
		||||
#define MAC10ADDR2   (0x594 / 4)
 | 
			
		||||
#define MAC11ADDR1   (0x598 / 4)
 | 
			
		||||
#define MAC11ADDR2   (0x59C / 4)
 | 
			
		||||
#define MAC12ADDR1   (0x5A0 / 4)
 | 
			
		||||
#define MAC12ADDR2   (0x5A4 / 4)
 | 
			
		||||
#define MAC13ADDR1   (0x5A8 / 4)
 | 
			
		||||
#define MAC13ADDR2   (0x5AC / 4)
 | 
			
		||||
#define MAC14ADDR1   (0x5B0 / 4)
 | 
			
		||||
#define MAC14ADDR2   (0x5B4 / 4)
 | 
			
		||||
#define MAC15ADDR1   (0x5B8 / 4)
 | 
			
		||||
#define MAC15ADDR2   (0x5BC / 4)
 | 
			
		||||
#define TR64         (0x680 / 4)
 | 
			
		||||
#define TR127        (0x684 / 4)
 | 
			
		||||
#define TR255        (0x688 / 4)
 | 
			
		||||
#define TR511        (0x68C / 4)
 | 
			
		||||
#define TR1K         (0x690 / 4)
 | 
			
		||||
#define TRMAX        (0x694 / 4)
 | 
			
		||||
#define TRMGV        (0x698 / 4)
 | 
			
		||||
#define RBYT         (0x69C / 4)
 | 
			
		||||
#define RPKT         (0x6A0 / 4)
 | 
			
		||||
#define RFCS         (0x6A4 / 4)
 | 
			
		||||
#define RMCA         (0x6A8 / 4)
 | 
			
		||||
#define RBCA         (0x6AC / 4)
 | 
			
		||||
#define RXCF         (0x6B0 / 4)
 | 
			
		||||
#define RXPF         (0x6B4 / 4)
 | 
			
		||||
#define RXUO         (0x6B8 / 4)
 | 
			
		||||
#define RALN         (0x6BC / 4)
 | 
			
		||||
#define RFLR         (0x6C0 / 4)
 | 
			
		||||
#define RCDE         (0x6C4 / 4)
 | 
			
		||||
#define RCSE         (0x6C8 / 4)
 | 
			
		||||
#define RUND         (0x6CC / 4)
 | 
			
		||||
#define ROVR         (0x6D0 / 4)
 | 
			
		||||
#define RFRG         (0x6D4 / 4)
 | 
			
		||||
#define RJBR         (0x6D8 / 4)
 | 
			
		||||
#define RDRP         (0x6DC / 4)
 | 
			
		||||
#define TBYT         (0x6E0 / 4)
 | 
			
		||||
#define TPKT         (0x6E4 / 4)
 | 
			
		||||
#define TMCA         (0x6E8 / 4)
 | 
			
		||||
#define TBCA         (0x6EC / 4)
 | 
			
		||||
#define TXPF         (0x6F0 / 4)
 | 
			
		||||
#define TDFR         (0x6F4 / 4)
 | 
			
		||||
#define TEDF         (0x6F8 / 4)
 | 
			
		||||
#define TSCL         (0x6FC / 4)
 | 
			
		||||
#define TMCL         (0x700 / 4)
 | 
			
		||||
#define TLCL         (0x704 / 4)
 | 
			
		||||
#define TXCL         (0x708 / 4)
 | 
			
		||||
#define TNCL         (0x70C / 4)
 | 
			
		||||
#define TDRP         (0x714 / 4)
 | 
			
		||||
#define TJBR         (0x718 / 4)
 | 
			
		||||
#define TFCS         (0x71C / 4)
 | 
			
		||||
#define TXCF         (0x720 / 4)
 | 
			
		||||
#define TOVR         (0x724 / 4)
 | 
			
		||||
#define TUND         (0x728 / 4)
 | 
			
		||||
#define TFRG         (0x72C / 4)
 | 
			
		||||
#define CAR1         (0x730 / 4)
 | 
			
		||||
#define CAR2         (0x734 / 4)
 | 
			
		||||
#define CAM1         (0x738 / 4)
 | 
			
		||||
#define CAM2         (0x73C / 4)
 | 
			
		||||
#define RREJ         (0x740 / 4)
 | 
			
		||||
#define IGADDR0      (0x800 / 4)
 | 
			
		||||
#define IGADDR1      (0x804 / 4)
 | 
			
		||||
#define IGADDR2      (0x808 / 4)
 | 
			
		||||
#define IGADDR3      (0x80C / 4)
 | 
			
		||||
#define IGADDR4      (0x810 / 4)
 | 
			
		||||
#define IGADDR5      (0x814 / 4)
 | 
			
		||||
#define IGADDR6      (0x818 / 4)
 | 
			
		||||
#define IGADDR7      (0x81C / 4)
 | 
			
		||||
#define GADDR0       (0x880 / 4)
 | 
			
		||||
#define GADDR1       (0x884 / 4)
 | 
			
		||||
#define GADDR2       (0x888 / 4)
 | 
			
		||||
#define GADDR3       (0x88C / 4)
 | 
			
		||||
#define GADDR4       (0x890 / 4)
 | 
			
		||||
#define GADDR5       (0x894 / 4)
 | 
			
		||||
#define GADDR6       (0x898 / 4)
 | 
			
		||||
#define GADDR7       (0x89C / 4)
 | 
			
		||||
#define ATTR         (0xBF8 / 4)
 | 
			
		||||
#define ATTRELI      (0xBFC / 4)
 | 
			
		||||
#define RQPRM0       (0xC00 / 4)
 | 
			
		||||
#define RQPRM1       (0xC04 / 4)
 | 
			
		||||
#define RQPRM2       (0xC08 / 4)
 | 
			
		||||
#define RQPRM3       (0xC0C / 4)
 | 
			
		||||
#define RQPRM4       (0xC10 / 4)
 | 
			
		||||
#define RQPRM5       (0xC14 / 4)
 | 
			
		||||
#define RQPRM6       (0xC18 / 4)
 | 
			
		||||
#define RQPRM7       (0xC1C / 4)
 | 
			
		||||
#define RFBPTR0      (0xC44 / 4)
 | 
			
		||||
#define RFBPTR1      (0xC4C / 4)
 | 
			
		||||
#define RFBPTR2      (0xC54 / 4)
 | 
			
		||||
#define RFBPTR3      (0xC5C / 4)
 | 
			
		||||
#define RFBPTR4      (0xC64 / 4)
 | 
			
		||||
#define RFBPTR5      (0xC6C / 4)
 | 
			
		||||
#define RFBPTR6      (0xC74 / 4)
 | 
			
		||||
#define RFBPTR7      (0xC7C / 4)
 | 
			
		||||
#define TMR_CTRL     (0xE00 / 4)
 | 
			
		||||
#define TMR_TEVENT   (0xE04 / 4)
 | 
			
		||||
#define TMR_TEMASK   (0xE08 / 4)
 | 
			
		||||
#define TMR_PEVENT   (0xE0C / 4)
 | 
			
		||||
#define TMR_PEMASK   (0xE10 / 4)
 | 
			
		||||
#define TMR_STAT     (0xE14 / 4)
 | 
			
		||||
#define TMR_CNT_H    (0xE18 / 4)
 | 
			
		||||
#define TMR_CNT_L    (0xE1C / 4)
 | 
			
		||||
#define TMR_ADD      (0xE20 / 4)
 | 
			
		||||
#define TMR_ACC      (0xE24 / 4)
 | 
			
		||||
#define TMR_PRSC     (0xE28 / 4)
 | 
			
		||||
#define TMROFF_H     (0xE30 / 4)
 | 
			
		||||
#define TMROFF_L     (0xE34 / 4)
 | 
			
		||||
#define TMR_ALARM1_H (0xE40 / 4)
 | 
			
		||||
#define TMR_ALARM1_L (0xE44 / 4)
 | 
			
		||||
#define TMR_ALARM2_H (0xE48 / 4)
 | 
			
		||||
#define TMR_ALARM2_L (0xE4C / 4)
 | 
			
		||||
#define TMR_FIPER1   (0xE80 / 4)
 | 
			
		||||
#define TMR_FIPER2   (0xE84 / 4)
 | 
			
		||||
#define TMR_FIPER3   (0xE88 / 4)
 | 
			
		||||
#define TMR_ETTS1_H  (0xEA0 / 4)
 | 
			
		||||
#define TMR_ETTS1_L  (0xEA4 / 4)
 | 
			
		||||
#define TMR_ETTS2_H  (0xEA8 / 4)
 | 
			
		||||
#define TMR_ETTS2_L  (0xEAC / 4)
 | 
			
		||||
 | 
			
		||||
#endif /* ! _ETSEC_REGISTERS_H_ */
 | 
			
		||||
							
								
								
									
										650
									
								
								hw/net/fsl_etsec/rings.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										650
									
								
								hw/net/fsl_etsec/rings.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,650 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Freescale eTSEC Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2011-2013 AdaCore
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#include "net/checksum.h"
 | 
			
		||||
 | 
			
		||||
#include "etsec.h"
 | 
			
		||||
#include "registers.h"
 | 
			
		||||
 | 
			
		||||
/* #define ETSEC_RING_DEBUG */
 | 
			
		||||
/* #define HEX_DUMP */
 | 
			
		||||
/* #define DEBUG_BD */
 | 
			
		||||
 | 
			
		||||
#ifdef ETSEC_RING_DEBUG
 | 
			
		||||
static const int debug_etsec = 1;
 | 
			
		||||
#else
 | 
			
		||||
static const int debug_etsec;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define RING_DEBUG(fmt, ...) do {              \
 | 
			
		||||
 if (debug_etsec) {                            \
 | 
			
		||||
        qemu_log(fmt , ## __VA_ARGS__);        \
 | 
			
		||||
    }                                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_BD
 | 
			
		||||
 | 
			
		||||
static void print_tx_bd_flags(uint16_t flags)
 | 
			
		||||
{
 | 
			
		||||
    qemu_log("      Ready: %d\n", !!(flags & BD_TX_READY));
 | 
			
		||||
    qemu_log("      PAD/CRC: %d\n", !!(flags & BD_TX_PADCRC));
 | 
			
		||||
    qemu_log("      Wrap: %d\n", !!(flags & BD_WRAP));
 | 
			
		||||
    qemu_log("      Interrupt: %d\n", !!(flags & BD_INTERRUPT));
 | 
			
		||||
    qemu_log("      Last in frame: %d\n", !!(flags & BD_LAST));
 | 
			
		||||
    qemu_log("      Tx CRC: %d\n", !!(flags & BD_TX_TC));
 | 
			
		||||
    qemu_log("      User-defined preamble / defer: %d\n",
 | 
			
		||||
           !!(flags & BD_TX_PREDEF));
 | 
			
		||||
    qemu_log("      Huge frame enable / Late collision: %d\n",
 | 
			
		||||
           !!(flags & BD_TX_HFELC));
 | 
			
		||||
    qemu_log("      Control frame / Retransmission Limit: %d\n",
 | 
			
		||||
           !!(flags & BD_TX_CFRL));
 | 
			
		||||
    qemu_log("      Retry count: %d\n",
 | 
			
		||||
           (flags >> BD_TX_RC_OFFSET) & BD_TX_RC_MASK);
 | 
			
		||||
    qemu_log("      Underrun / TCP/IP off-load enable: %d\n",
 | 
			
		||||
           !!(flags & BD_TX_TOEUN));
 | 
			
		||||
    qemu_log("      Truncation: %d\n", !!(flags & BD_TX_TR));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_rx_bd_flags(uint16_t flags)
 | 
			
		||||
{
 | 
			
		||||
    qemu_log("      Empty: %d\n", !!(flags & BD_RX_EMPTY));
 | 
			
		||||
    qemu_log("      Receive software ownership: %d\n", !!(flags & BD_RX_RO1));
 | 
			
		||||
    qemu_log("      Wrap: %d\n", !!(flags & BD_WRAP));
 | 
			
		||||
    qemu_log("      Interrupt: %d\n", !!(flags & BD_INTERRUPT));
 | 
			
		||||
    qemu_log("      Last in frame: %d\n", !!(flags & BD_LAST));
 | 
			
		||||
    qemu_log("      First in frame: %d\n", !!(flags & BD_RX_FIRST));
 | 
			
		||||
    qemu_log("      Miss: %d\n", !!(flags & BD_RX_MISS));
 | 
			
		||||
    qemu_log("      Broadcast: %d\n", !!(flags & BD_RX_BROADCAST));
 | 
			
		||||
    qemu_log("      Multicast: %d\n", !!(flags & BD_RX_MULTICAST));
 | 
			
		||||
    qemu_log("      Rx frame length violation: %d\n", !!(flags & BD_RX_LG));
 | 
			
		||||
    qemu_log("      Rx non-octet aligned frame: %d\n", !!(flags & BD_RX_NO));
 | 
			
		||||
    qemu_log("      Short frame: %d\n", !!(flags & BD_RX_SH));
 | 
			
		||||
    qemu_log("      Rx CRC Error: %d\n", !!(flags & BD_RX_CR));
 | 
			
		||||
    qemu_log("      Overrun: %d\n", !!(flags & BD_RX_OV));
 | 
			
		||||
    qemu_log("      Truncation: %d\n", !!(flags & BD_RX_TR));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void print_bd(eTSEC_rxtx_bd bd, int mode, uint32_t index)
 | 
			
		||||
{
 | 
			
		||||
    qemu_log("eTSEC %s Data Buffer Descriptor (%u)\n",
 | 
			
		||||
           mode == eTSEC_TRANSMIT ? "Transmit" : "Receive",
 | 
			
		||||
           index);
 | 
			
		||||
    qemu_log("   Flags   : 0x%04x\n", bd.flags);
 | 
			
		||||
    if (mode == eTSEC_TRANSMIT) {
 | 
			
		||||
        print_tx_bd_flags(bd.flags);
 | 
			
		||||
    } else {
 | 
			
		||||
        print_rx_bd_flags(bd.flags);
 | 
			
		||||
    }
 | 
			
		||||
    qemu_log("   Length  : 0x%04x\n", bd.length);
 | 
			
		||||
    qemu_log("   Pointer : 0x%08x\n", bd.bufptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  /* DEBUG_BD */
 | 
			
		||||
 | 
			
		||||
static void read_buffer_descriptor(eTSEC         *etsec,
 | 
			
		||||
                                   hwaddr         addr,
 | 
			
		||||
                                   eTSEC_rxtx_bd *bd)
 | 
			
		||||
{
 | 
			
		||||
    assert(bd != NULL);
 | 
			
		||||
 | 
			
		||||
    RING_DEBUG("READ Buffer Descriptor @ 0x" TARGET_FMT_plx"\n", addr);
 | 
			
		||||
    cpu_physical_memory_read(addr,
 | 
			
		||||
                             bd,
 | 
			
		||||
                             sizeof(eTSEC_rxtx_bd));
 | 
			
		||||
 | 
			
		||||
    if (etsec->regs[DMACTRL].value & DMACTRL_LE) {
 | 
			
		||||
        bd->flags  = lduw_le_p(&bd->flags);
 | 
			
		||||
        bd->length = lduw_le_p(&bd->length);
 | 
			
		||||
        bd->bufptr = ldl_le_p(&bd->bufptr);
 | 
			
		||||
    } else {
 | 
			
		||||
        bd->flags  = lduw_be_p(&bd->flags);
 | 
			
		||||
        bd->length = lduw_be_p(&bd->length);
 | 
			
		||||
        bd->bufptr = ldl_be_p(&bd->bufptr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_buffer_descriptor(eTSEC         *etsec,
 | 
			
		||||
                                    hwaddr         addr,
 | 
			
		||||
                                    eTSEC_rxtx_bd *bd)
 | 
			
		||||
{
 | 
			
		||||
    assert(bd != NULL);
 | 
			
		||||
 | 
			
		||||
    if (etsec->regs[DMACTRL].value & DMACTRL_LE) {
 | 
			
		||||
        stw_le_p(&bd->flags, bd->flags);
 | 
			
		||||
        stw_le_p(&bd->length, bd->length);
 | 
			
		||||
        stl_le_p(&bd->bufptr, bd->bufptr);
 | 
			
		||||
    } else {
 | 
			
		||||
        stw_be_p(&bd->flags, bd->flags);
 | 
			
		||||
        stw_be_p(&bd->length, bd->length);
 | 
			
		||||
        stl_be_p(&bd->bufptr, bd->bufptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RING_DEBUG("Write Buffer Descriptor @ 0x" TARGET_FMT_plx"\n", addr);
 | 
			
		||||
    cpu_physical_memory_write(addr,
 | 
			
		||||
                              bd,
 | 
			
		||||
                              sizeof(eTSEC_rxtx_bd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ievent_set(eTSEC    *etsec,
 | 
			
		||||
                       uint32_t  flags)
 | 
			
		||||
{
 | 
			
		||||
    etsec->regs[IEVENT].value |= flags;
 | 
			
		||||
 | 
			
		||||
    if ((flags & IEVENT_TXB && etsec->regs[IMASK].value & IMASK_TXBEN)
 | 
			
		||||
        || (flags & IEVENT_TXF && etsec->regs[IMASK].value & IMASK_TXFEN)) {
 | 
			
		||||
        qemu_irq_raise(etsec->tx_irq);
 | 
			
		||||
        RING_DEBUG("%s Raise Tx IRQ\n", __func__);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((flags & IEVENT_RXB && etsec->regs[IMASK].value & IMASK_RXBEN)
 | 
			
		||||
        || (flags & IEVENT_RXF && etsec->regs[IMASK].value & IMASK_RXFEN)) {
 | 
			
		||||
        qemu_irq_pulse(etsec->rx_irq);
 | 
			
		||||
        RING_DEBUG("%s Raise Rx IRQ\n", __func__);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tx_padding_and_crc(eTSEC *etsec, uint32_t min_frame_len)
 | 
			
		||||
{
 | 
			
		||||
    int add = min_frame_len - etsec->tx_buffer_len;
 | 
			
		||||
 | 
			
		||||
    /* Padding */
 | 
			
		||||
    if (add > 0) {
 | 
			
		||||
        RING_DEBUG("pad:%u\n", add);
 | 
			
		||||
        etsec->tx_buffer = g_realloc(etsec->tx_buffer,
 | 
			
		||||
                                        etsec->tx_buffer_len + add);
 | 
			
		||||
 | 
			
		||||
        memset(etsec->tx_buffer + etsec->tx_buffer_len, 0x0, add);
 | 
			
		||||
        etsec->tx_buffer_len += add;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Never add CRC in QEMU */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void process_tx_fcb(eTSEC *etsec)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t flags = (uint8_t)(*etsec->tx_buffer);
 | 
			
		||||
    /* L3 header offset from start of frame */
 | 
			
		||||
    uint8_t l3_header_offset = (uint8_t)*(etsec->tx_buffer + 3);
 | 
			
		||||
    /* L4 header offset from start of L3 header */
 | 
			
		||||
    uint8_t l4_header_offset = (uint8_t)*(etsec->tx_buffer + 2);
 | 
			
		||||
    /* L3 header */
 | 
			
		||||
    uint8_t *l3_header = etsec->tx_buffer + 8 + l3_header_offset;
 | 
			
		||||
    /* L4 header */
 | 
			
		||||
    uint8_t *l4_header = l3_header + l4_header_offset;
 | 
			
		||||
 | 
			
		||||
    /* if packet is IP4 and IP checksum is requested */
 | 
			
		||||
    if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
 | 
			
		||||
        /* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure
 | 
			
		||||
         * if it also does IP4 checksum. */
 | 
			
		||||
        net_checksum_calculate(etsec->tx_buffer + 8,
 | 
			
		||||
                etsec->tx_buffer_len - 8);
 | 
			
		||||
    }
 | 
			
		||||
    /* TODO Check the correct usage of the PHCS field of the FCB in case the NPH
 | 
			
		||||
     * flag is on */
 | 
			
		||||
 | 
			
		||||
    /* if packet is IP4 and TCP or UDP */
 | 
			
		||||
    if (flags & FCB_TX_IP && flags & FCB_TX_TUP) {
 | 
			
		||||
        /* if UDP */
 | 
			
		||||
        if (flags & FCB_TX_UDP) {
 | 
			
		||||
            /* if checksum is requested */
 | 
			
		||||
            if (flags & FCB_TX_CTU) {
 | 
			
		||||
                /* do UDP checksum */
 | 
			
		||||
 | 
			
		||||
                net_checksum_calculate(etsec->tx_buffer + 8,
 | 
			
		||||
                        etsec->tx_buffer_len - 8);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* set checksum field to 0 */
 | 
			
		||||
                l4_header[6] = 0;
 | 
			
		||||
                l4_header[7] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (flags & FCB_TX_CTU) { /* if TCP and checksum is requested */
 | 
			
		||||
            /* do TCP checksum */
 | 
			
		||||
            net_checksum_calculate(etsec->tx_buffer + 8,
 | 
			
		||||
                                   etsec->tx_buffer_len - 8);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void process_tx_bd(eTSEC         *etsec,
 | 
			
		||||
                          eTSEC_rxtx_bd *bd)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *tmp_buff = NULL;
 | 
			
		||||
    hwaddr tbdbth     = (hwaddr)(etsec->regs[TBDBPH].value & 0xF) << 32;
 | 
			
		||||
 | 
			
		||||
    if (bd->length == 0) {
 | 
			
		||||
        /* ERROR */
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (etsec->tx_buffer_len == 0) {
 | 
			
		||||
        /* It's the first BD */
 | 
			
		||||
        etsec->first_bd = *bd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* TODO: if TxBD[TOE/UN] skip the Tx Frame Control Block*/
 | 
			
		||||
 | 
			
		||||
    /* Load this Data Buffer */
 | 
			
		||||
    etsec->tx_buffer = g_realloc(etsec->tx_buffer,
 | 
			
		||||
                                    etsec->tx_buffer_len + bd->length);
 | 
			
		||||
    tmp_buff = etsec->tx_buffer + etsec->tx_buffer_len;
 | 
			
		||||
    cpu_physical_memory_read(bd->bufptr + tbdbth, tmp_buff, bd->length);
 | 
			
		||||
 | 
			
		||||
    /* Update buffer length */
 | 
			
		||||
    etsec->tx_buffer_len += bd->length;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (etsec->tx_buffer_len != 0 && (bd->flags & BD_LAST)) {
 | 
			
		||||
        if (etsec->regs[MACCFG1].value & MACCFG1_TX_EN) {
 | 
			
		||||
            /* MAC Transmit enabled */
 | 
			
		||||
 | 
			
		||||
            /* Process offload Tx FCB */
 | 
			
		||||
            if (etsec->first_bd.flags & BD_TX_TOEUN) {
 | 
			
		||||
                process_tx_fcb(etsec);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (etsec->first_bd.flags & BD_TX_PADCRC
 | 
			
		||||
                || etsec->regs[MACCFG2].value & MACCFG2_PADCRC) {
 | 
			
		||||
 | 
			
		||||
                /* Padding and CRC (Padding implies CRC) */
 | 
			
		||||
                tx_padding_and_crc(etsec, 64);
 | 
			
		||||
 | 
			
		||||
            } else if (etsec->first_bd.flags & BD_TX_TC
 | 
			
		||||
                       || etsec->regs[MACCFG2].value & MACCFG2_CRC_EN) {
 | 
			
		||||
 | 
			
		||||
                /* Only CRC */
 | 
			
		||||
                /* Never add CRC in QEMU */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#if defined(HEX_DUMP)
 | 
			
		||||
            qemu_log("eTSEC Send packet size:%d\n", etsec->tx_buffer_len);
 | 
			
		||||
            qemu_hexdump(etsec->tx_buffer, stderr, "", etsec->tx_buffer_len);
 | 
			
		||||
#endif  /* ETSEC_RING_DEBUG */
 | 
			
		||||
 | 
			
		||||
            if (etsec->first_bd.flags & BD_TX_TOEUN) {
 | 
			
		||||
                qemu_send_packet(qemu_get_queue(etsec->nic),
 | 
			
		||||
                        etsec->tx_buffer + 8,
 | 
			
		||||
                        etsec->tx_buffer_len - 8);
 | 
			
		||||
            } else {
 | 
			
		||||
                qemu_send_packet(qemu_get_queue(etsec->nic),
 | 
			
		||||
                        etsec->tx_buffer,
 | 
			
		||||
                        etsec->tx_buffer_len);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        etsec->tx_buffer_len = 0;
 | 
			
		||||
 | 
			
		||||
        if (bd->flags & BD_INTERRUPT) {
 | 
			
		||||
            ievent_set(etsec, IEVENT_TXF);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (bd->flags & BD_INTERRUPT) {
 | 
			
		||||
            ievent_set(etsec, IEVENT_TXB);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Update DB flags */
 | 
			
		||||
 | 
			
		||||
    /* Clear Ready */
 | 
			
		||||
    bd->flags &= ~BD_TX_READY;
 | 
			
		||||
 | 
			
		||||
    /* Clear Defer */
 | 
			
		||||
    bd->flags &= ~BD_TX_PREDEF;
 | 
			
		||||
 | 
			
		||||
    /* Clear Late Collision */
 | 
			
		||||
    bd->flags &= ~BD_TX_HFELC;
 | 
			
		||||
 | 
			
		||||
    /* Clear Retransmission Limit */
 | 
			
		||||
    bd->flags &= ~BD_TX_CFRL;
 | 
			
		||||
 | 
			
		||||
    /* Clear Retry Count */
 | 
			
		||||
    bd->flags &= ~(BD_TX_RC_MASK << BD_TX_RC_OFFSET);
 | 
			
		||||
 | 
			
		||||
    /* Clear Underrun */
 | 
			
		||||
    bd->flags &= ~BD_TX_TOEUN;
 | 
			
		||||
 | 
			
		||||
    /* Clear Truncation */
 | 
			
		||||
    bd->flags &= ~BD_TX_TR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 | 
			
		||||
{
 | 
			
		||||
    hwaddr        ring_base = 0;
 | 
			
		||||
    hwaddr        bd_addr   = 0;
 | 
			
		||||
    eTSEC_rxtx_bd bd;
 | 
			
		||||
    uint16_t      bd_flags;
 | 
			
		||||
 | 
			
		||||
    if (!(etsec->regs[MACCFG1].value & MACCFG1_TX_EN)) {
 | 
			
		||||
        RING_DEBUG("%s: MAC Transmit not enabled\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ring_base = (hwaddr)(etsec->regs[TBASEH].value & 0xF) << 32;
 | 
			
		||||
    ring_base += etsec->regs[TBASE0 + ring_nbr].value & ~0x7;
 | 
			
		||||
    bd_addr    = etsec->regs[TBPTR0 + ring_nbr].value & ~0x7;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        read_buffer_descriptor(etsec, bd_addr, &bd);
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_BD
 | 
			
		||||
        print_bd(bd,
 | 
			
		||||
                 eTSEC_TRANSMIT,
 | 
			
		||||
                 (bd_addr - ring_base) / sizeof(eTSEC_rxtx_bd));
 | 
			
		||||
 | 
			
		||||
#endif  /* DEBUG_BD */
 | 
			
		||||
 | 
			
		||||
        /* Save flags before BD update */
 | 
			
		||||
        bd_flags = bd.flags;
 | 
			
		||||
 | 
			
		||||
        if (bd_flags & BD_TX_READY) {
 | 
			
		||||
            process_tx_bd(etsec, &bd);
 | 
			
		||||
 | 
			
		||||
            /* Write back BD after update */
 | 
			
		||||
            write_buffer_descriptor(etsec, bd_addr, &bd);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Wrap or next BD */
 | 
			
		||||
        if (bd_flags & BD_WRAP) {
 | 
			
		||||
            bd_addr = ring_base;
 | 
			
		||||
        } else {
 | 
			
		||||
            bd_addr += sizeof(eTSEC_rxtx_bd);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } while (bd_addr != ring_base);
 | 
			
		||||
 | 
			
		||||
    bd_addr = ring_base;
 | 
			
		||||
 | 
			
		||||
    /* Save the Buffer Descriptor Pointers to current bd */
 | 
			
		||||
    etsec->regs[TBPTR0 + ring_nbr].value = bd_addr;
 | 
			
		||||
 | 
			
		||||
    /* Set transmit halt THLTx */
 | 
			
		||||
    etsec->regs[TSTAT].value |= 1 << (31 - ring_nbr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fill_rx_bd(eTSEC          *etsec,
 | 
			
		||||
                       eTSEC_rxtx_bd  *bd,
 | 
			
		||||
                       const uint8_t **buf,
 | 
			
		||||
                       size_t         *size)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t to_write;
 | 
			
		||||
    hwaddr   bufptr = bd->bufptr +
 | 
			
		||||
        ((hwaddr)(etsec->regs[TBDBPH].value & 0xF) << 32);
 | 
			
		||||
    uint8_t  padd[etsec->rx_padding];
 | 
			
		||||
    uint8_t  rem;
 | 
			
		||||
 | 
			
		||||
    RING_DEBUG("eTSEC fill Rx buffer @ 0x%016" HWADDR_PRIx
 | 
			
		||||
               " size:%zu(padding + crc:%u) + fcb:%u\n",
 | 
			
		||||
               bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size);
 | 
			
		||||
 | 
			
		||||
    bd->length = 0;
 | 
			
		||||
 | 
			
		||||
    /* This operation will only write FCB */
 | 
			
		||||
    if (etsec->rx_fcb_size != 0) {
 | 
			
		||||
 | 
			
		||||
        cpu_physical_memory_write(bufptr, etsec->rx_fcb, etsec->rx_fcb_size);
 | 
			
		||||
 | 
			
		||||
        bufptr             += etsec->rx_fcb_size;
 | 
			
		||||
        bd->length         += etsec->rx_fcb_size;
 | 
			
		||||
        etsec->rx_fcb_size  = 0;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* We remove padding from the computation of to_write because it is not
 | 
			
		||||
     * allocated in the buffer.
 | 
			
		||||
     */
 | 
			
		||||
    to_write = MIN(*size - etsec->rx_padding,
 | 
			
		||||
                   etsec->regs[MRBLR].value - etsec->rx_fcb_size);
 | 
			
		||||
 | 
			
		||||
    /* This operation can only write packet data and no padding */
 | 
			
		||||
    if (to_write > 0) {
 | 
			
		||||
        cpu_physical_memory_write(bufptr, *buf, to_write);
 | 
			
		||||
 | 
			
		||||
        *buf   += to_write;
 | 
			
		||||
        bufptr += to_write;
 | 
			
		||||
        *size  -= to_write;
 | 
			
		||||
 | 
			
		||||
        bd->flags  &= ~BD_RX_EMPTY;
 | 
			
		||||
        bd->length += to_write;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (*size == etsec->rx_padding) {
 | 
			
		||||
        /* The remaining bytes are only for padding which is not actually
 | 
			
		||||
         * allocated in the data buffer.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding);
 | 
			
		||||
 | 
			
		||||
        if (rem > 0) {
 | 
			
		||||
            memset(padd, 0x0, sizeof(padd));
 | 
			
		||||
            etsec->rx_padding -= rem;
 | 
			
		||||
            *size             -= rem;
 | 
			
		||||
            bd->length        += rem;
 | 
			
		||||
            cpu_physical_memory_write(bufptr, padd, rem);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t fcb_size = 0;
 | 
			
		||||
    uint8_t  prsdep   = (etsec->regs[RCTRL].value >> RCTRL_PRSDEP_OFFSET)
 | 
			
		||||
        & RCTRL_PRSDEP_MASK;
 | 
			
		||||
 | 
			
		||||
    if (prsdep != 0) {
 | 
			
		||||
        /* Prepend FCB (FCB size + RCTRL[PAL]) */
 | 
			
		||||
        fcb_size = 8 + ((etsec->regs[RCTRL].value >> 16) & 0x1F);
 | 
			
		||||
 | 
			
		||||
        etsec->rx_fcb_size = fcb_size;
 | 
			
		||||
 | 
			
		||||
        /* TODO: fill_FCB(etsec); */
 | 
			
		||||
        memset(etsec->rx_fcb, 0x0, sizeof(etsec->rx_fcb));
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        etsec->rx_fcb_size = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (etsec->rx_buffer != NULL) {
 | 
			
		||||
        g_free(etsec->rx_buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Do not copy the frame for now */
 | 
			
		||||
    etsec->rx_buffer     = (uint8_t *)buf;
 | 
			
		||||
    etsec->rx_buffer_len = size;
 | 
			
		||||
 | 
			
		||||
    /* CRC padding (We don't have to compute the CRC) */
 | 
			
		||||
    etsec->rx_padding = 4;
 | 
			
		||||
 | 
			
		||||
    etsec->rx_first_in_frame = 1;
 | 
			
		||||
    etsec->rx_remaining_data = etsec->rx_buffer_len;
 | 
			
		||||
    RING_DEBUG("%s: rx_buffer_len:%u rx_padding+crc:%u\n", __func__,
 | 
			
		||||
               etsec->rx_buffer_len, etsec->rx_padding);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    int ring_nbr = 0;           /* Always use ring0 (no filer) */
 | 
			
		||||
 | 
			
		||||
    if (etsec->rx_buffer_len != 0) {
 | 
			
		||||
        RING_DEBUG("%s: We can't receive now,"
 | 
			
		||||
                   " a buffer is already in the pipe\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (etsec->regs[RSTAT].value & 1 << (23 - ring_nbr)) {
 | 
			
		||||
        RING_DEBUG("%s: The ring is halted\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (etsec->regs[DMACTRL].value & DMACTRL_GRS) {
 | 
			
		||||
        RING_DEBUG("%s: Graceful receive stop\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!(etsec->regs[MACCFG1].value & MACCFG1_RX_EN)) {
 | 
			
		||||
        RING_DEBUG("%s: MAC Receive not enabled\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
 | 
			
		||||
        /* CRC is not in the packet yet, so short frame is below 60 bytes */
 | 
			
		||||
        RING_DEBUG("%s: Drop short frame\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rx_init_frame(etsec, buf, size);
 | 
			
		||||
 | 
			
		||||
    etsec_walk_rx_ring(etsec, ring_nbr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
 | 
			
		||||
{
 | 
			
		||||
    hwaddr         ring_base     = 0;
 | 
			
		||||
    hwaddr         bd_addr       = 0;
 | 
			
		||||
    hwaddr         start_bd_addr = 0;
 | 
			
		||||
    eTSEC_rxtx_bd  bd;
 | 
			
		||||
    uint16_t       bd_flags;
 | 
			
		||||
    size_t         remaining_data;
 | 
			
		||||
    const uint8_t *buf;
 | 
			
		||||
    uint8_t       *tmp_buf;
 | 
			
		||||
    size_t         size;
 | 
			
		||||
 | 
			
		||||
    if (etsec->rx_buffer_len == 0) {
 | 
			
		||||
        /* No frame to send */
 | 
			
		||||
        RING_DEBUG("No frame to send\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    remaining_data = etsec->rx_remaining_data + etsec->rx_padding;
 | 
			
		||||
    buf            = etsec->rx_buffer
 | 
			
		||||
        + (etsec->rx_buffer_len - etsec->rx_remaining_data);
 | 
			
		||||
    size           = etsec->rx_buffer_len + etsec->rx_padding;
 | 
			
		||||
 | 
			
		||||
    ring_base = (hwaddr)(etsec->regs[RBASEH].value & 0xF) << 32;
 | 
			
		||||
    ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7;
 | 
			
		||||
    start_bd_addr  = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        read_buffer_descriptor(etsec, bd_addr, &bd);
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_BD
 | 
			
		||||
        print_bd(bd,
 | 
			
		||||
                 eTSEC_RECEIVE,
 | 
			
		||||
                 (bd_addr - ring_base) / sizeof(eTSEC_rxtx_bd));
 | 
			
		||||
 | 
			
		||||
#endif  /* DEBUG_BD */
 | 
			
		||||
 | 
			
		||||
        /* Save flags before BD update */
 | 
			
		||||
        bd_flags = bd.flags;
 | 
			
		||||
 | 
			
		||||
        if (bd_flags & BD_RX_EMPTY) {
 | 
			
		||||
            fill_rx_bd(etsec, &bd, &buf, &remaining_data);
 | 
			
		||||
 | 
			
		||||
            if (etsec->rx_first_in_frame) {
 | 
			
		||||
                bd.flags |= BD_RX_FIRST;
 | 
			
		||||
                etsec->rx_first_in_frame = 0;
 | 
			
		||||
                etsec->rx_first_bd = bd;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Last in frame */
 | 
			
		||||
            if (remaining_data == 0) {
 | 
			
		||||
 | 
			
		||||
                /* Clear flags */
 | 
			
		||||
 | 
			
		||||
                bd.flags &= ~0x7ff;
 | 
			
		||||
 | 
			
		||||
                bd.flags |= BD_LAST;
 | 
			
		||||
 | 
			
		||||
                /* NOTE: non-octet aligned frame is impossible in qemu */
 | 
			
		||||
 | 
			
		||||
                if (size >= etsec->regs[MAXFRM].value) {
 | 
			
		||||
                    /* frame length violation */
 | 
			
		||||
                    qemu_log("%s frame length violation: size:%zu MAXFRM:%d\n",
 | 
			
		||||
                           __func__, size, etsec->regs[MAXFRM].value);
 | 
			
		||||
 | 
			
		||||
                    bd.flags |= BD_RX_LG;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (size  < 64) {
 | 
			
		||||
                    /* Short frame */
 | 
			
		||||
                    bd.flags |= BD_RX_SH;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* TODO: Broadcast and Multicast */
 | 
			
		||||
 | 
			
		||||
                if (bd.flags | BD_INTERRUPT) {
 | 
			
		||||
                    /* Set RXFx */
 | 
			
		||||
                    etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
 | 
			
		||||
 | 
			
		||||
                    /* Set IEVENT */
 | 
			
		||||
                    ievent_set(etsec, IEVENT_RXF);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                if (bd.flags | BD_INTERRUPT) {
 | 
			
		||||
                    /* Set IEVENT */
 | 
			
		||||
                    ievent_set(etsec, IEVENT_RXB);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Write back BD after update */
 | 
			
		||||
            write_buffer_descriptor(etsec, bd_addr, &bd);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Wrap or next BD */
 | 
			
		||||
        if (bd_flags & BD_WRAP) {
 | 
			
		||||
            bd_addr = ring_base;
 | 
			
		||||
        } else {
 | 
			
		||||
            bd_addr += sizeof(eTSEC_rxtx_bd);
 | 
			
		||||
        }
 | 
			
		||||
    } while (remaining_data != 0
 | 
			
		||||
             && (bd_flags & BD_RX_EMPTY)
 | 
			
		||||
             && bd_addr != start_bd_addr);
 | 
			
		||||
 | 
			
		||||
    /* Reset ring ptr */
 | 
			
		||||
    etsec->regs[RBPTR0 + ring_nbr].value = bd_addr;
 | 
			
		||||
 | 
			
		||||
    /* The frame is too large to fit in the Rx ring */
 | 
			
		||||
    if (remaining_data > 0) {
 | 
			
		||||
 | 
			
		||||
        /* Set RSTAT[QHLTx] */
 | 
			
		||||
        etsec->regs[RSTAT].value |= 1 << (23 - ring_nbr);
 | 
			
		||||
 | 
			
		||||
        /* Save remaining data to send the end of the frame when the ring will
 | 
			
		||||
         * be restarted
 | 
			
		||||
         */
 | 
			
		||||
        etsec->rx_remaining_data = remaining_data;
 | 
			
		||||
 | 
			
		||||
        /* Copy the frame */
 | 
			
		||||
        tmp_buf = g_malloc(size);
 | 
			
		||||
        memcpy(tmp_buf, etsec->rx_buffer, size);
 | 
			
		||||
        etsec->rx_buffer = tmp_buf;
 | 
			
		||||
 | 
			
		||||
        RING_DEBUG("no empty RxBD available any more\n");
 | 
			
		||||
    } else {
 | 
			
		||||
        etsec->rx_buffer_len = 0;
 | 
			
		||||
        etsec->rx_buffer     = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RING_DEBUG("eTSEC End of ring_write: remaining_data:%zu\n", remaining_data);
 | 
			
		||||
}
 | 
			
		||||
@@ -405,6 +405,8 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
 | 
			
		||||
 | 
			
		||||
    dev->rx_bufs++;
 | 
			
		||||
 | 
			
		||||
    qemu_flush_queued_packets(qemu_get_queue(dev->nic));
 | 
			
		||||
 | 
			
		||||
    DPRINTF("h_add_logical_lan_buffer():  Added buf  ptr=%d  rx_bufs=%d"
 | 
			
		||||
            " bd=0x%016llx\n", dev->add_buf_ptr, dev->rx_bufs,
 | 
			
		||||
            (unsigned long long)buf);
 | 
			
		||||
 
 | 
			
		||||
@@ -397,12 +397,15 @@ static int peer_detach(VirtIONet *n, int index)
 | 
			
		||||
static void virtio_net_set_queues(VirtIONet *n)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < n->max_queues; i++) {
 | 
			
		||||
        if (i < n->curr_queues) {
 | 
			
		||||
            assert(!peer_attach(n, i));
 | 
			
		||||
            r = peer_attach(n, i);
 | 
			
		||||
            assert(!r);
 | 
			
		||||
        } else {
 | 
			
		||||
            assert(!peer_detach(n, i));
 | 
			
		||||
            r = peer_detach(n, i);
 | 
			
		||||
            assert(!r);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ void init_pam(DeviceState *dev, MemoryRegion *ram_memory,
 | 
			
		||||
    /* XXX: should distinguish read/write cases */
 | 
			
		||||
    memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space,
 | 
			
		||||
                             start, size);
 | 
			
		||||
    memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", pci_address_space,
 | 
			
		||||
    memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", ram_memory,
 | 
			
		||||
                             start, size);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 4; ++i) {
 | 
			
		||||
 
 | 
			
		||||
@@ -272,7 +272,7 @@ static void mch_update_smram(MCHPCIState *mch)
 | 
			
		||||
    PCIDevice *pd = PCI_DEVICE(mch);
 | 
			
		||||
 | 
			
		||||
    memory_region_transaction_begin();
 | 
			
		||||
    smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM],
 | 
			
		||||
    smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM],
 | 
			
		||||
                    mch->smm_enabled);
 | 
			
		||||
    memory_region_transaction_commit();
 | 
			
		||||
}
 | 
			
		||||
@@ -283,7 +283,7 @@ static void mch_set_smm(int smm, void *arg)
 | 
			
		||||
    PCIDevice *pd = PCI_DEVICE(mch);
 | 
			
		||||
 | 
			
		||||
    memory_region_transaction_begin();
 | 
			
		||||
    smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM],
 | 
			
		||||
    smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM],
 | 
			
		||||
                    &mch->smram_region);
 | 
			
		||||
    memory_region_transaction_commit();
 | 
			
		||||
}
 | 
			
		||||
@@ -306,8 +306,8 @@ static void mch_write_config(PCIDevice *d,
 | 
			
		||||
        mch_update_pciexbar(mch);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM,
 | 
			
		||||
                       MCH_HOST_BRDIGE_SMRAM_SIZE)) {
 | 
			
		||||
    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM,
 | 
			
		||||
                       MCH_HOST_BRIDGE_SMRAM_SIZE)) {
 | 
			
		||||
        mch_update_smram(mch);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -347,7 +347,7 @@ static void mch_reset(DeviceState *qdev)
 | 
			
		||||
    pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
 | 
			
		||||
                 MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
 | 
			
		||||
    d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
 | 
			
		||||
 | 
			
		||||
    mch_update(mch);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -221,29 +221,23 @@ static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
 | 
			
		||||
                                         DeviceState *dev,
 | 
			
		||||
                                         uint8_t **exp_cap, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    PCIDevice *pci_dev = PCI_DEVICE(dev);
 | 
			
		||||
    *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
 | 
			
		||||
    uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
 | 
			
		||||
 | 
			
		||||
    PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
 | 
			
		||||
    PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: %d\n", state);
 | 
			
		||||
    if (sltsta & PCI_EXP_SLTSTA_EIS) {
 | 
			
		||||
        /* the slot is electromechanically locked.
 | 
			
		||||
         * This error is propagated up to qdev and then to HMP/QMP.
 | 
			
		||||
         */
 | 
			
		||||
        error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* TODO: multifunction hot-plug.
 | 
			
		||||
     * Right now, only a device of function = 0 is allowed to be
 | 
			
		||||
     * hot plugged/unplugged.
 | 
			
		||||
     */
 | 
			
		||||
    assert(PCI_FUNC(pci_dev->devfn) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
 | 
			
		||||
                              Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *exp_cap;
 | 
			
		||||
    PCIDevice *pci_dev = PCI_DEVICE(dev);
 | 
			
		||||
 | 
			
		||||
    pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
 | 
			
		||||
 | 
			
		||||
@@ -256,6 +250,12 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* TODO: multifunction hot-plug.
 | 
			
		||||
     * Right now, only a device of function = 0 is allowed to be
 | 
			
		||||
     * hot plugged/unplugged.
 | 
			
		||||
     */
 | 
			
		||||
    assert(PCI_FUNC(pci_dev->devfn) == 0);
 | 
			
		||||
 | 
			
		||||
    pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
 | 
			
		||||
                               PCI_EXP_SLTSTA_PDS);
 | 
			
		||||
    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
 | 
			
		||||
 
 | 
			
		||||
@@ -238,6 +238,7 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
 | 
			
		||||
       the first node as boot node and be happy */
 | 
			
		||||
    for (i = smp_cpus - 1; i >= 0; i--) {
 | 
			
		||||
        CPUState *cpu;
 | 
			
		||||
        PowerPCCPU *pcpu;
 | 
			
		||||
        char cpu_name[128];
 | 
			
		||||
        uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
 | 
			
		||||
 | 
			
		||||
@@ -246,14 +247,16 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        env = cpu->env_ptr;
 | 
			
		||||
        pcpu = POWERPC_CPU(cpu);
 | 
			
		||||
 | 
			
		||||
        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
 | 
			
		||||
                 cpu->cpu_index);
 | 
			
		||||
                 ppc_get_vcpu_dt_id(pcpu));
 | 
			
		||||
        qemu_fdt_add_subnode(fdt, cpu_name);
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
 | 
			
		||||
        qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
 | 
			
		||||
                              ppc_get_vcpu_dt_id(pcpu));
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
 | 
			
		||||
                              env->dcache_line_size);
 | 
			
		||||
        qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								hw/ppc/ppc.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								hw/ppc/ppc.c
									
									
									
									
									
								
							@@ -26,6 +26,7 @@
 | 
			
		||||
#include "hw/ppc/ppc_e500.h"
 | 
			
		||||
#include "qemu/timer.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "sysemu/cpus.h"
 | 
			
		||||
#include "hw/timer/m48t59.h"
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
#include "hw/loader.h"
 | 
			
		||||
@@ -1362,3 +1363,24 @@ int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* CPU device-tree ID helpers */
 | 
			
		||||
int ppc_get_vcpu_dt_id(PowerPCCPU *cpu)
 | 
			
		||||
{
 | 
			
		||||
    return cpu->cpu_dt_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cs;
 | 
			
		||||
 | 
			
		||||
    CPU_FOREACH(cs) {
 | 
			
		||||
        PowerPCCPU *cpu = POWERPC_CPU(cs);
 | 
			
		||||
 | 
			
		||||
        if (cpu->cpu_dt_id == cpu_dt_id) {
 | 
			
		||||
            return cpu;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "hw/usb.h"
 | 
			
		||||
#include "qemu/config-file.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
@@ -206,19 +207,20 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
 | 
			
		||||
 | 
			
		||||
    CPU_FOREACH(cpu) {
 | 
			
		||||
        DeviceClass *dc = DEVICE_GET_CLASS(cpu);
 | 
			
		||||
        int index = ppc_get_vcpu_dt_id(POWERPC_CPU(cpu));
 | 
			
		||||
        uint32_t associativity[] = {cpu_to_be32(0x5),
 | 
			
		||||
                                    cpu_to_be32(0x0),
 | 
			
		||||
                                    cpu_to_be32(0x0),
 | 
			
		||||
                                    cpu_to_be32(0x0),
 | 
			
		||||
                                    cpu_to_be32(cpu->numa_node),
 | 
			
		||||
                                    cpu_to_be32(cpu->cpu_index)};
 | 
			
		||||
                                    cpu_to_be32(index)};
 | 
			
		||||
 | 
			
		||||
        if ((cpu->cpu_index % smt) != 0) {
 | 
			
		||||
        if ((index % smt) != 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        snprintf(cpu_model, 32, "/cpus/%s@%x", dc->fw_name,
 | 
			
		||||
                 cpu->cpu_index);
 | 
			
		||||
                 index);
 | 
			
		||||
 | 
			
		||||
        offset = fdt_path_offset(fdt, cpu_model);
 | 
			
		||||
        if (offset < 0) {
 | 
			
		||||
@@ -367,7 +369,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
 | 
			
		||||
        CPUPPCState *env = &cpu->env;
 | 
			
		||||
        DeviceClass *dc = DEVICE_GET_CLASS(cs);
 | 
			
		||||
        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
 | 
			
		||||
        int index = cs->cpu_index;
 | 
			
		||||
        int index = ppc_get_vcpu_dt_id(cpu);
 | 
			
		||||
        uint32_t servers_prop[smp_threads];
 | 
			
		||||
        uint32_t gservers_prop[smp_threads * 2];
 | 
			
		||||
        char *nodename;
 | 
			
		||||
@@ -685,6 +687,7 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
 | 
			
		||||
    if (shift > 0) {
 | 
			
		||||
        /* Kernel handles htab, we don't need to allocate one */
 | 
			
		||||
        spapr->htab_shift = shift;
 | 
			
		||||
        kvmppc_kern_htab = true;
 | 
			
		||||
    } else {
 | 
			
		||||
        if (!spapr->htab) {
 | 
			
		||||
            /* Allocate an htab if we don't yet have one */
 | 
			
		||||
@@ -740,8 +743,21 @@ static void spapr_cpu_reset(void *opaque)
 | 
			
		||||
    env->spr[SPR_HIOR] = 0;
 | 
			
		||||
 | 
			
		||||
    env->external_htab = (uint8_t *)spapr->htab;
 | 
			
		||||
    if (kvm_enabled() && !env->external_htab) {
 | 
			
		||||
        /*
 | 
			
		||||
         * HV KVM, set external_htab to 1 so our ppc_hash64_load_hpte*
 | 
			
		||||
         * functions do the right thing.
 | 
			
		||||
         */
 | 
			
		||||
        env->external_htab = (void *)1;
 | 
			
		||||
    }
 | 
			
		||||
    env->htab_base = -1;
 | 
			
		||||
    env->htab_mask = HTAB_SIZE(spapr) - 1;
 | 
			
		||||
    /*
 | 
			
		||||
     * htab_mask is the mask used to normalize hash value to PTEG index.
 | 
			
		||||
     * htab_shift is log2 of hash table size.
 | 
			
		||||
     * We have 8 hpte per group, and each hpte is 16 bytes.
 | 
			
		||||
     * ie have 128 bytes per hpte entry.
 | 
			
		||||
     */
 | 
			
		||||
    env->htab_mask = (1ULL << ((spapr)->htab_shift - 7)) - 1;
 | 
			
		||||
    env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
 | 
			
		||||
        (spapr->htab_shift - 18);
 | 
			
		||||
}
 | 
			
		||||
@@ -1305,20 +1321,15 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
 | 
			
		||||
 | 
			
		||||
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
			
		||||
                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
 | 
			
		||||
        if (kernel_size < 0) {
 | 
			
		||||
        if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
 | 
			
		||||
            kernel_size = load_elf(kernel_filename,
 | 
			
		||||
                                   translate_kernel_address, NULL,
 | 
			
		||||
                                   NULL, &lowaddr, NULL, 0, ELF_MACHINE, 0);
 | 
			
		||||
            kernel_le = kernel_size > 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (kernel_size < 0) {
 | 
			
		||||
            kernel_size = load_image_targphys(kernel_filename,
 | 
			
		||||
                                              KERNEL_LOAD_ADDR,
 | 
			
		||||
                                              load_limit - KERNEL_LOAD_ADDR);
 | 
			
		||||
        }
 | 
			
		||||
        if (kernel_size < 0) {
 | 
			
		||||
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
			
		||||
                    kernel_filename);
 | 
			
		||||
            fprintf(stderr, "qemu: error loading %s: %s\n",
 | 
			
		||||
                    kernel_filename, load_elf_strerror(kernel_size));
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1366,6 +1377,24 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
 | 
			
		||||
    assert(spapr->fdt_skel != NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int spapr_kvm_type(const char *vm_type)
 | 
			
		||||
{
 | 
			
		||||
    if (!vm_type) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!strcmp(vm_type, "HV")) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!strcmp(vm_type, "PR")) {
 | 
			
		||||
        return 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_report("Unknown kvm-type specified '%s'", vm_type);
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QEMUMachine spapr_machine = {
 | 
			
		||||
    .name = "pseries",
 | 
			
		||||
    .desc = "pSeries Logical Partition (PAPR compliant)",
 | 
			
		||||
@@ -1376,6 +1405,7 @@ static QEMUMachine spapr_machine = {
 | 
			
		||||
    .max_cpus = MAX_CPUS,
 | 
			
		||||
    .no_parallel = 1,
 | 
			
		||||
    .default_boot_order = NULL,
 | 
			
		||||
    .kvm_type = spapr_kvm_type,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void spapr_machine_init(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,17 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
 | 
			
		||||
    return rb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * hash value/pteg group index is normalized by htab_mask
 | 
			
		||||
     */
 | 
			
		||||
    if (((pte_index & ~7ULL) / HPTES_PER_GROUP) & ~env->htab_mask) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
                            target_ulong opcode, target_ulong *args)
 | 
			
		||||
{
 | 
			
		||||
@@ -50,8 +61,8 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    target_ulong ptel = args[3];
 | 
			
		||||
    target_ulong page_shift = 12;
 | 
			
		||||
    target_ulong raddr;
 | 
			
		||||
    target_ulong i;
 | 
			
		||||
    hwaddr hpte;
 | 
			
		||||
    target_ulong index;
 | 
			
		||||
    uint64_t token;
 | 
			
		||||
 | 
			
		||||
    /* only handle 4k and 16M pages for now */
 | 
			
		||||
    if (pteh & HPTE64_V_LARGE) {
 | 
			
		||||
@@ -91,33 +102,37 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
 | 
			
		||||
    pteh &= ~0x60ULL;
 | 
			
		||||
 | 
			
		||||
    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
 | 
			
		||||
    if (!valid_pte_index(env, pte_index)) {
 | 
			
		||||
        return H_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    index = 0;
 | 
			
		||||
    if (likely((flags & H_EXACT) == 0)) {
 | 
			
		||||
        pte_index &= ~7ULL;
 | 
			
		||||
        hpte = pte_index * HASH_PTE_SIZE_64;
 | 
			
		||||
        for (i = 0; ; ++i) {
 | 
			
		||||
            if (i == 8) {
 | 
			
		||||
        token = ppc_hash64_start_access(cpu, pte_index);
 | 
			
		||||
        do {
 | 
			
		||||
            if (index == 8) {
 | 
			
		||||
                ppc_hash64_stop_access(token);
 | 
			
		||||
                return H_PTEG_FULL;
 | 
			
		||||
            }
 | 
			
		||||
            if ((ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) == 0) {
 | 
			
		||||
            if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            hpte += HASH_PTE_SIZE_64;
 | 
			
		||||
        }
 | 
			
		||||
        } while (index++);
 | 
			
		||||
        ppc_hash64_stop_access(token);
 | 
			
		||||
    } else {
 | 
			
		||||
        i = 0;
 | 
			
		||||
        hpte = pte_index * HASH_PTE_SIZE_64;
 | 
			
		||||
        if (ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) {
 | 
			
		||||
        token = ppc_hash64_start_access(cpu, pte_index);
 | 
			
		||||
        if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) {
 | 
			
		||||
            ppc_hash64_stop_access(token);
 | 
			
		||||
            return H_PTEG_FULL;
 | 
			
		||||
        }
 | 
			
		||||
        ppc_hash64_stop_access(token);
 | 
			
		||||
    }
 | 
			
		||||
    ppc_hash64_store_hpte1(env, hpte, ptel);
 | 
			
		||||
    /* eieio();  FIXME: need some sort of barrier for smp? */
 | 
			
		||||
    ppc_hash64_store_hpte0(env, hpte, pteh | HPTE64_V_HPTE_DIRTY);
 | 
			
		||||
 | 
			
		||||
    args[0] = pte_index + i;
 | 
			
		||||
    ppc_hash64_store_hpte(env, pte_index + index,
 | 
			
		||||
                          pteh | HPTE64_V_HPTE_DIRTY, ptel);
 | 
			
		||||
 | 
			
		||||
    args[0] = pte_index + index;
 | 
			
		||||
    return H_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -133,17 +148,17 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
 | 
			
		||||
                                target_ulong flags,
 | 
			
		||||
                                target_ulong *vp, target_ulong *rp)
 | 
			
		||||
{
 | 
			
		||||
    hwaddr hpte;
 | 
			
		||||
    uint64_t token;
 | 
			
		||||
    target_ulong v, r, rb;
 | 
			
		||||
 | 
			
		||||
    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
 | 
			
		||||
    if (!valid_pte_index(env, ptex)) {
 | 
			
		||||
        return REMOVE_PARM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hpte = ptex * HASH_PTE_SIZE_64;
 | 
			
		||||
 | 
			
		||||
    v = ppc_hash64_load_hpte0(env, hpte);
 | 
			
		||||
    r = ppc_hash64_load_hpte1(env, hpte);
 | 
			
		||||
    token = ppc_hash64_start_access(ppc_env_get_cpu(env), ptex);
 | 
			
		||||
    v = ppc_hash64_load_hpte0(env, token, 0);
 | 
			
		||||
    r = ppc_hash64_load_hpte1(env, token, 0);
 | 
			
		||||
    ppc_hash64_stop_access(token);
 | 
			
		||||
 | 
			
		||||
    if ((v & HPTE64_V_VALID) == 0 ||
 | 
			
		||||
        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
 | 
			
		||||
@@ -152,7 +167,7 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
 | 
			
		||||
    }
 | 
			
		||||
    *vp = v;
 | 
			
		||||
    *rp = r;
 | 
			
		||||
    ppc_hash64_store_hpte0(env, hpte, HPTE64_V_HPTE_DIRTY);
 | 
			
		||||
    ppc_hash64_store_hpte(env, ptex, HPTE64_V_HPTE_DIRTY, 0);
 | 
			
		||||
    rb = compute_tlbie_rb(v, r, ptex);
 | 
			
		||||
    ppc_tlb_invalidate_one(env, rb);
 | 
			
		||||
    return REMOVE_SUCCESS;
 | 
			
		||||
@@ -259,17 +274,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    target_ulong flags = args[0];
 | 
			
		||||
    target_ulong pte_index = args[1];
 | 
			
		||||
    target_ulong avpn = args[2];
 | 
			
		||||
    hwaddr hpte;
 | 
			
		||||
    uint64_t token;
 | 
			
		||||
    target_ulong v, r, rb;
 | 
			
		||||
 | 
			
		||||
    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
 | 
			
		||||
    if (!valid_pte_index(env, pte_index)) {
 | 
			
		||||
        return H_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hpte = pte_index * HASH_PTE_SIZE_64;
 | 
			
		||||
 | 
			
		||||
    v = ppc_hash64_load_hpte0(env, hpte);
 | 
			
		||||
    r = ppc_hash64_load_hpte1(env, hpte);
 | 
			
		||||
    token = ppc_hash64_start_access(cpu, pte_index);
 | 
			
		||||
    v = ppc_hash64_load_hpte0(env, token, 0);
 | 
			
		||||
    r = ppc_hash64_load_hpte1(env, token, 0);
 | 
			
		||||
    ppc_hash64_stop_access(token);
 | 
			
		||||
 | 
			
		||||
    if ((v & HPTE64_V_VALID) == 0 ||
 | 
			
		||||
        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
 | 
			
		||||
@@ -282,11 +297,11 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    r |= (flags << 48) & HPTE64_R_KEY_HI;
 | 
			
		||||
    r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
 | 
			
		||||
    rb = compute_tlbie_rb(v, r, pte_index);
 | 
			
		||||
    ppc_hash64_store_hpte0(env, hpte, (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY);
 | 
			
		||||
    ppc_hash64_store_hpte(env, pte_index,
 | 
			
		||||
                          (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
 | 
			
		||||
    ppc_tlb_invalidate_one(env, rb);
 | 
			
		||||
    ppc_hash64_store_hpte1(env, hpte, r);
 | 
			
		||||
    /* Don't need a memory barrier, due to qemu's global lock */
 | 
			
		||||
    ppc_hash64_store_hpte0(env, hpte, v | HPTE64_V_HPTE_DIRTY);
 | 
			
		||||
    ppc_hash64_store_hpte(env, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
 | 
			
		||||
    return H_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -299,7 +314,7 @@ static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    uint8_t *hpte;
 | 
			
		||||
    int i, ridx, n_entries = 1;
 | 
			
		||||
 | 
			
		||||
    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
 | 
			
		||||
    if (!valid_pte_index(env, pte_index)) {
 | 
			
		||||
        return H_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -467,13 +482,13 @@ static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    target_ulong vpa = args[2];
 | 
			
		||||
    target_ulong ret = H_PARAMETER;
 | 
			
		||||
    CPUPPCState *tenv;
 | 
			
		||||
    CPUState *tcpu;
 | 
			
		||||
    PowerPCCPU *tcpu;
 | 
			
		||||
 | 
			
		||||
    tcpu = qemu_get_cpu(procno);
 | 
			
		||||
    tcpu = ppc_get_vcpu_by_dt_id(procno);
 | 
			
		||||
    if (!tcpu) {
 | 
			
		||||
        return H_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    tenv = tcpu->env_ptr;
 | 
			
		||||
    tenv = &tcpu->env;
 | 
			
		||||
 | 
			
		||||
    switch (flags) {
 | 
			
		||||
    case FLAGS_REGISTER_VPA:
 | 
			
		||||
 
 | 
			
		||||
@@ -243,6 +243,42 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static target_ulong get_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
 | 
			
		||||
                                target_ulong *tce)
 | 
			
		||||
{
 | 
			
		||||
    if (ioba >= tcet->window_size) {
 | 
			
		||||
        hcall_dprintf("spapr_iommu_get_tce on out-of-bounds IOBA 0x"
 | 
			
		||||
                      TARGET_FMT_lx "\n", ioba);
 | 
			
		||||
        return H_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *tce = tcet->table[ioba >> SPAPR_TCE_PAGE_SHIFT];
 | 
			
		||||
 | 
			
		||||
    return H_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static target_ulong h_get_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 | 
			
		||||
                              target_ulong opcode, target_ulong *args)
 | 
			
		||||
{
 | 
			
		||||
    target_ulong liobn = args[0];
 | 
			
		||||
    target_ulong ioba = args[1];
 | 
			
		||||
    target_ulong tce = 0;
 | 
			
		||||
    target_ulong ret = H_PARAMETER;
 | 
			
		||||
    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
 | 
			
		||||
 | 
			
		||||
    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
 | 
			
		||||
 | 
			
		||||
    if (tcet) {
 | 
			
		||||
        ret = get_tce_emu(tcet, ioba, &tce);
 | 
			
		||||
        if (!ret) {
 | 
			
		||||
            args[0] = tce;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    trace_spapr_iommu_get(liobn, ioba, ret, tce);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
 | 
			
		||||
                 uint32_t liobn, uint64_t window, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
@@ -295,6 +331,7 @@ static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
 | 
			
		||||
    /* hcall-tce */
 | 
			
		||||
    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
 | 
			
		||||
    spapr_register_hypercall(H_GET_TCE, h_get_tce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static TypeInfo spapr_tce_table_info = {
 | 
			
		||||
 
 | 
			
		||||
@@ -469,6 +469,8 @@ static const MemoryRegionOps spapr_msi_ops = {
 | 
			
		||||
 | 
			
		||||
void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t window_size = 4096;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
 | 
			
		||||
     * we need to allocate some memory to catch those writes coming
 | 
			
		||||
@@ -476,10 +478,19 @@ void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr)
 | 
			
		||||
     * As MSIMessage:addr is going to be the same and MSIMessage:data
 | 
			
		||||
     * is going to be a VIRQ number, 4 bytes of the MSI MR will only
 | 
			
		||||
     * be used.
 | 
			
		||||
     *
 | 
			
		||||
     * For KVM we want to ensure that this memory is a full page so that
 | 
			
		||||
     * our memory slot is of page size granularity.
 | 
			
		||||
     */
 | 
			
		||||
#ifdef CONFIG_KVM
 | 
			
		||||
    if (kvm_enabled()) {
 | 
			
		||||
        window_size = getpagesize();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    spapr->msi_win_addr = addr;
 | 
			
		||||
    memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr,
 | 
			
		||||
                          "msi", getpagesize());
 | 
			
		||||
                          "msi", window_size);
 | 
			
		||||
    memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr,
 | 
			
		||||
                                &spapr->msiwindow);
 | 
			
		||||
}
 | 
			
		||||
@@ -728,6 +739,8 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
    dc->props = spapr_phb_properties;
 | 
			
		||||
    dc->reset = spapr_phb_reset;
 | 
			
		||||
    dc->vmsd = &vmstate_spapr_pci;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 | 
			
		||||
    dc->cannot_instantiate_with_device_add_yet = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo spapr_phb_info = {
 | 
			
		||||
 
 | 
			
		||||
@@ -131,7 +131,7 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
 | 
			
		||||
                                         uint32_t nret, target_ulong rets)
 | 
			
		||||
{
 | 
			
		||||
    target_ulong id;
 | 
			
		||||
    CPUState *cpu;
 | 
			
		||||
    PowerPCCPU *cpu;
 | 
			
		||||
 | 
			
		||||
    if (nargs != 1 || nret != 2) {
 | 
			
		||||
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 | 
			
		||||
@@ -139,9 +139,9 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    id = rtas_ld(args, 0);
 | 
			
		||||
    cpu = qemu_get_cpu(id);
 | 
			
		||||
    cpu = ppc_get_vcpu_by_dt_id(id);
 | 
			
		||||
    if (cpu != NULL) {
 | 
			
		||||
        if (cpu->halted) {
 | 
			
		||||
        if (CPU(cpu)->halted) {
 | 
			
		||||
            rtas_st(rets, 1, 0);
 | 
			
		||||
        } else {
 | 
			
		||||
            rtas_st(rets, 1, 2);
 | 
			
		||||
@@ -161,7 +161,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
 | 
			
		||||
                           uint32_t nret, target_ulong rets)
 | 
			
		||||
{
 | 
			
		||||
    target_ulong id, start, r3;
 | 
			
		||||
    CPUState *cs;
 | 
			
		||||
    PowerPCCPU *cpu;
 | 
			
		||||
 | 
			
		||||
    if (nargs != 3 || nret != 1) {
 | 
			
		||||
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 | 
			
		||||
@@ -172,9 +172,9 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
 | 
			
		||||
    start = rtas_ld(args, 1);
 | 
			
		||||
    r3 = rtas_ld(args, 2);
 | 
			
		||||
 | 
			
		||||
    cs = qemu_get_cpu(id);
 | 
			
		||||
    if (cs != NULL) {
 | 
			
		||||
        PowerPCCPU *cpu = POWERPC_CPU(cs);
 | 
			
		||||
    cpu = ppc_get_vcpu_by_dt_id(id);
 | 
			
		||||
    if (cpu != NULL) {
 | 
			
		||||
        CPUState *cs = CPU(cpu);
 | 
			
		||||
        CPUPPCState *env = &cpu->env;
 | 
			
		||||
 | 
			
		||||
        if (!cs->halted) {
 | 
			
		||||
 
 | 
			
		||||
@@ -174,6 +174,19 @@ static int xilinx_load_device_tree(hwaddr addr,
 | 
			
		||||
    if (!fdt) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
 | 
			
		||||
                              initrd_base);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        error_report("couldn't set /chosen/linux,initrd-start");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
 | 
			
		||||
                              (initrd_base + initrd_size));
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        error_report("couldn't set /chosen/linux,initrd-end");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
 | 
			
		||||
    if (r < 0)
 | 
			
		||||
        fprintf(stderr, "couldn't set /chosen/bootargs\n");
 | 
			
		||||
@@ -187,6 +200,8 @@ static void virtex_init(QEMUMachineInitArgs *args)
 | 
			
		||||
    const char *cpu_model = args->cpu_model;
 | 
			
		||||
    const char *kernel_filename = args->kernel_filename;
 | 
			
		||||
    const char *kernel_cmdline = args->kernel_cmdline;
 | 
			
		||||
    hwaddr initrd_base = 0;
 | 
			
		||||
    int initrd_size = 0;
 | 
			
		||||
    MemoryRegion *address_space_mem = get_system_memory();
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
    PowerPCCPU *cpu;
 | 
			
		||||
@@ -259,10 +274,27 @@ static void virtex_init(QEMUMachineInitArgs *args)
 | 
			
		||||
 | 
			
		||||
        boot_info.ima_size = kernel_size;
 | 
			
		||||
 | 
			
		||||
        /* Load initrd. */
 | 
			
		||||
        if (args->initrd_filename) {
 | 
			
		||||
            initrd_base = high = ROUND_UP(high, 4);
 | 
			
		||||
            initrd_size = load_image_targphys(args->initrd_filename,
 | 
			
		||||
                                              high, ram_size - high);
 | 
			
		||||
 | 
			
		||||
            if (initrd_size < 0) {
 | 
			
		||||
                error_report("couldn't load ram disk '%s'",
 | 
			
		||||
                             args->initrd_filename);
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
            high = ROUND_UP(high + initrd_size, 4);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Provide a device-tree.  */
 | 
			
		||||
        boot_info.fdt = high + (8192 * 2);
 | 
			
		||||
        boot_info.fdt &= ~8191;
 | 
			
		||||
        xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
 | 
			
		||||
 | 
			
		||||
        xilinx_load_device_tree(boot_info.fdt, ram_size,
 | 
			
		||||
                                initrd_base, initrd_size,
 | 
			
		||||
                                kernel_cmdline);
 | 
			
		||||
    }
 | 
			
		||||
    env->load_info = &boot_info;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,15 @@ void css_conditional_io_interrupt(SubchDev *sch)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void css_adapter_interrupt(uint8_t isc)
 | 
			
		||||
{
 | 
			
		||||
    S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
    uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
 | 
			
		||||
 | 
			
		||||
    trace_css_adapter_interrupt(isc);
 | 
			
		||||
    s390_io_interrupt(cpu, 0, 0, 0, io_int_word);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sch_handle_clear_func(SubchDev *sch)
 | 
			
		||||
{
 | 
			
		||||
    PMCW *p = &sch->curr_status.pmcw;
 | 
			
		||||
@@ -1259,6 +1268,7 @@ void css_reset_sch(SubchDev *sch)
 | 
			
		||||
    sch->channel_prog = 0x0;
 | 
			
		||||
    sch->last_cmd_valid = false;
 | 
			
		||||
    sch->orb = NULL;
 | 
			
		||||
    sch->thinint_active = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void css_reset(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,7 @@ struct SubchDev {
 | 
			
		||||
    CCW1 last_cmd;
 | 
			
		||||
    bool last_cmd_valid;
 | 
			
		||||
    ORB *orb;
 | 
			
		||||
    bool thinint_active;
 | 
			
		||||
    /* transport-provided data: */
 | 
			
		||||
    int (*ccw_cb) (SubchDev *, CCW1);
 | 
			
		||||
    SenseId id;
 | 
			
		||||
@@ -97,4 +98,5 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
 | 
			
		||||
void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
 | 
			
		||||
                           int hotplugged, int add);
 | 
			
		||||
void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 | 
			
		||||
void css_adapter_interrupt(uint8_t isc);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -98,10 +98,10 @@ static int s390_ipl_init(SysBusDevice *dev)
 | 
			
		||||
        uint64_t pentry = KERN_IMAGE_START;
 | 
			
		||||
        kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
 | 
			
		||||
                               NULL, 1, ELF_MACHINE, 0);
 | 
			
		||||
        if (kernel_size == -1) {
 | 
			
		||||
        if (kernel_size < 0) {
 | 
			
		||||
            kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
 | 
			
		||||
        }
 | 
			
		||||
        if (kernel_size == -1) {
 | 
			
		||||
        if (kernel_size < 0) {
 | 
			
		||||
            fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * virtio ccw target implementation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2012 IBM Corp.
 | 
			
		||||
 * Copyright 2012,2014 IBM Corp.
 | 
			
		||||
 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
@@ -188,6 +188,13 @@ typedef struct VirtioFeatDesc {
 | 
			
		||||
    uint8_t index;
 | 
			
		||||
} QEMU_PACKED VirtioFeatDesc;
 | 
			
		||||
 | 
			
		||||
typedef struct VirtioThinintInfo {
 | 
			
		||||
    hwaddr summary_indicator;
 | 
			
		||||
    hwaddr device_indicator;
 | 
			
		||||
    uint64_t ind_bit;
 | 
			
		||||
    uint8_t isc;
 | 
			
		||||
} QEMU_PACKED VirtioThinintInfo;
 | 
			
		||||
 | 
			
		||||
/* Specify where the virtqueues for the subchannel are in guest memory. */
 | 
			
		||||
static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
 | 
			
		||||
                              uint16_t index, uint16_t num)
 | 
			
		||||
@@ -237,6 +244,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
 | 
			
		||||
    bool check_len;
 | 
			
		||||
    int len;
 | 
			
		||||
    hwaddr hw_len;
 | 
			
		||||
    VirtioThinintInfo *thinint;
 | 
			
		||||
 | 
			
		||||
    if (!dev) {
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
@@ -428,6 +436,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
 | 
			
		||||
            ret = -EINVAL;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (sch->thinint_active) {
 | 
			
		||||
            /* Trigger a command reject. */
 | 
			
		||||
            ret = -ENOSYS;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (!ccw.cda) {
 | 
			
		||||
            ret = -EFAULT;
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -480,6 +493,42 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
 | 
			
		||||
            ret = 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case CCW_CMD_SET_IND_ADAPTER:
 | 
			
		||||
        if (check_len) {
 | 
			
		||||
            if (ccw.count != sizeof(*thinint)) {
 | 
			
		||||
                ret = -EINVAL;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (ccw.count < sizeof(*thinint)) {
 | 
			
		||||
            /* Can't execute command. */
 | 
			
		||||
            ret = -EINVAL;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        len = sizeof(*thinint);
 | 
			
		||||
        hw_len = len;
 | 
			
		||||
        if (!ccw.cda) {
 | 
			
		||||
            ret = -EFAULT;
 | 
			
		||||
        } else if (dev->indicators && !sch->thinint_active) {
 | 
			
		||||
            /* Trigger a command reject. */
 | 
			
		||||
            ret = -ENOSYS;
 | 
			
		||||
        } else {
 | 
			
		||||
            thinint = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
 | 
			
		||||
            if (!thinint) {
 | 
			
		||||
                ret = -EFAULT;
 | 
			
		||||
            } else {
 | 
			
		||||
                len = hw_len;
 | 
			
		||||
                dev->summary_indicator = thinint->summary_indicator;
 | 
			
		||||
                dev->indicators = thinint->device_indicator;
 | 
			
		||||
                dev->thinint_isc = thinint->isc;
 | 
			
		||||
                dev->ind_bit = thinint->ind_bit;
 | 
			
		||||
                cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
 | 
			
		||||
                sch->thinint_active = ((dev->indicators != 0) &&
 | 
			
		||||
                                       (dev->summary_indicator != 0));
 | 
			
		||||
                sch->curr_status.scsw.count = ccw.count - len;
 | 
			
		||||
                ret = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        ret = -ENOSYS;
 | 
			
		||||
        break;
 | 
			
		||||
@@ -511,6 +560,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
 | 
			
		||||
    sch->channel_prog = 0x0;
 | 
			
		||||
    sch->last_cmd_valid = false;
 | 
			
		||||
    sch->orb = NULL;
 | 
			
		||||
    sch->thinint_active = false;
 | 
			
		||||
    /*
 | 
			
		||||
     * Use a device number if provided. Otherwise, fall back to subchannel
 | 
			
		||||
     * number.
 | 
			
		||||
@@ -858,6 +908,28 @@ static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
 | 
			
		||||
    return container_of(d, VirtioCcwDevice, parent_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
 | 
			
		||||
                                     uint8_t to_be_set)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t ind_old, ind_new;
 | 
			
		||||
    hwaddr len = 1;
 | 
			
		||||
    uint8_t *ind_addr;
 | 
			
		||||
 | 
			
		||||
    ind_addr = cpu_physical_memory_map(ind_loc, &len, 1);
 | 
			
		||||
    if (!ind_addr) {
 | 
			
		||||
        error_report("%s(%x.%x.%04x): unable to access indicator",
 | 
			
		||||
                     __func__, sch->cssid, sch->ssid, sch->schid);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    do {
 | 
			
		||||
        ind_old = *ind_addr;
 | 
			
		||||
        ind_new = ind_old | to_be_set;
 | 
			
		||||
    } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old);
 | 
			
		||||
    cpu_physical_memory_unmap(ind_addr, len, 1, len);
 | 
			
		||||
 | 
			
		||||
    return ind_old;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
 | 
			
		||||
{
 | 
			
		||||
    VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
 | 
			
		||||
@@ -872,9 +944,26 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
 | 
			
		||||
        if (!dev->indicators) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (sch->thinint_active) {
 | 
			
		||||
            /*
 | 
			
		||||
             * In the adapter interrupt case, indicators points to a
 | 
			
		||||
             * memory area that may be (way) larger than 64 bit and
 | 
			
		||||
             * ind_bit indicates the start of the indicators in a big
 | 
			
		||||
             * endian notation.
 | 
			
		||||
             */
 | 
			
		||||
            virtio_set_ind_atomic(sch, dev->indicators +
 | 
			
		||||
                                  (dev->ind_bit + vector) / 8,
 | 
			
		||||
                                  0x80 >> ((dev->ind_bit + vector) % 8));
 | 
			
		||||
            if (!virtio_set_ind_atomic(sch, dev->summary_indicator,
 | 
			
		||||
                                       0x01)) {
 | 
			
		||||
                css_adapter_interrupt(dev->thinint_isc);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            indicators = ldq_phys(&address_space_memory, dev->indicators);
 | 
			
		||||
            indicators |= 1ULL << vector;
 | 
			
		||||
            stq_phys(&address_space_memory, dev->indicators, indicators);
 | 
			
		||||
            css_conditional_io_interrupt(sch);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (!dev->indicators2) {
 | 
			
		||||
            return;
 | 
			
		||||
@@ -883,10 +972,8 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
 | 
			
		||||
        indicators = ldq_phys(&address_space_memory, dev->indicators2);
 | 
			
		||||
        indicators |= 1ULL << vector;
 | 
			
		||||
        stq_phys(&address_space_memory, dev->indicators2, indicators);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        css_conditional_io_interrupt(sch);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned virtio_ccw_get_features(DeviceState *d)
 | 
			
		||||
@@ -907,6 +994,7 @@ static void virtio_ccw_reset(DeviceState *d)
 | 
			
		||||
    css_reset_sch(dev->sch);
 | 
			
		||||
    dev->indicators = 0;
 | 
			
		||||
    dev->indicators2 = 0;
 | 
			
		||||
    dev->summary_indicator = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@
 | 
			
		||||
#define CCW_CMD_SET_IND      0x43
 | 
			
		||||
#define CCW_CMD_SET_CONF_IND 0x53
 | 
			
		||||
#define CCW_CMD_READ_VQ_CONF 0x32
 | 
			
		||||
#define CCW_CMD_SET_IND_ADAPTER 0x73
 | 
			
		||||
 | 
			
		||||
#define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device"
 | 
			
		||||
#define VIRTIO_CCW_DEVICE(obj) \
 | 
			
		||||
@@ -83,9 +84,12 @@ struct VirtioCcwDevice {
 | 
			
		||||
    bool ioeventfd_started;
 | 
			
		||||
    bool ioeventfd_disabled;
 | 
			
		||||
    uint32_t flags;
 | 
			
		||||
    uint8_t thinint_isc;
 | 
			
		||||
    /* Guest provided values: */
 | 
			
		||||
    hwaddr indicators;
 | 
			
		||||
    hwaddr indicators2;
 | 
			
		||||
    hwaddr summary_indicator;
 | 
			
		||||
    uint64_t ind_bit;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* virtual css bus type */
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,8 @@
 | 
			
		||||
 | 
			
		||||
#define SRP_RSP_SENSE_DATA_LEN  18
 | 
			
		||||
 | 
			
		||||
#define SRP_REPORT_LUNS_WLUN    0xc10100000000000ULL
 | 
			
		||||
 | 
			
		||||
typedef union vscsi_crq {
 | 
			
		||||
    struct viosrp_crq s;
 | 
			
		||||
    uint8_t raw[16];
 | 
			
		||||
@@ -719,12 +721,70 @@ static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vscsi_report_luns(VSCSIState *s, vscsi_req *req)
 | 
			
		||||
{
 | 
			
		||||
    BusChild *kid;
 | 
			
		||||
    int i, len, n, rc;
 | 
			
		||||
    uint8_t *resp_data;
 | 
			
		||||
    bool found_lun0;
 | 
			
		||||
 | 
			
		||||
    n = 0;
 | 
			
		||||
    found_lun0 = false;
 | 
			
		||||
    QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
 | 
			
		||||
        SCSIDevice *dev = SCSI_DEVICE(kid->child);
 | 
			
		||||
 | 
			
		||||
        n += 8;
 | 
			
		||||
        if (dev->channel == 0 && dev->id == 0 && dev->lun == 0) {
 | 
			
		||||
            found_lun0 = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!found_lun0) {
 | 
			
		||||
        n += 8;
 | 
			
		||||
    }
 | 
			
		||||
    len = n+8;
 | 
			
		||||
 | 
			
		||||
    resp_data = g_malloc0(len);
 | 
			
		||||
    memset(resp_data, 0, len);
 | 
			
		||||
    stl_be_p(resp_data, n);
 | 
			
		||||
    i = found_lun0 ? 8 : 16;
 | 
			
		||||
    QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
 | 
			
		||||
        DeviceState *qdev = kid->child;
 | 
			
		||||
        SCSIDevice *dev = SCSI_DEVICE(qdev);
 | 
			
		||||
 | 
			
		||||
        if (dev->id == 0 && dev->channel == 0) {
 | 
			
		||||
            resp_data[i] = 0;         /* Use simple LUN for 0 (SAM5 4.7.7.1) */
 | 
			
		||||
        } else {
 | 
			
		||||
            resp_data[i] = (2 << 6);  /* Otherwise LUN addressing (4.7.7.4)  */
 | 
			
		||||
        }
 | 
			
		||||
        resp_data[i] |= dev->id;
 | 
			
		||||
        resp_data[i+1] = (dev->channel << 5);
 | 
			
		||||
        resp_data[i+1] |= dev->lun;
 | 
			
		||||
        i += 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vscsi_preprocess_desc(req);
 | 
			
		||||
    rc = vscsi_srp_transfer_data(s, req, 0, resp_data, len);
 | 
			
		||||
    g_free(resp_data);
 | 
			
		||||
    if (rc < 0) {
 | 
			
		||||
        vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
 | 
			
		||||
        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
 | 
			
		||||
    } else {
 | 
			
		||||
        vscsi_send_rsp(s, req, 0, len - rc, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
 | 
			
		||||
{
 | 
			
		||||
    union srp_iu *srp = &req->iu.srp;
 | 
			
		||||
    SCSIDevice *sdev;
 | 
			
		||||
    int n, lun;
 | 
			
		||||
 | 
			
		||||
    if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN)
 | 
			
		||||
      && srp->cmd.cdb[0] == REPORT_LUNS) {
 | 
			
		||||
        vscsi_report_luns(s, req);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
 | 
			
		||||
    if (!sdev) {
 | 
			
		||||
        DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
 | 
			
		||||
/* config register */
 | 
			
		||||
#define R_CONFIG            (0x00 / 4)
 | 
			
		||||
#define IFMODE              (1 << 31)
 | 
			
		||||
#define IFMODE              (1U << 31)
 | 
			
		||||
#define ENDIAN              (1 << 26)
 | 
			
		||||
#define MODEFAIL_GEN_EN     (1 << 17)
 | 
			
		||||
#define MAN_START_COM       (1 << 16)
 | 
			
		||||
@@ -87,7 +87,7 @@
 | 
			
		||||
 | 
			
		||||
#define R_LQSPI_CFG         (0xa0 / 4)
 | 
			
		||||
#define R_LQSPI_CFG_RESET       0x03A002EB
 | 
			
		||||
#define LQSPI_CFG_LQ_MODE       (1 << 31)
 | 
			
		||||
#define LQSPI_CFG_LQ_MODE       (1U << 31)
 | 
			
		||||
#define LQSPI_CFG_TWO_MEM       (1 << 30)
 | 
			
		||||
#define LQSPI_CFG_SEP_BUS       (1 << 30)
 | 
			
		||||
#define LQSPI_CFG_U_PAGE        (1 << 28)
 | 
			
		||||
 
 | 
			
		||||
@@ -546,10 +546,10 @@ static int emulated_initfn(CCIDCardState *base)
 | 
			
		||||
        printf("%s: failed to initialize vcard\n", EMULATED_DEV_NAME);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    qemu_thread_create(&card->event_thread_id, event_thread, card,
 | 
			
		||||
                       QEMU_THREAD_JOINABLE);
 | 
			
		||||
    qemu_thread_create(&card->apdu_thread_id, handle_apdu_thread, card,
 | 
			
		||||
                       QEMU_THREAD_JOINABLE);
 | 
			
		||||
    qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread,
 | 
			
		||||
                       card, QEMU_THREAD_JOINABLE);
 | 
			
		||||
    qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread,
 | 
			
		||||
                       card, QEMU_THREAD_JOINABLE);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,7 @@ typedef uint64_t target_ulong;
 | 
			
		||||
#define EXCP_HLT        0x10001 /* hlt instruction reached */
 | 
			
		||||
#define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
 | 
			
		||||
#define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
 | 
			
		||||
#define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */
 | 
			
		||||
 | 
			
		||||
#define TB_JMP_CACHE_BITS 12
 | 
			
		||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
 | 
			
		||||
 
 | 
			
		||||
@@ -836,13 +836,13 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
 | 
			
		||||
                                    hwaddr offset);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * memory_region_present: translate an address/size relative to a
 | 
			
		||||
 * MemoryRegion into a #MemoryRegionSection.
 | 
			
		||||
 * memory_region_present: checks if an address relative to a @parent
 | 
			
		||||
 * translates into #MemoryRegion within @parent
 | 
			
		||||
 *
 | 
			
		||||
 * Answer whether a #MemoryRegion within @parent covers the address
 | 
			
		||||
 * @addr.
 | 
			
		||||
 *
 | 
			
		||||
 * @parent: a MemoryRegion within which @addr is a relative address
 | 
			
		||||
 * @parent: a #MemoryRegion within which @addr is a relative address
 | 
			
		||||
 * @addr: the area within @parent to be searched
 | 
			
		||||
 */
 | 
			
		||||
bool memory_region_present(MemoryRegion *parent, hwaddr addr);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,9 @@
 | 
			
		||||
#define HW_BOARDS_H
 | 
			
		||||
 | 
			
		||||
#include "sysemu/blockdev.h"
 | 
			
		||||
#include "sysemu/qemumachine.h"
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUMachine QEMUMachine;
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUMachineInitArgs {
 | 
			
		||||
    const QEMUMachine *machine;
 | 
			
		||||
    ram_addr_t ram_size;
 | 
			
		||||
@@ -24,6 +23,8 @@ typedef void QEMUMachineResetFunc(void);
 | 
			
		||||
 | 
			
		||||
typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
 | 
			
		||||
 | 
			
		||||
typedef int QEMUMachineGetKvmtypeFunc(const char *arg);
 | 
			
		||||
 | 
			
		||||
struct QEMUMachine {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *alias;
 | 
			
		||||
@@ -31,6 +32,7 @@ struct QEMUMachine {
 | 
			
		||||
    QEMUMachineInitFunc *init;
 | 
			
		||||
    QEMUMachineResetFunc *reset;
 | 
			
		||||
    QEMUMachineHotAddCPUFunc *hot_add_cpu;
 | 
			
		||||
    QEMUMachineGetKvmtypeFunc *kvm_type;
 | 
			
		||||
    BlockInterfaceType block_default_type;
 | 
			
		||||
    int max_cpus;
 | 
			
		||||
    unsigned int no_serial:1,
 | 
			
		||||
 
 | 
			
		||||
@@ -201,6 +201,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
    uint64_t addr, low = (uint64_t)-1, high = 0;
 | 
			
		||||
    uint8_t *data = NULL;
 | 
			
		||||
    char label[128];
 | 
			
		||||
    int ret = ELF_LOAD_FAILED;
 | 
			
		||||
 | 
			
		||||
    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
 | 
			
		||||
        goto fail;
 | 
			
		||||
@@ -211,23 +212,31 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
    switch (elf_machine) {
 | 
			
		||||
        case EM_PPC64:
 | 
			
		||||
            if (EM_PPC64 != ehdr.e_machine)
 | 
			
		||||
                if (EM_PPC != ehdr.e_machine)
 | 
			
		||||
                if (EM_PPC != ehdr.e_machine) {
 | 
			
		||||
                    ret = ELF_LOAD_WRONG_ARCH;
 | 
			
		||||
                    goto fail;
 | 
			
		||||
                }
 | 
			
		||||
            break;
 | 
			
		||||
        case EM_X86_64:
 | 
			
		||||
            if (EM_X86_64 != ehdr.e_machine)
 | 
			
		||||
                if (EM_386 != ehdr.e_machine)
 | 
			
		||||
                if (EM_386 != ehdr.e_machine) {
 | 
			
		||||
                    ret = ELF_LOAD_WRONG_ARCH;
 | 
			
		||||
                    goto fail;
 | 
			
		||||
                }
 | 
			
		||||
            break;
 | 
			
		||||
        case EM_MICROBLAZE:
 | 
			
		||||
            if (EM_MICROBLAZE != ehdr.e_machine)
 | 
			
		||||
                if (EM_MICROBLAZE_OLD != ehdr.e_machine)
 | 
			
		||||
                if (EM_MICROBLAZE_OLD != ehdr.e_machine) {
 | 
			
		||||
                    ret = ELF_LOAD_WRONG_ARCH;
 | 
			
		||||
                    goto fail;
 | 
			
		||||
                }
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            if (elf_machine != ehdr.e_machine)
 | 
			
		||||
            if (elf_machine != ehdr.e_machine) {
 | 
			
		||||
                ret = ELF_LOAD_WRONG_ARCH;
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pentry)
 | 
			
		||||
   	*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 | 
			
		||||
@@ -305,5 +314,5 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
			
		||||
 fail:
 | 
			
		||||
    g_free(data);
 | 
			
		||||
    g_free(phdr);
 | 
			
		||||
    return -1;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ Object *ich9_lpc_find(void);
 | 
			
		||||
#define ICH9_USB_UHCI1_DEV                      29
 | 
			
		||||
#define ICH9_USB_UHCI1_FUNC                     0
 | 
			
		||||
 | 
			
		||||
/* D30:F0 DMI-to-PCI brdige */
 | 
			
		||||
/* D30:F0 DMI-to-PCI bridge */
 | 
			
		||||
#define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE"
 | 
			
		||||
#define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,12 @@ int get_image_size(const char *filename);
 | 
			
		||||
int load_image(const char *filename, uint8_t *addr); /* deprecated */
 | 
			
		||||
int load_image_targphys(const char *filename, hwaddr,
 | 
			
		||||
                        uint64_t max_sz);
 | 
			
		||||
 | 
			
		||||
#define ELF_LOAD_FAILED       -1
 | 
			
		||||
#define ELF_LOAD_NOT_ELF      -2
 | 
			
		||||
#define ELF_LOAD_WRONG_ARCH   -3
 | 
			
		||||
#define ELF_LOAD_WRONG_ENDIAN -4
 | 
			
		||||
const char *load_elf_strerror(int error);
 | 
			
		||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
			
		||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
			
		||||
             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
			
		||||
@@ -43,10 +49,12 @@ void pstrcpy_targphys(const char *name,
 | 
			
		||||
                      hwaddr dest, int buf_size,
 | 
			
		||||
                      const char *source);
 | 
			
		||||
 | 
			
		||||
extern bool rom_file_in_ram;
 | 
			
		||||
extern bool option_rom_has_mr;
 | 
			
		||||
extern bool rom_file_has_mr;
 | 
			
		||||
 | 
			
		||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
			
		||||
                 hwaddr addr, int32_t bootindex);
 | 
			
		||||
                 hwaddr addr, int32_t bootindex,
 | 
			
		||||
                 bool option_rom);
 | 
			
		||||
void *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
			
		||||
                   hwaddr addr, const char *fw_file_name,
 | 
			
		||||
                   FWCfgReadCallback fw_callback, void *callback_opaque);
 | 
			
		||||
@@ -60,7 +68,7 @@ void *rom_ptr(hwaddr addr);
 | 
			
		||||
void do_info_roms(Monitor *mon, const QDict *qdict);
 | 
			
		||||
 | 
			
		||||
#define rom_add_file_fixed(_f, _a, _i)          \
 | 
			
		||||
    rom_add_file(_f, NULL, _a, _i)
 | 
			
		||||
    rom_add_file(_f, NULL, _a, _i, false)
 | 
			
		||||
#define rom_add_blob_fixed(_f, _b, _l, _a)      \
 | 
			
		||||
    rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -125,8 +125,8 @@ typedef struct Q35PCIHost {
 | 
			
		||||
#define MCH_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1)
 | 
			
		||||
#define MCH_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3)
 | 
			
		||||
 | 
			
		||||
#define MCH_HOST_BRDIGE_SMRAM                  0x9d
 | 
			
		||||
#define MCH_HOST_BRDIGE_SMRAM_SIZE             1
 | 
			
		||||
#define MCH_HOST_BRIDGE_SMRAM                  0x9d
 | 
			
		||||
#define MCH_HOST_BRIDGE_SMRAM_SIZE             1
 | 
			
		||||
#define MCH_HOST_BRIDGE_SMRAM_DEFAULT          ((uint8_t)0x2)
 | 
			
		||||
#define MCH_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6))
 | 
			
		||||
#define MCH_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5))
 | 
			
		||||
@@ -140,16 +140,16 @@ typedef struct Q35PCIHost {
 | 
			
		||||
#define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END  0x100000
 | 
			
		||||
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC                0x9e
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1))
 | 
			
		||||
#define MCH_HOST_BRDIGE_ESMRAMC_T_EN           ((uint8_t)1)
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1))
 | 
			
		||||
#define MCH_HOST_BRIDGE_ESMRAMC_T_EN           ((uint8_t)1)
 | 
			
		||||
 | 
			
		||||
/* D1:F0 PCIE* port*/
 | 
			
		||||
#define MCH_PCIE_DEV                           1
 | 
			
		||||
 
 | 
			
		||||
@@ -176,6 +176,8 @@ struct BusClass {
 | 
			
		||||
    void (*reset)(BusState *bus);
 | 
			
		||||
    /* maximum devices allowed on the bus, 0: no limit. */
 | 
			
		||||
    int max_dev;
 | 
			
		||||
    /* number of automatically allocated bus ids (e.g. ide.0) */
 | 
			
		||||
    int automatic_ids;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct BusChild {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include "hw/irq.h"
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "sysemu/qemumachine.h"
 | 
			
		||||
 | 
			
		||||
/* xen-machine.c */
 | 
			
		||||
enum xen_mode {
 | 
			
		||||
@@ -36,7 +37,7 @@ void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
 | 
			
		||||
 | 
			
		||||
qemu_irq *xen_interrupt_controller_init(void);
 | 
			
		||||
 | 
			
		||||
int xen_init(void);
 | 
			
		||||
int xen_init(QEMUMachine *machine);
 | 
			
		||||
int xen_hvm_init(MemoryRegion **ram_memory);
 | 
			
		||||
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -159,7 +159,7 @@ void qerror_report_err(Error *err);
 | 
			
		||||
    ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
 | 
			
		||||
 | 
			
		||||
#define QERR_KVM_MISSING_CAP \
 | 
			
		||||
    ERROR_CLASS_K_V_M_MISSING_CAP, "Using KVM without %s, %s unavailable"
 | 
			
		||||
    ERROR_CLASS_KVM_MISSING_CAP, "Using KVM without %s, %s unavailable"
 | 
			
		||||
 | 
			
		||||
#define QERR_MIGRATION_ACTIVE \
 | 
			
		||||
    ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress"
 | 
			
		||||
 
 | 
			
		||||
@@ -44,9 +44,37 @@ static inline void muls64(uint64_t *plow, uint64_t *phigh,
 | 
			
		||||
    *plow = r;
 | 
			
		||||
    *phigh = r >> 64;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
 | 
			
		||||
{
 | 
			
		||||
    if (divisor == 0) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        __uint128_t dividend = ((__uint128_t)*phigh << 64) | *plow;
 | 
			
		||||
        __uint128_t result = dividend / divisor;
 | 
			
		||||
        *plow = result;
 | 
			
		||||
        *phigh = dividend % divisor;
 | 
			
		||||
        return result > UINT64_MAX;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
 | 
			
		||||
{
 | 
			
		||||
    if (divisor == 0) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        __int128_t dividend = ((__int128_t)*phigh << 64) | *plow;
 | 
			
		||||
        __int128_t result = dividend / divisor;
 | 
			
		||||
        *plow = result;
 | 
			
		||||
        *phigh = dividend % divisor;
 | 
			
		||||
        return result != *plow;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
 | 
			
		||||
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
 | 
			
		||||
int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
 | 
			
		||||
int divs128(int64_t *plow, int64_t *phigh, int64_t divisor);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -52,12 +52,13 @@ void qemu_event_reset(QemuEvent *ev);
 | 
			
		||||
void qemu_event_wait(QemuEvent *ev);
 | 
			
		||||
void qemu_event_destroy(QemuEvent *ev);
 | 
			
		||||
 | 
			
		||||
void qemu_thread_create(QemuThread *thread,
 | 
			
		||||
void qemu_thread_create(QemuThread *thread, const char *name,
 | 
			
		||||
                        void *(*start_routine)(void *),
 | 
			
		||||
                        void *arg, int mode);
 | 
			
		||||
void *qemu_thread_join(QemuThread *thread);
 | 
			
		||||
void qemu_thread_get_self(QemuThread *thread);
 | 
			
		||||
bool qemu_thread_is_self(QemuThread *thread);
 | 
			
		||||
void qemu_thread_exit(void *retval);
 | 
			
		||||
void qemu_thread_naming(bool enable);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
#include "config-host.h"
 | 
			
		||||
#include "qemu/queue.h"
 | 
			
		||||
#include "qom/cpu.h"
 | 
			
		||||
#include "sysemu/qemumachine.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KVM
 | 
			
		||||
#include <linux/kvm.h>
 | 
			
		||||
@@ -152,7 +153,7 @@ extern KVMState *kvm_state;
 | 
			
		||||
 | 
			
		||||
/* external API */
 | 
			
		||||
 | 
			
		||||
int kvm_init(void);
 | 
			
		||||
int kvm_init(QEMUMachine *machine);
 | 
			
		||||
 | 
			
		||||
int kvm_has_sync_mmu(void);
 | 
			
		||||
int kvm_has_vcpu_events(void);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								include/sysemu/qemumachine.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								include/sysemu/qemumachine.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU Machine typedef
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright Alexander Graf <agraf@suse.de>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef QEMUMACHINE_H
 | 
			
		||||
#define QEMUMACHINE_H
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUMachine QEMUMachine;
 | 
			
		||||
 | 
			
		||||
#endif /* !QEMUMACHINE_H */
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "sysemu/qemumachine.h"
 | 
			
		||||
 | 
			
		||||
extern bool qtest_allowed;
 | 
			
		||||
 | 
			
		||||
@@ -26,7 +27,7 @@ static inline bool qtest_enabled(void)
 | 
			
		||||
 | 
			
		||||
bool qtest_driver(void);
 | 
			
		||||
 | 
			
		||||
int qtest_init_accel(void);
 | 
			
		||||
int qtest_init_accel(QEMUMachine *machine);
 | 
			
		||||
void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
 | 
			
		||||
 | 
			
		||||
static inline int qtest_available(void)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								kvm-all.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								kvm-all.c
									
									
									
									
									
								
							@@ -36,6 +36,8 @@
 | 
			
		||||
#include "qemu/event_notifier.h"
 | 
			
		||||
#include "trace.h"
 | 
			
		||||
 | 
			
		||||
#include "hw/boards.h"
 | 
			
		||||
 | 
			
		||||
/* This check must be after config-host.h is included */
 | 
			
		||||
#ifdef CONFIG_EVENTFD
 | 
			
		||||
#include <sys/eventfd.h>
 | 
			
		||||
@@ -1339,7 +1341,7 @@ static int kvm_max_vcpus(KVMState *s)
 | 
			
		||||
    return (ret) ? ret : kvm_recommended_vcpus(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_init(void)
 | 
			
		||||
int kvm_init(QEMUMachine *machine)
 | 
			
		||||
{
 | 
			
		||||
    static const char upgrade_note[] =
 | 
			
		||||
        "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
 | 
			
		||||
@@ -1356,7 +1358,8 @@ int kvm_init(void)
 | 
			
		||||
    KVMState *s;
 | 
			
		||||
    const KVMCapabilityInfo *missing_cap;
 | 
			
		||||
    int ret;
 | 
			
		||||
    int i;
 | 
			
		||||
    int i, type = 0;
 | 
			
		||||
    const char *kvm_type;
 | 
			
		||||
 | 
			
		||||
    s = g_malloc0(sizeof(KVMState));
 | 
			
		||||
 | 
			
		||||
@@ -1420,18 +1423,25 @@ int kvm_init(void)
 | 
			
		||||
                    nc->name, nc->num, soft_vcpus_limit);
 | 
			
		||||
 | 
			
		||||
            if (nc->num > hard_vcpus_limit) {
 | 
			
		||||
                ret = -EINVAL;
 | 
			
		||||
                fprintf(stderr, "Number of %s cpus requested (%d) exceeds "
 | 
			
		||||
                        "the maximum cpus supported by KVM (%d)\n",
 | 
			
		||||
                        nc->name, nc->num, hard_vcpus_limit);
 | 
			
		||||
                goto err;
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        nc++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
 | 
			
		||||
    if (machine->kvm_type) {
 | 
			
		||||
        type = machine->kvm_type(kvm_type);
 | 
			
		||||
    } else if (kvm_type) {
 | 
			
		||||
        fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        ret = kvm_ioctl(s, KVM_CREATE_VM, 0);
 | 
			
		||||
        ret = kvm_ioctl(s, KVM_CREATE_VM, type);
 | 
			
		||||
    } while (ret == -EINTR);
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "sysemu/kvm.h"
 | 
			
		||||
#include "sysemu/qemumachine.h"
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_USER_ONLY
 | 
			
		||||
#include "hw/pci/msi.h"
 | 
			
		||||
@@ -34,7 +35,7 @@ int kvm_init_vcpu(CPUState *cpu)
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_init(void)
 | 
			
		||||
int kvm_init(QEMUMachine *machine)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -269,7 +269,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
 | 
			
		||||
    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
 | 
			
		||||
    /* launch the event_thread. This will trigger reader adds for all the
 | 
			
		||||
     * existing readers */
 | 
			
		||||
    qemu_thread_create(&thread_id, event_thread, NULL, 0);
 | 
			
		||||
    qemu_thread_create(&thread_id, "vsc/event", event_thread, NULL, 0);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user