There is an undocumented obscure argument to the uvm_reg::read and write functions called extension which is of type uvm_object. It defaults to NULL. While not documented in the class reference manual, the comment in the code stipulates it can be used to for user defined extensions to the read/write calls.
I have successfully implemented a burst read using this argument (for a spi protocol agent). The call is the same (register.read) but i pass the extra extension argument. I created a class called burst_extension which contains the burst size and a queue of data to be filled from the spi bus (could be used for writes as well) and a burst size. Assuming you are using a uvm_reg_adapter, the adapter can retrieve the current uvm_reg_item by calling this.get_item() inside the reg2bus routine (can't do it inside bus2reg). Magically, the reg_item object contains a handle to the extension object From there I can access the extension which contains the burst size and the data. I can then translate it appropriately into a burst operation on the bus.
From the user's point of view, it is nice because burst calls are simply the read/write calls with an extra argument. The adapter can get a little messy, but it is one-time pain and abstracted from other users.
I'd be happy to provide more details.